Implémentation d'événements dans mon propre objet

Ce que je veux avoir est un objet personnalisé qui fournit certains événements. Par exemple:

var CustomObjectTextChangedEventName = 'textChanged'; var CustomObject = function () { var _this = this; var _text = ""; _this.OnTextChanged = document.createEvent("Event"); _this.OnTextChanged.initEvent(CustomObjectTextChangedEventName, true, false); _this.ChangeText = function (newText) { _text = newText; fireTextChanged(); }; function fireTextChanged() { _this.dispatchEvent(_this.OnTextChanged); } } 

Le code pour utiliser l'événement ressemblerait à:

 myCustomObject = new CustomObject(); myCustomObject.addEventListener(CustomObjectTextChangedEventName, handleTextChanged, false); 

Comme vous pouvez le voir … la manière par défaut d'utiliser les événements dans JS. Mais je ne peux pas gêner …

Actuellement, mon problème est que mon objet ne met pas en œuvre "addEventListener" et "dispatchEvent". Mais ces fonctions sont normalement mises en œuvre à partir de "l'élément" …

Puis-je les rendre disponibles de quelque façon ou dois-je les mettre en œuvre pour la mienne? Comment les mettre en œuvre? Dois-je mettre en œuvre ma propre gestion d'événement? (Avoir une liste interne de gestionnaires, une fonction "add" – et "supprimer" -handler, et déclencher chaque gestionnaire lorsque je veux déclencher l'événement)

Salutations!

La fonction addEventListener est une méthode de classe Element . L'une des façons est de rendre CustomObject hériter d' Element comme ceci:

 CustomObject.prototype = Element.prototype; 

Le problème est que la classe Element peut avoir des implémentations différentes parmi les différents navigateurs. Ainsi, par exemple, les événements de tir peuvent ne pas être faciles (voir cette publication ).

Donc, je conseille de le faire par vous-même. Ce n'est pas difficile, essayez quelque chose comme ceci:

 var CustomObject = function () { var _this = this; _this.events = {}; _this.addEventListener = function(name, handler) { if (_this.events.hasOwnProperty(name)) _this.events[name].push(handler); else _this.events[name] = [handler]; }; _this.removeEventListener = function(name, handler) { /* This is a bit tricky, because how would you identify functions? This simple solution should work if you pass THE SAME handler. */ if (!_this.events.hasOwnProperty(name)) return; var index = _this.events[name].indexOf(handler); if (index != -1) _this.events[name].splice(index, 1); }; _this.fireEvent = function(name, args) { if (!_this.events.hasOwnProperty(name)) return; if (!args || !args.length) args = []; var evs = _this.events[name], l = evs.length; for (var i = 0; i < l; i++) { evs[i].apply(null, args); } }; } 

Maintenant, l'utiliser est aussi simple que:

 var co = new CustomObject(); co.addEventListener('textChange', function(name) { console.log(name); }); co.fireEvent('textChange', ['test']); 

C'est une solution de base. Vous voudrez peut-être le modifier, mais je pense que vous devez saisir l'idée.

Je ne suis pas sûr de tous les 100%, mais le résultat est le résultat de mon ancienne recherche dans ce problème:

  • Vous ne pouvez pas mettre à disposition, en quelque sorte, cela.
  • Vous pouvez simplement mettre en œuvre votre propre logique. Pour cela, vous pouvez utiliser le code existant dans l' élément MDN element.removeEventListener avec peu de modifications. Ci-dessous copier \ passé du code du lien MDN:

 // code source: MDN: https://developer.mozilla.org/en/DOM/element.removeEventListener // without changes if (!Element.prototype.addEventListener) { var oListeners = {}; function runListeners(oEvent) { if (!oEvent) { oEvent = window.event; } for (var iLstId = 0, iElId = 0, oEvtListeners = oListeners[oEvent.type]; iElId < oEvtListeners.aEls.length; iElId++) { if (oEvtListeners.aEls[iElId] === this) { for (iLstId; iLstId < oEvtListeners.aEvts[iElId].length; iLstId++) { oEvtListeners.aEvts[iElId][iLstId].call(this, oEvent); } break; } } } Element.prototype.addEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) { if (oListeners.hasOwnProperty(sEventType)) { var oEvtListeners = oListeners[sEventType]; for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) { if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; } } if (nElIdx === -1) { oEvtListeners.aEls.push(this); oEvtListeners.aEvts.push([fListener]); this["on" + sEventType] = runListeners; } else { var aElListeners = oEvtListeners.aEvts[nElIdx]; if (this["on" + sEventType] !== runListeners) { aElListeners.splice(0); this["on" + sEventType] = runListeners; } for (var iLstId = 0; iLstId < aElListeners.length; iLstId++) { if (aElListeners[iLstId] === fListener) { return; } } aElListeners.push(fListener); } } else { oListeners[sEventType] = { aEls: [this], aEvts: [ [fListener] ] }; this["on" + sEventType] = runListeners; } }; Element.prototype.removeEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) { if (!oListeners.hasOwnProperty(sEventType)) { return; } var oEvtListeners = oListeners[sEventType]; for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) { if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; } } if (nElIdx === -1) { return; } for (var iLstId = 0, aElListeners = oEvtListeners.aEvts[nElIdx]; iLstId < aElListeners.length; iLstId++) { if (aElListeners[iLstId] === fListener) { aElListeners.splice(iLstId, 1); } } }; } 
  • Je pense que tout ce que vous devez changer est de remplacer Element.prototype par CustomObject.prototype . Et pour soutenir dispathEvent vous devez ajouter CustomObject.prototype.dispatchEvent = runListener; Ligne de code. En outre, il est préférable d'inclure ce code dans la fonction de fermeture;

