/**\r
+ * X.EventDispatcher\r
+ * \r
+ * 1. as3 の EventDispatcher ライクなクラス。そのまま使ったり、継承したり。コールバック中にイベントを追加したら?削除したら?にも対処している。\r
+ * 2. _rawObject メンバがいる場合、addEventListener, attachEvent, on 等で生のブラウザオブジェクトにリスナを登録する。\r
+ * window, document, HTMLElement, Image, XHR などが _rawObject\r
+ * \r
* use X.Callback\r
* \r
* https://developer.mozilla.org/ja/docs/Web/API/EventTarget.addEventListener\r
BEFORE_CANCEL : 5,\r
CANCELED : 6,\r
TIMEOUT : 7,\r
+ // INSTANCE_KILLED\r
+ // KILL_INSTANCE_CANCELED\r
_LAST_EVENT : 7\r
};\r
\r
+// --- define / local variables ----------------------------\r
+var x_eventdispatcher_once = false,\r
+ x_eventdispatcher_needsIndex = false,\r
+ x_eventdispatcher_temp = {};\r
+\r
+if( X.UA.MacIE ){\r
+ x_eventdispatcher_temp.DOM_W3C = true;\r
+ x_eventdispatcher_temp.EVENT_DOM0 = true;\r
+} else\r
+if( X.UA.IE4 ){ // ie4 & iemobi4\r
+ x_eventdispatcher_temp.DOM_IE4 = true;\r
+ x_eventdispatcher_temp.EVENT_DOM0 = true;\r
+} else\r
+if( document.getElementById ){\r
+ x_eventdispatcher_temp.DOM_W3C = true;\r
+ if( document.addEventListener ){\r
+ x_eventdispatcher_temp.EVENT_W3C = true;\r
+ } else\r
+ if( document.attachEvent ){\r
+ x_eventdispatcher_temp.EVENT_IE = true;\r
+ } else {\r
+ x_eventdispatcher_temp.EVENT_DOM0 = true;\r
+ };\r
+} else\r
+if( document.all ){\r
+ x_eventdispatcher_temp.DOM_IE4 = true;\r
+ x_eventdispatcher_temp.EVENT_DOM0 = true;\r
+} else\r
+if( document.layers ){\r
+ \r
+} else {\r
+ \r
+};\r
\r
+/**\r
+ * イベントターゲットをラップする場合(widnow, document, Image, XHR 等)、通常は new 時に渡します。参照:コンストラクタ実体 {@link X.EventDispatcher.Constructor}\r
+ * アプリケーション独自のイベントをやり取りしたいだけ、という場合、イベントターゲットは不要です。\r
+ * @constructor\r
+ * @classdesc EventTarget オブジェクトをラップしたり、アプリケーションで独自に定義したイベントを発信するためのクラスです。\r
+ * listen, unlisten, dispatch という addEventListener, removeEventListener, dispatchEvent に対応する関数を持ちます。さらに listening という as3 の hasEventListener に相当する関数を持ちます。\r
+ * as3 の EventDispatcher に相当する機能に加え、イベントターゲットオブジェクト(widnow, document, HTMLElement, XHR 等)が設定されていた場合に、それらへ実際のイベント登録・解除も行います。\r
+ * このイベントの登録・解除はクロスブラウザ対策が施されていて、IE5~8の独自イベントの差異を吸収し、DOM0 に対しても複数のイベントリスナを登録します。\r
+ * さらに、コールバックに対して、this コンテキストや、追加の引数を指定できます。 this コンテキストを指定しなかった場合、EventDispatcher インスタンスがコールバック関数の this になります。 \r
+ * @param {object=} opt_argument \r
+ */\r
X.EventDispatcher =\r
X.Class.create(\r
'EventDispatcher',\r
{\r
+\r
+ /**\r
+ * @namespace\r
+ * @memberof X.EventDispatcher\r
+ */\r
+\r
+ /**\r
+ * イベントリスナをイベント名(string)や数値(1~,フレームワーク内で定義)をキーとするArrayで記憶します。\r
+ * Arrayには、{k:種類,x:コンテキスト(thisObject),f:関数,s:サプリメントする引数の配列} というハッシュ、または関数が蓄えられています。\r
+ * @private\r
+ * @type {Object.<(number|string), Array.<(callbackDef|function)>>}\r
+ */\r
_listeners : null,\r
- _dispatching : 0, // dispatch 中の unlisten で使用\r
- _unlistens : null, // dispatch 中の unlisten で使用\r
- _needsIndex : false, // listening で index を返す\r
- _reserves : null,\r
+\r
+ /**\r
+ * _rawObject には HTMLElement, window, document, XHR といったイベントターゲットオブジェクトを設定します。\r
+ * _rawObject が設定されていると on(), off() 時に addEventListener(DOM Level2) や detachEvent(ie5~8), on~(DOM0) 等を操作します。\r
+ * _rawObject は最初の on() 前に設定しておかないと addEventListener 等が意図したように行われません。\r
+ * X.Dom.Node では非同期に HTMLElement を生成していて、要素生成以前に on, off を呼び出すことができます。これは適宜に migrateEvent, restoreEvent を呼んで解決しているためです。\r
+ * @private\r
+ * @type {Object}\r
+ */\r
+ _rawNode : null,\r
+ _handleEvent : null,\r
+ \r
+ _dispatching : 0, // dispatch 中の unlisten で使用\r
+ _unlistens : null, // dispatch 中の unlisten で使用\r
+ _reserves : null, // dispatch中に unlisten されたイベントリスナ\r
_killReserved : false,\r
\r
- listen : function( type, arg1, arg2, arg3 ){\r
- var list = this._listeners,\r
- i, r, f;\r
- if( this._dispatching ){\r
- if( !this._reserves ) this._reserves = [];\r
- this._reserves[ this._reserves.length ] = [ type, arg1, arg2, arg3, X.EventDispatcher._once ];\r
- return this;\r
- };\r
- \r
- if( X.Type.isArray( type ) ){\r
- for( i = type.length; i; ){\r
- this.listen( type[ --i ], arg1, arg2, arg3 );\r
- };\r
- return this;\r
+ /**\r
+ * X.EventDispatcher のコンストラクタの実体。\r
+ * @private\r
+ * @this {X.EventDispatcher}\r
+ */\r
+ Constructor : function( rawObject ){\r
+ if( rawObject ){\r
+ this._rawNode = rawObject;\r
};\r
- \r
- if( this.listening( type, arg1, arg2, arg3 ) ) return this;\r
-\r
- if( !list ) list = this._listeners = {};\r
- if( !( list = list[ type ] ) ) list = this._listeners[ type ] = [];\r
- \r
- f = X.Callback._classifyCallbackArgs( arg1, arg2, arg3, this );\r
- list[ list.length ] = f;\r
- f.once = X.EventDispatcher._once;\r
- \r
- return this;\r
},\r
+\r
+ /**\r
+ * \r
+ * @this {X.EventDispatcher}\r
+ */\r
+ on : x_eventdispatcher_on,\r
+ listen : x_eventdispatcher_on,\r
+ \r
listenOnce : function( type, arg1, arg2, arg3 ){\r
- X.EventDispatcher._once = true;\r
+ x_eventdispatcher_once = true;\r
this.listen( type, arg1, arg2, arg3 );\r
- X.EventDispatcher._once = false;\r
- return this;\r
- },\r
- unlisten : function( type, arg1, arg2, arg3 ){\r
- var list = this._listeners,\r
- _list, reserves, unlistens, i, f;\r
- if( !list ) return this;\r
- \r
- if( X.Type.isArray( type ) ){\r
- for( i = type.length; i; ){\r
- this.unlisten( type[ --i ], arg1, arg2, arg3 );\r
- };\r
- return this;\r
- };\r
- \r
- if( type === undefined ){\r
- // 全て削除\r
- for( type in list ){\r
- _list = list[ type ];\r
- for( i = _list.length; i; ){\r
- this.unlisten( type, _list[ --i ] ); // override されていることがあるので、必ず unlisten を使用\r
- };\r
- // this.unlisten( type ); これは無茶!\r
- };\r
- return this;\r
- } else\r
- if( arg1 === undefined ){\r
- // 同一タイプを全て削除\r
- if( _list = list[ type ] ){\r
- for( i = _list.length; i; ){\r
- this.unlisten( type, _list[ --i ] ); // override されていることがあるので、必ず unlisten を使用\r
- };\r
- };\r
- return this;\r
- } else\r
- if( reserves = this._reserves ){\r
- for( i = reserves.length; i; ){\r
- f = reserves[ --i ];\r
- if( f[ 0 ] === type && f[ 1 ] === arg1 && f[ 2 ] === arg2 && f[ 3 ] === arg3 ){\r
- reserves.splice( i, 1 );\r
- if( !reserves.legth ) delete this._reserves;\r
- return this;\r
- };\r
- };\r
- };\r
- \r
- this._needsIndex = true;\r
- i = this.listening( type, arg1, arg2, arg3 );\r
- delete this._needsIndex;\r
- if( i === false ) return this;\r
-\r
- f = ( _list = list[ type ] )[ i ];\r
- if( unlistens = this._unlistens ){\r
- ( unlistens = unlistens[ type ] ) ?\r
- ( unlistens[ unlistens.length ] = f ) :\r
- ( this._unlistens[ type ] = [ f ] );\r
- } else {\r
- delete f.once;\r
- f.kill === X.Callback._kill && f.kill();\r
- _list.splice( i, 1 );\r
- if( !_list.length ){\r
- delete this._listeners[ type ];\r
- if( X.isEmptyObject( this._listeners ) ) delete this._listeners;\r
- };\r
- };\r
+ x_eventdispatcher_once = false;\r
return this;\r
},\r
+ \r
+ off : x_eventdispatcher_off,\r
+ unlisten : x_eventdispatcher_off,\r
+ \r
listening : function( type, arg1, arg2, arg3 ){\r
var list = this._listeners, unlistens, i, f, hash;\r
if( type === undefined ) return !!list;\r
};\r
for( i = list.length; i; ){\r
f = list[ --i ];\r
- if( f === hash || ( f.x === hash.x && f.f === hash.f && f.s === hash.s ) ) return this._needsIndex ? i : true;\r
+ if( f === hash || ( f.x === hash.x && f.f === hash.f && f.s === hash.s ) ) return x_eventdispatcher_needsIndex ? i : true;\r
};\r
return false;\r
},\r
if( list = this._reserves ){\r
for( i = 0, l = list.length; i < l; ++i ){\r
f = list[ i ];\r
- X.EventDispatcher._once = f[ 4 ];\r
+ x_eventdispatcher_once = f[ 4 ];\r
this.listen( f[ 0 ], f[ 1 ], f[ 2 ], f[ 3 ] );\r
- X.EventDispatcher._once = false;\r
+ x_eventdispatcher_once = false;\r
f.length = 0;\r
};\r
list.length = 0;\r
}\r
);\r
\r
-X.EventDispatcher.prototype.on = X.EventDispatcher.prototype.listen;\r
-X.EventDispatcher.prototype.off = X.EventDispatcher.prototype.unlisten;\r
\r
-X.EventDispatcher._once = false;\r
+// --- implements ------------------------------------------\r
+function x_eventdispatcher_on( type, arg1, arg2, arg3 ){\r
+ var list = this._listeners,\r
+ i, r, f;\r
+ \r
+ if( this._dispatching ){\r
+ if( !this._reserves ) this._reserves = [];\r
+ this._reserves[ this._reserves.length ] = [ type, arg1, arg2, arg3, x_eventdispatcher_once ];\r
+ return this;\r
+ };\r
+ \r
+ if( X.Type.isArray( type ) ){\r
+ for( i = type.length; i; ){\r
+ this.listen( type[ --i ], arg1, arg2, arg3 );\r
+ };\r
+ return this;\r
+ };\r
+ \r
+ ( !list || !list[ type ] ) && X.Type.isString( type ) && x_eventdispatcher_actualAddEvent( this, type );\r
+ \r
+ if( this.listening( type, arg1, arg2, arg3 ) ) return this;\r
+\r
+ if( !list ) list = this._listeners = {};\r
+ if( !( list = list[ type ] ) ) list = this._listeners[ type ] = [];\r
+ \r
+ f = X.Callback._classifyCallbackArgs( arg1, arg2, arg3, this );\r
+ list[ list.length ] = f;\r
+ f.once = x_eventdispatcher_once;\r
+ \r
+ return this;\r
+};\r
+\r
+function x_eventdispatcher_off( type, arg1, arg2, arg3 ){\r
+ var list = this._listeners,\r
+ _list, reserves, unlistens, i, f;\r
+ if( !list ) return this;\r
+ \r
+ if( X.Type.isArray( type ) ){\r
+ for( i = type.length; i; ){\r
+ this.unlisten( type[ --i ], arg1, arg2, arg3 );\r
+ };\r
+ return this;\r
+ };\r
+ \r
+ if( type === undefined ){\r
+ // 全て削除\r
+ for( type in list ){\r
+ _list = list[ type ];\r
+ for( i = _list.length; i; ){\r
+ this.unlisten( type, _list[ --i ] ); // override されていることがあるので、必ず unlisten を使用\r
+ };\r
+ // this.unlisten( type ); これは無茶!\r
+ };\r
+ return this;\r
+ } else\r
+ if( arg1 === undefined ){\r
+ // 同一タイプを全て削除\r
+ if( _list = list[ type ] ){\r
+ for( i = _list.length; i; ){\r
+ this.unlisten( type, _list[ --i ] ); // override されていることがあるので、必ず unlisten を使用\r
+ };\r
+ };\r
+ return this;\r
+ } else\r
+ if( reserves = this._reserves ){\r
+ for( i = reserves.length; i; ){\r
+ f = reserves[ --i ];\r
+ if( f[ 0 ] === type && f[ 1 ] === arg1 && f[ 2 ] === arg2 && f[ 3 ] === arg3 ){\r
+ reserves.splice( i, 1 );\r
+ if( !reserves.legth ) delete this._reserves;\r
+ return this;\r
+ };\r
+ };\r
+ };\r
+ \r
+ x_eventdispatcher_needsIndex = true;\r
+ i = this.listening( type, arg1, arg2, arg3 );\r
+ x_eventdispatcher_needsIndex = false;\r
+ if( i === false ) return this;\r
+\r
+ f = ( _list = list[ type ] )[ i ];\r
+ if( unlistens = this._unlistens ){\r
+ ( unlistens = unlistens[ type ] ) ?\r
+ ( unlistens[ unlistens.length ] = f ) :\r
+ ( this._unlistens[ type ] = [ f ] );\r
+ } else {\r
+ delete f.once;\r
+ f.kill === X.Callback._kill && f.kill();\r
+ _list.splice( i, 1 );\r
+ if( !_list.length ){\r
+ delete this._listeners[ type ];\r
+ X.Type.isString( type ) && x_eventdispatcher_actualRemoveEvent( this, type );\r
+ if( X.isEmptyObject( this._listeners ) ) delete this._listeners;\r
+ };\r
+ };\r
+ return this;\r
+};\r
+\r
+\r
+x_eventdispatcher_actualAddEvent =\r
+ // Days on the Moon DOM Events とブラウザの実装 \r
+ // http://nanto.asablo.jp/blog/2007/03/23/1339502\r
+ // Safari 2 では関数オブジェクトしか EventListener として使えませんが、Safari のナイトリービルドでは handleEvent メソッドを持つオブジェクトも EventListener として使えるようです。\r
+ x_eventdispatcher_temp.EVENT_W3C && ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 ) ? // Safari3-\r
+ (function( that, type ){\r
+ var raw = that._rawNode;\r
+ if( !raw ) return;\r
+ that._handleEvent = that._handleEvent || X.Callback.create( that );\r
+ type = X.Dom.Event.Rename[ type ] || type;\r
+ if( raw.addEventListener ){\r
+ raw.addEventListener( type, that._handleEvent, false );\r
+ } else {\r
+ // Safari は Image, Opera7 は window\r
+ raw[ 'on' + type ] = that._handleEvent;\r
+ };\r
+ }) :\r
+ x_eventdispatcher_temp.EVENT_W3C ?\r
+ (function( that, type ){\r
+ that._rawNode && that._rawNode.addEventListener( X.Dom.Event.Rename[ type ] || type, that, false );\r
+ }) :\r
+ x_eventdispatcher_temp.EVENT_IE ?\r
+ (function( that, type ){\r
+ var raw = that._rawNode;\r
+ if( !raw ) return;\r
+ type = X.Dom.Event.Rename[ type ] || type;\r
+ //if( type === 'load' && that._tag && X.Dom.Event._LOAD_FIX_TAGS[ that._tag ] ){\r
+ // type = 'readystatechange';\r
+ //};\r
+ that._handleEvent = that._handleEvent || X.Callback.create( that );\r
+ if( raw.attachEvent ){\r
+ raw.attachEvent( 'on' + type, that._handleEvent );\r
+ } else {\r
+ raw[ 'on' + type ] = that._handleEvent;\r
+ };\r
+ }) :\r
+ (function( that, type ){\r
+ var raw = that._rawNode || ( that._ie4getRawNode && that._ie4getRawNode() );\r
+ if( !raw ) return;\r
+ raw[ 'on' + ( X.Dom.Event.Rename[ type ] || type ) ] = that._handleEvent = that._handleEvent || X.Callback.create( that );\r
+ });\r
+\r
+\r
+x_eventdispatcher_actualRemoveEvent =\r
+ x_eventdispatcher_temp.EVENT_W3C && ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 ) ? // Safari3-\r
+ (function( that, type ){\r
+ var raw = that._rawNode;\r
+ if( !raw ) return;\r
+ type = X.Dom.Event.Rename[ type ] || type;\r
+ \r
+ if( raw.addEventListener ){ // Image\r
+ raw.removeEventListener( type, that._handleEvent, false );\r
+ } else {\r
+ raw[ 'on' + type ] = null;\r
+ };\r
+ if( !that._listeners ){\r
+ X.Callback._correct( that._handleEvent );\r
+ delete that._handleEvent;\r
+ };\r
+ }) :\r
+ x_eventdispatcher_temp.EVENT_W3C ?\r
+ (function( that, type ){\r
+ var raw = that._rawNode;\r
+ if( !raw ) return;\r
+ raw.removeEventListener( X.Dom.Event.Rename[ type ] || type, that, false );\r
+ }) :\r
+ x_eventdispatcher_temp.EVENT_IE ?\r
+ (function( that, type ){\r
+ var raw = that._rawNode;\r
+ if( !raw ) return;\r
+ type = X.Dom.Event.Rename[ type ] || type;\r
+ //if( type === 'load' && that._tag && X.Dom.Event._LOAD_FIX_TAGS[ that._tag ] ){\r
+ // type = 'readystatechange';\r
+ //};\r
+ if( raw.attachEvent ){\r
+ raw.detachEvent( 'on' + type, that._handleEvent );\r
+ } else {\r
+ raw[ 'on' + type ] = X.emptyFunction;\r
+ raw[ 'on' + type ] = '';\r
+ };\r
+ if( !that._listeners ){\r
+ X.Callback._correct( that._handleEvent );\r
+ delete that._handleEvent;\r
+ };\r
+ }) :\r
+ (function( that, type ){\r
+ var raw = that._rawNode || ( that._ie4getRawNode && that._ie4getRawNode() );\r
+ if( !raw ) return;\r
+ type = X.Dom.Event.Rename[ type ] || type;\r
+ raw[ 'on' + type ] = X.emptyFunction;\r
+ raw[ 'on' + type ] = '';\r
+ if( !that._listeners ){\r
+ X.Callback._correct( that._handleEvent );\r
+ delete that._handleEvent;\r
+ };\r
+ });\r
+\r
\r
console.log( 'X.Core.EventDispatcher' );\r
// axis\r
// https://w3g.jp/blog/tools/wheelevent_crossbrowser\r
// ホイール系イベント2014年版クロスブラウザ\r
- if( e.deltaY ){\r
- this.deltaX = e.deltaX;\r
- this.deltaY = e.deltaY;\r
+ if( e.deltaY !== undefined ){\r
+ this.deltaX = e.deltaX / 100;\r
+ this.deltaY = e.deltaY / 100;\r
} else\r
if( e.wheelDeltaY !== undefined ){\r
this.deltaX = e.wheelDeltaX / 120;\r
} else\r
if( e.wheelDelta !== undefined ){\r
this.deltaX = 0;\r
- this.deltaY = -e.wheelDelta / 120;\r
+ this.deltaY = e.wheelDelta / -120;\r
} else\r
if( e.detail !== undefined ){\r
this.deltaX = 0;\r
- this.deltaY = e.type === 'MozMousePixelScroll' ? e.detail / 15 : e.detail; // 3\r
+ this.deltaY = e.type === 'MozMousePixelScroll' ? e.detail / 45 : e.detail / 3; // 3\r
} else {\r
this.deltaX = this.deltaY = 0;\r
};\r
};\r
this.button = this.which - 1;\r
this.deltaX = 0;\r
- this.deltaY = e.wheelDelta / -12;\r
+ this.deltaY = e.wheelDelta / -120;\r
\r
if( this.type === 'wheel' ) console.log( e.wheelDelta );\r
};\r
console.log( 'wheel <= DOMMouseScroll' );\r
X.Dom.Event.Rename[ 'wheel' ] = 'DOMMouseScroll';\r
};\r
- } else\r
- if( document.onmousewheel !== undefined ){\r
+ } else {\r
+ X.Dom.Event.Rename[ 'wheel' ] = 'mousewheel';\r
+ };\r
+ if( document.onmousewheel !== undefined ){ // Opera で判定失敗\r
X.Dom.Event.Rename[ 'wheel' ] = 'mousewheel';\r
- }; \r
+ };\r
};\r
\r
+\r
+\r
if( window.onwebkitanimationend !== undefined && window.onanimationend === undefined ){\r
console.log( 'animationend <= webkitAnimationEnd' );\r
X.Dom.Event.Rename[ 'animationend' ] = 'webkitAnimationEnd';\r
\r
\r
\r
-X.Dom.Node.prototype.listen = function( type, arg1, arg2, arg3 /* [ listener || ( context + function ) || function ][ arguments ] */ ){\r
- if( this._xnodeType === 0 || this._xnodeType === 3 ) return this;\r
- \r
- if( X.Type.isArray( type ) ){\r
- return X.EventDispatcher.prototype.listen.apply( this, arguments );\r
- };\r
- \r
- ( !this._listeners || !this._listeners[ type ] ) && X.Type.isString( type ) && this._addEvent( type );\r
- \r
- return X.EventDispatcher.prototype.listen.apply( this, arguments );\r
-};\r
-\r
-X.Dom.Node.prototype._addEvent =\r
- // Days on the Moon DOM Events とブラウザの実装 \r
- // http://nanto.asablo.jp/blog/2007/03/23/1339502\r
- // Safari 2 では関数オブジェクトしか EventListener として使えませんが、Safari のナイトリービルドでは handleEvent メソッドを持つオブジェクトも EventListener として使えるようです。\r
- X.Dom.EVENT_W3C && ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 ) ? // Safari3-\r
- (function( type ){\r
- var raw = this._rawNode;\r
- if( !raw ) return;\r
- this._handleEvent = this._handleEvent || X.Callback.create( this );\r
- type = X.Dom.Event.Rename[ type ] || type;\r
- if( raw.addEventListener ){\r
- raw.addEventListener( type, this._handleEvent, false );\r
- } else {\r
- // Safari は Image, Opera7 は window\r
- raw[ 'on' + type ] = this._handleEvent;\r
- };\r
- }) :\r
- X.Dom.EVENT_W3C ?\r
- (function( type ){\r
- this._rawNode && this._rawNode.addEventListener( X.Dom.Event.Rename[ type ] || type, this, false );\r
- }) :\r
- X.Dom.EVENT_IE ?\r
- (function( type ){\r
- var raw = this._rawNode;\r
- if( !raw ) return;\r
- type = X.Dom.Event.Rename[ type ] || type;\r
- //if( type === 'load' && this._tag && X.Dom.Event._LOAD_FIX_TAGS[ this._tag ] ){\r
- // type = 'readystatechange';\r
- //};\r
- this._handleEvent = this._handleEvent || X.Callback.create( this );\r
- if( raw.attachEvent ){\r
- raw.attachEvent( 'on' + type, this._handleEvent );\r
- } else {\r
- raw[ 'on' + type ] = this._handleEvent;\r
- };\r
- }) :\r
- (function( type ){\r
- var raw = this._rawNode || ( this._ie4getRawNode && this._ie4getRawNode() );\r
- if( !raw ) return;\r
- raw[ 'on' + ( X.Dom.Event.Rename[ type ] || type ) ] = this._handleEvent = this._handleEvent || X.Callback.create( this );\r
- });\r
-\r
-\r
-X.Dom.Node.prototype.unlisten = function( type, arg1, arg2, arg3 ){\r
- var list = this._listeners, l;\r
- \r
- if( X.Type.isArray( type ) ){\r
- return list ? X.EventDispatcher.prototype.unlisten.apply( this, arguments ) : this;\r
- };\r
-\r
- l = !this._dispatching && list && type !== undefined && list[ type ] && list[ type ].length;\r
- \r
- X.EventDispatcher.prototype.unlisten.apply( this, arguments );\r
- \r
- l && !list[ type ] && X.Type.isString( type ) && this._removeEvent( type );\r
- \r
- return this;\r
-};\r
-\r
-X.Dom.Node.prototype._removeEvent =\r
- X.Dom.EVENT_W3C && ( X.UA.WebKit < 525.13 || X.UA.Opera7 || X.UA.NetFront < 4 ) ? // Safari3-\r
- (function( type ){\r
- var raw = this._rawNode;\r
- if( !raw ) return;\r
- type = X.Dom.Event.Rename[ type ] || type;\r
- \r
- if( raw.addEventListener ){ // Image\r
- raw.removeEventListener( type, this._handleEvent, false );\r
- } else {\r
- raw[ 'on' + type ] = null;\r
- };\r
- if( !this._listeners ){\r
- X.Callback._correct( this._handleEvent );\r
- delete this._handleEvent;\r
- };\r
- }) :\r
- X.Dom.EVENT_W3C ?\r
- (function( type ){\r
- var raw = this._rawNode;\r
- if( !raw ) return;\r
- raw.removeEventListener( X.Dom.Event.Rename[ type ] || type, this, false );\r
- }) :\r
- X.Dom.EVENT_IE ?\r
- (function( type ){\r
- var raw = this._rawNode;\r
- if( !raw ) return;\r
- type = X.Dom.Event.Rename[ type ] || type;\r
- //if( type === 'load' && this._tag && X.Dom.Event._LOAD_FIX_TAGS[ this._tag ] ){\r
- // type = 'readystatechange';\r
- //};\r
- if( raw.attachEvent ){\r
- raw.detachEvent( 'on' + type, this._handleEvent );\r
- } else {\r
- raw[ 'on' + type ] = X.emptyFunction;\r
- raw[ 'on' + type ] = '';\r
- };\r
- if( !this._listeners ){\r
- X.Callback._correct( this._handleEvent );\r
- delete this._handleEvent;\r
- };\r
- }) :\r
- (function( type ){\r
- var raw = this._rawNode || ( this._ie4getRawNode && this._ie4getRawNode() );\r
- if( !raw ) return;\r
- type = X.Dom.Event.Rename[ type ] || type;\r
- raw[ 'on' + type ] = X.emptyFunction;\r
- raw[ 'on' + type ] = '';\r
- if( !this._listeners ){\r
- X.Callback._correct( this._handleEvent );\r
- delete this._handleEvent;\r
- };\r
- });\r
-\r
+// TODO handleEvent を拡張可能にするために、クロージャに移動する\r
// Is this in regard to the Safari 1.x preventDefault bug on click/dblclick?\r
// https://groups.google.com/forum/#!msg/comp.lang.javascript/uYEuCHjHxnw/yKoHtZJPa1QJ\r
X.Dom.Node.prototype.handleEvent =\r
if( !hash ) return;\r
for( type in hash ){\r
// 数字イベントの除外\r
- /*'' + parseFloat( type ) !== type && */this._removeEvent( type );\r
+ /*'' + parseFloat( type ) !== type && */x_eventdispatcher_actualRemoveEvent( this, type );\r
};\r
};\r
\r
if( !hash ) return;\r
for( type in hash ){\r
// 数字イベントの除外\r
- /*'' + parseFloat( type ) !== type && */ this._addEvent( type );\r
+ /*'' + parseFloat( type ) !== type && */ x_eventdispatcher_actualAddEvent( this, type );\r
};\r
};\r
\r