* \r
* @class __Listeners__\r
* @private\r
- * @abstract\r
*/\r
var X_Listeners_;\r
\r
X_LISTENERS_KILL_RESERVED = 4; // X.Event で、イベントIDを 5 から始めているので注意。\r
\r
\r
-\r
// ------------------------------------------------------------------------- //\r
// ------------ local variables -------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
\r
/**\r
+ * <p>ぺったんR フレームワークの特徴であるイベントリスナの作法は次の記事で詳しく解説しています。\r
+ * <a href="http://outcloud.blogspot.jp/2015/06/eventdispatcher.html" target="_blank">ぺったんRフレームワークのコールバックのお作法</a>\r
+ * \r
* <ol>\r
* <li>as3 の EventDispatcher ライクなクラス。そのまま使ったり、継承したり。\r
* <li>_rawObject メンバがいる場合、addEventListener, attachEvent, on 等で生のブラウザオブジェクトにリスナを登録する。\r
* window, document, HTMLElement, Image, XHR, Silverlight などが _rawObject になる。\r
* <li>イベントディスパッチ中にリスナの追加が呼び出された場合、リスナはこれ以降のイベントから呼ばれます。同様にリスナの削除が呼ばれた場合、そのリスナが呼ばれることはありません。\r
* </ol>\r
- * \r
- * <blockquot>\r
- * <p><a href="https://developer.mozilla.org/ja/docs/Web/API/EventTarget.addEventListener" target="_blank">\r
- * MDN > 開発者向けのWeb技術 > Web API インターフェイス > EventTarget > EventTarget.addEventListener イベント発送中のリスナーの追加</a>\r
- * <p>EventListener がイベント処理中に EventTarget に追加された場合、それが現在のアクションによって実行されることはありませんが、浮上フェーズのように、後の段階のイベントフローで実行されるかもしれません。\r
- * </blockquot>\r
- * \r
- * <blockquot>\r
- * <p><a href="https://developer.mozilla.org/ja/docs/Web/API/EventTarget.removeEventListener" target="_blank">\r
- * MDN > 開発者向けのWeb技術 > Web API インターフェイス > EventTarget > EventTarget.removeEventListener 注記</a>\r
- * <p>イベントリスナーが イベントを処理中であるイベントターゲットから削除された場合、現在のアクションによってそのイベントリスナーが実行されることはありません。\r
- * <p>イベントリスナーは、決して削除された後に実行されることはありません。\r
- * <p>イベントターゲット上にある現在のどのイベントリスナーも指定していない引数付きの removeEventListener は、何の効果もありません。\r
- * </blockquot>\r
- *\r
* <p>listen, unlisten, dispatch という addEventListener, removeEventListener, dispatchEvent に対応する関数を持ちます。\r
* また listening という ActionScript3 の hasEventListener に相当する関数を持ちます。\r
* \r
* Arrayには、{kind:種類,context:コンテキスト(thisObject),func:コールバック関数,supplement:サプリメントする引数の配列} というハッシュ、または関数が蓄えられています。\r
* \r
* @private\r
- * @type {__X_EventDispatcher_Listeners__}\r
+ * @type {__Listeners__}\r
*/\r
'_listeners' : null,\r
\r
if( ( unlistens = listeners[ X_LISTENERS_UNLISTENS ] ) && ( unlistens = unlistens[ opt_type ] ) ){\r
for( i = unlistens.length; i; ){\r
f = unlistens[ --i ];\r
- if( f === cbHash || ( f.context === cbHash.context && f.func === cbHash.func && f.supplement === cbHash.supplement && f.lock === lock ) ) return false;\r
+ if( f === cbHash || ( f.context === cbHash.context && f.func === cbHash.func && f.name === cbHash.name && f.supplement === cbHash.supplement && f.lock === lock ) ) return false;\r
};\r
};\r
for( i = list.length; i; ){\r
f = list[ --i ];\r
- if( f === cbHash || ( f.context === cbHash.context && f.func === cbHash.func && f.supplement === cbHash.supplement && f.lock === lock ) ){\r
+ if( f === cbHash || ( f.context === cbHash.context && f.func === cbHash.func && f.name === cbHash.name && f.supplement === cbHash.supplement && f.lock === lock ) ){\r
// index を要求された場合、lock されていない、または unlock なら index を返す\r
return X_EventDispatcher_needsIndex ? i : true;\r
};\r
if( !listeners ) listeners = this[ '_listeners' ] = {};\r
list = listeners[ type ] || ( listeners[ type ] = [] );\r
\r
- add && X_EventDispatcher_addEvent( this, type, raw, list );\r
+ add && X_EventDispatcher_actualAddEvent( this, type, raw, list );\r
\r
f = X_Callback_classifyCallbackArgs( opt_arg1, opt_arg2, opt_arg3, this );\r
list[ list.length ] = f;\r
( listeners[ X_LISTENERS_UNLISTENS ][ opt_type ] = [ f ] );\r
} else {\r
delete f.once;\r
- list.splice( i, 1 );\r
- if( !list.length ){\r
- raw = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
+ if( list.length !== 1 ){\r
+ list.splice( i, 1 );\r
+ } else {\r
+ list.length = 0;\r
+\r
delete listeners[ opt_type ];\r
- //empty = X_Object_isEmpty( listeners );\r
+\r
// TODO カウンター\r
empty = true;\r
for( k in listeners ){\r
empty = false;\r
break;\r
};\r
- if( raw && !X_String_isNumberString( '' + opt_type ) ){ // 数字イベントの除外\r
- X_EventDispatcher_removeEvent( this, opt_type, raw, list, !empty );\r
+\r
+ if( !X_String_isNumberString( '' + opt_type ) ){ // 数字イベントの除外\r
+ raw = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
+ raw && X_EventDispatcher_actualRemoveEvent( this, opt_type, raw, list, !empty );\r
};\r
+ \r
if( empty ) delete this[ '_listeners' ];\r
};\r
};\r
};\r
};\r
\r
-function X_EventDispatcher_addEvent( that, type, raw, list ){\r
+function X_EventDispatcher_actualAddEvent( that, type, raw, list ){\r
var i, f;\r
X_EventDispatcher_lock || ( type = X_Event_Rename[ type ] || type );\r
\r
return this[ 'dispatch' ]( type );\r
};\r
\r
-function X_EventDispatcher_removeEvent( that, type, raw, list, skip ){\r
+function X_EventDispatcher_actualRemoveEvent( that, type, raw, list, skip ){\r
var i;\r
X_EventDispatcher_unlock || ( type = X_Event_Rename[ type ] || type );\r
\r
function X_EventDispatcher_toggleAllEvents( that, add ){\r
var list = that[ '_listeners' ],\r
raw = that[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( that ),\r
- func = add ? X_EventDispatcher_addEvent : X_EventDispatcher_removeEvent,\r
+ func = add ? X_EventDispatcher_actualAddEvent : X_EventDispatcher_actualRemoveEvent,\r
type;\r
if( !list || !raw ) return;\r
for( type in list ){\r