JS用イベントドリブン実装に必須EventDispatcher作ったよ(this固定機能付)
必要になったので作ってみた。
this固定してdispatchできるよ!
ちゃちゃっとさっき作ったばっかなので、ほとんどテストしてません・・・
多分平気!
とりあえずFireFoxで必要だったのでIEとかでは動かしてもないので動かないかも。
Class.create();の部分だけprototype.js使ってるので、prototype.jsつかってなければ書き換えてください。
コード
//EventDispatcher.js /** * EventDispatcher * @author kaw */ var EventDispatcher = Class.create(); EventDispatcher.prototype = { /** * * @type Array */ _targetList:null, /** * Constructor * @param {} subClassInstance * @usage * new EventDispatcher( this ); */ initialize:function( subClassInstance ){ this._targetList = new Array(); var reference = this; subClassInstance.dispatchEvent = function( ){ reference.dispatchEvent.apply( reference , arguments ); } subClassInstance.addEventListener = function( ){ reference.addEventListener.apply( reference , arguments ); } subClassInstance.removeEventListener = function( ){ reference.removeEventListener.apply( reference , arguments ); } }, /** * イベントを発行します. * @param String event * @param {} broadCastObject * @usage * this.dispatchEvent( "change" , { id:1212 , type:"AAAA" } ); */ dispatchEvent:function( event , broadCastObject ){ if( this._targetList[event] == undefined ){ return; } var list = this._targetList[event]; var len = list.length; for( var i = 0 ; i < len ; i++ ){ var o = list[i]; var handler = o['handler']; var ref = o['ref']; if( ref == undefined ){ handler( broadCastObject ); }else{ handler.apply( ref , [ broadCastObject ] ); } } }, /** * イベントを追加します. * @param String event * @param Function handler * @param {} ref 必須ではありませんが指定すると、コールバック先のthis参照がrefで固定されます. * @usage * target.addEventListener( "change" , this._onChanged , this ); */ addEventListener:function( event , handler , ref ){ if( this._targetList[event] == undefined ){ this._targetList[event] = new Array(); } /* var list = this._targetList[event]; var len = list.length; for( var i = 0 ; i < len ; i++ ){ var o = list[i]; var _handler = o['handler']; if( _handler == handler ){ //登録済み. return; } } */ this.removeEventListener( event , handler ); this._targetList[event].push( { handler:handler , ref:ref } ); }, /** * イベントを削除します. * @param String event * @param Function handler * @usage * target.removeEventListener( "change" , this._onChanged ); */ removeEventListener:function( event , handler ){ if( this._targetList[event] == undefined ){ return; } var list = this._targetList[event]; var len = list.length; for( var i = 0 ; i < len ; i++ ){ var o = list[i]; var _handler = o['handler']; if( _handler == handler ){ list.splice( i , 1 );//delete return; } } } } /** * EventDispatcherに対象のオブジェクトを追加します. * @param {} obj * @usage * EventDispatcher.register( this ); */ EventDispatcher.register = function( obj ){ return new EventDispatcher( obj ); }
使い方
var TestEventDispatcher = Class.create(); TestEventDispatcher.prototype = { initialize:function(){ //イベントDispatcherに登録 EventDispatcher.register( this ); }, callTestDummyEvent:function(){ //イベントのdispatch this.dispatchEvent( "testDummyEvent" , ">>>ここにはオブジェクトとかdispatch先の引数に渡したいものを指定できますよ!" ); } } var Test = Class.create(); Test.prototype = { _member:null, initialize:function( value ){ this._member = value; var testEventDispatcher = new TestEventDispatcher(); //リスナーの登録 //第三引数にコールバック先でthisを固定する参照を渡すことができます testEventDispatcher.addEventListener( "testDummyEvent" , this._onChanged , this ); //Test!! testEventDispatcher.callTestDummyEvent(); }, _onChanged:function( event ){ alert( "値のdispatchできてる?? >> " + event );//値のdispatchできてる?? >> ここにはオブジェクトとかdispatch先の引数に渡したいものを指定できますよ! alert( "thisとおってる?? >> " + this._member );//thisとおってる?? >> Hello! } } new Test( "Hello!" );