2012-06-11 17 views
9

Was ich haben will, ist ein benutzerdefiniertes Objekt, das einige Ereignisse zur Verfügung stellt. Zum Beispiel:Implementierung von Ereignissen in meinem eigenen Objekt

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); 
    } 
} 

Der Code um das Ereignis verwenden würde wie folgt aussehen:

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

Wie Sie ... die Standard Möglichkeit der Verwendung von Ereignissen in JS zu sehen. Aber ich kann es nicht worling machen ...

Derzeit ist mein Problem, dass mein Objekt nicht "addEventListener" und "dispatchEvent" implementieren. Aber diese Funktionen sind normalerweise von „Element“ implementiert ...

Kann ich sie irgendwie zugänglich zu machen oder muss ich sie für meine eigene implementieren? Wie muss ich sie umsetzen? Muss ich mein eigenes Eventhandling implementieren? (Eine interne Liste der Handler mit, ein „add“ - und „Entfernen“ -Handler Funktion und jeden Handler ausgelöst, wenn ich das Ereignis ausgelöst will)

Grüße!

+0

I don t wissen, ob das hilft, aber Backbone.js Ereignisse in sie aufgebaut hat. Jedes mit ihm erstellte Modell kann benutzerdefinierte Ereignisse mit der Syntax 'object.trigger (event_name) 'auslösen. – Deeptechtons

+0

Es ist auch einfach mit jQuery ... deshalb habe ich es gelernt, kann nicht so schwer sein: P $ (_ this) .trigger (CustomObjectTextChangedEventName , _text); $ (myCustomObject) .bind (CustomObjectTextChangedEventName, handleTextChanged); –

Antwort

15

addEventListener Die Funktion ist eine Methode der Element Klasse. Eine Möglichkeit ist, CustomObject vererben Element so zu machen:

CustomObject.prototype = Element.prototype; 

Das Problem ist, dass Element Klasse verschiedene Implementierungen unter verschiedenen Browsern haben. So ist es beispielsweise nicht einfach, Feuer zu veranstalten (siehe this post).

Also ich Rat dies selbst zu tun. Es ist nicht schwer, versuchen, etwas wie folgt aus:

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); 
     } 
    }; 
} 

Jetzt, da es so einfach mit:

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

Dies ist eine grundlegende Lösung. Vielleicht möchten Sie es ändern, aber ich denke, Sie sollten die Idee verstehen.

+0

Das ist, was ich habe mit "eine interne Liste von Handlern, eine" hinzufügen "- und" entfernen "-Handler-Funktion, und feuern Sie jeden Handler, wenn ich das Ereignis auslösen möchte" =) Danke! –

+0

@DominikKirschenhofer Cool. Ich habe den 'remove'-Handler vergessen, also habe ich ihn gerade hinzugefügt. Es sollte funktionieren. :) – freakish

+1

In Bezug auf die "trickreiche" Teil - Entfernen von Handlern durch die Übergabe der gleichen Funktion Objekt: das gleiche gilt für native Event Handler. Ich habe gerade ein Button 'click' Event getestet, und' removeEventListener' hat nicht funktioniert, es sei denn, ich habe einen Verweis auf das gleiche Funktionsobjekt bereitgestellt. – GolfWolf

1

ich auf all 100% bin nicht sicher, aber die nächste ist ein Ergebnis meiner alten Forschung innerhalb dieses Problems:

  • Sie nicht die irgendwie zur Verfügung stellen können.
  • Sie können einfach Ihre eigene Logik implementieren. Dazu können Sie Code verwenden, der in MDN element.removeEventListener Artikel mit kleinen Änderungen vorhanden ist. Darunter \ Vergangenheit des Codes von MDN Link kopieren:

// 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); } 
    } 
    }; 
} 
  • Ich denke, was alles, was Sie ändern müssen, ist Element.prototype mit CustomObject.prototype zu ersetzen. Und zur Unterstützung dispathEvent müssen Sie CustomObject.prototype.dispatchEvent = runListener; Codezeile hinzufügen. Auch kann es besser sein, diesen Code in die Closure-Funktion einzuschließen;

Ich habe dies nicht in meinen Apps getestet, aber vielleicht kann Ihnen das helfen.

UPDATE: Next Anlenkpunkte in Codequelle, die XObject() Klasse enthält, die Ereignisse Ereignis Hinzufügen/Entfernen und Dispatching unterstützt. Testbeispiel ist enthalten. Der gesamte Code basiert auf der obigen Antwort. http://jsfiddle.net/8jZrR/

+0

@Dominik Kirschenhofer, siehe Link in ** UPDATE: ** Absatz –

+0

COOL! Vielen Dank! –

1

Ich habe meine Probe mit dem Code von freakish verbessert. Ich würde immer noch den Eventhandling-Teil in eine "Basisklasse" extrahieren ... vielleicht, wenn es noch etwas Zeit gibt =)

Es gibt auch ein Beispiel für die Verwendung von 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> 

Verwandte Themen