Je n'ai pas testé cela dans mes applications, mais peut-être que cela peut vous aider.

MISE À JOUR: Les liens suivants XObject() source de code qui contient la classe XObject() qui prend en charge l'ajout d'événements / suppression et l'envoi d'événements. L'exemple de test est inclus. Tout le code est basé sur la réponse ci-dessus. http://jsfiddle.net/8jZrR/

J'ai amélioré mon échantillon avec le code de freakish. Je voudrais encore extraire la partie de gestion d'événement en une "classe de base" … peut-être quand il y a plus de temps =)

Il existe également un exemple pour utiliser jQuery!

 <!doctype html> <html lang="en"> <head> <title>Custom Events Test</title> <meta charset="utf-8"> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script> <script> /* jQuery var CustomObjectTextChangedEventName = 'textChanged'; var CustomObject = function () { var _this = this; var _text = ""; _this.ChangeText = function (newText) { _text = newText; fireTextChanged(); }; function fireTextChanged() { $(_this).trigger(CustomObjectTextChangedEventName, _text); } } var myCustomObject; $(document).ready(function () { myCustomObject = new CustomObject(); $(myCustomObject).bind(CustomObjectTextChangedEventName, handleTextChanged); }) function handleTextChanged(event, msg) { window.alert(msg); } function buttonClick() { var newText = document.getElementById('tbText').value; myCustomObject.ChangeText(newText); } */ var CustomObjectTextChangedEventName = 'textChanged'; var CustomObject = function (alias) { var _this = this; var _events = {}; var _text = ""; _this.Alias = alias; _this.OnTextChanged = document.createEvent("Event"); _this.OnTextChanged.initEvent(CustomObjectTextChangedEventName, true, false); _this.ChangeText = function (newText) { var args = new TextChangedEventArgs(); args.OldText = _text; args.NewText = newText; _text = newText; fireEvent(CustomObjectTextChangedEventName, args); }; _this.addEventListener = function (name, handler) { if (_events.hasOwnProperty(name)) _events[name].push(handler); else _events[name] = [handler]; }; _this.removeEventListener = function (name, handler) { /* This is a bit tricky, because how would you identify functions? This simple solution should work if you pass THE SAME handler. */ if (!_events.hasOwnProperty(name)) return; var index = _events[name].indexOf(handler); if (index != -1) _events[name].splice(index, 1); }; function fireEvent(name, args) { if (!_events.hasOwnProperty(name)) return; var evs = _events[name], l = evs.length; for (var i = 0; i < l; i++) { evs[i](_this, args); } } } var TextChangedEventArgs = function () { var _this = this; _this.OldText = null; _this.NewText = null; } var myCustomObject; var myCustomObject2; window.onload = function () { myCustomObject = new CustomObject("myCustomObject"); myCustomObject.addEventListener(CustomObjectTextChangedEventName, handleTextChanged); myCustomObject2 = new CustomObject("myCustomObject2"); myCustomObject2.addEventListener(CustomObjectTextChangedEventName, handleTextChanged); }; function handleTextChanged(sender, args) { window.alert('At ' + sender.Alias + ' from [' + args.OldText + '] to [' + args.NewText + ']'); } function buttonClick() { var newText = document.getElementById('tbText').value; myCustomObject.ChangeText(newText); } function buttonClick2() { var newText = document.getElementById('tbText2').value; myCustomObject2.ChangeText(newText); } </script> </head> <body> <input type="text" id="tbText" /> <input type="button" value="Change" onclick="buttonClick();" /> <input type="text" id="tbText2" /> <input type="button" value="Change" onclick="buttonClick2();" /> </body>