// ------------ local variables -------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
\r
-var XCallback_USE_CLOSURE = false,\r
-\r
- XCallback_LIVE_LIST = [],\r
- XCallback_POOL_LIST = [],\r
- \r
- XCallback_THIS_FUNC = 1,\r
- XCallback_HANDLEEVENT = 2,\r
- XCallback_FUNC_ONLY = 3;\r
+var X_Callback_LIVE_LIST = [],\r
+ X_Callback_POOL_LIST = [],\r
+ X_Closure_COMMAND_BACK = X_Callback_LIVE_LIST,\r
+ X_Closure_COMMAND_DROP = X_Callback_POOL_LIST,\r
\r
+ X_Callback_THIS_FUNC = 1,\r
+ X_Callback_HANDLEEVENT = 2,\r
+ X_Callback_FUNC_ONLY = 3,\r
+\r
+ X_Callback_NONE = 0,\r
+ X_Callback_UN_LISTEN = 1,\r
+ X_Callback_STOP_PROPAGATION = 2, // 上位階層への伝播のキャンセル\r
+ X_Callback_STOP_NOW = 4 | 2, // 同一階層のリスナーのキャンセル(上位へもキャンセル)\r
+ X_Callback_PREVENT_DEFAULT = 8, // 結果動作のキャンセル,\r
+ X_Callback_MONOPOLY = 16, // move event を独占する\r
+ X_Callback_SYS_CANCEL = 32 | 4 | 2;\r
\r
/*\r
* handleEvent という関数のメンバーを持つオブジェクト\r
\r
/*\r
* \r
- * @typedef {funciton}\r
+ * @typedef {(funciton|{ _ : function, same : function, kill : function, a : (Array|undefined) })}\r
*/\r
var functionHash;\r
\r
X.Callback = {\r
- \r
- NONE : 0,\r
- UN_LISTEN : 1,\r
- STOP_PROPAGATION : 2, // 上位階層への伝播のキャンセル\r
- STOP_NOW : 4 | 2, // 同一階層のリスナーのキャンセル(上位へもキャンセル)\r
- PREVENT_DEFAULT : 8, // 結果動作のキャンセル,\r
- MONOPOLY : 16, // move event を独占する\r
- SYS_CANCEL : 32 | 4 | 2,\r
- \r
- _USE_CLOSURE : false,\r
- \r
- _LIVE_LIST : [],\r
- _POOL_LIST : [],\r
- \r
- _THIS_FUNC : 1,\r
- _HANDLEEVENT : 2,\r
- _FUNC_ONLY : 3,\r
- \r
- create : function( arg1, arg2, arg3 /* [ listener || ( context + function ) || function ][ args... ] */ ){\r
- var live = X.Callback._LIVE_LIST,\r
- hash = X.Callback._classifyCallbackArgs( arg1, arg2, arg3 ),\r
- f;\r
- \r
- if( !hash.k ) return hash;\r
- \r
- f = X.Callback._POOL_LIST.pop();\r
- if( !f ){\r
- f = new Function( 'var a=arguments,f=a.callee;f.a=a;return f._(f)' ); // f.x=this;\r
- f[ 'kill' ] = X.Callback._kill;\r
- f[ 'same' ] = X.Callback._same;\r
- f._ = X.Callback._proxyCallback;\r
- };\r
- \r
- live[ live.length ] = f;\r
- \r
- switch( f.k = hash.k ){\r
- case X.Callback._THIS_FUNC :\r
- f.x = hash.x;\r
- f.f = hash.f;\r
- break;\r
- case X.Callback._HANDLEEVENT :\r
- f.x = hash.x;\r
- break;\r
- case X.Callback._FUNC_ONLY :\r
- f.f = hash.f;\r
- break;\r
- };\r
+ NONE : X_Callback_NONE,\r
+ UN_LISTEN : X_Callback_UN_LISTEN,\r
+ STOP_PROPAGATION : X_Callback_STOP_PROPAGATION,\r
+ STOP_NOW : X_Callback_STOP_NOW,\r
+ PREVENT_DEFAULT : X_Callback_PREVENT_DEFAULT,\r
+ MONOPOLY : X_Callback_MONOPOLY\r
+};\r
\r
- if( hash.s ) f.s = hash.s;\r
- return f;\r
- },\r
- \r
- _createClosure : function( obj ){\r
- return function(){\r
- obj.a = arguments;\r
- return obj._( obj );\r
- };\r
- },\r
+// ------------------------------------------------------------------------- //\r
+// --- implements ---------------------------------------------------------- //\r
+// ------------------------------------------------------------------------- //\r
+\r
+function X_Callback_create( thisObject, opt_callback, opt_args /* [ listener || ( context + function ) || function ][ args... ] */ ){\r
+ var obj = X_Callback_classifyCallbackArgs( thisObject, opt_callback, opt_args ),\r
+ l, ret, _obj;\r
+ if( !obj.k ) return obj;\r
+ if( l = X_Callback_POOL_LIST.length ){\r
+ ret = X_Callback_POOL_LIST[ l - 1 ]; --X_Callback_POOL_LIST.length; // ret = X_Callback_POOL_LIST.pop();\r
+ _obj = ret( X_Closure_COMMAND_BACK );\r
+ _obj.k = obj.k;\r
+ _obj.f = obj.f;\r
+ _obj.x = obj.x;\r
+ _obj.s = obj.s;\r
+ } else {\r
+ ret = X_Closure_actualClosure( obj );\r
+ };\r
+ X_Callback_LIVE_LIST[ X_Callback_LIVE_LIST.length ] = ret;\r
+ return ret;\r
+};\r
+\r
+function X_Closure_actualClosure( obj ){\r
+ return function(){\r
+ if( arguments[ 0 ] === X_Closure_COMMAND_BACK ) return obj;\r
+ if( arguments[ 0 ] !== X_Closure_COMMAND_DROP ) return X_Callback_proxyCallback( obj, arguments );\r
+ };\r
+};\r
+\r
+function X_Callback_classifyCallbackArgs( arg1, arg2, arg3, alt_context ){\r
+ var obj;\r
\r
- _classifyCallbackArgs : function( arg1, arg2, arg3, alt_context ){\r
- var obj;\r
- \r
- if( arg1 && X.Type.isFunction( arg2 ) ){\r
- obj = { x : arg1, f : arg2, k : X.Callback._THIS_FUNC };\r
- } else\r
- if( arg1 && X.Type.isFunction( arg1[ 'handleEvent' ] ) ){\r
- obj = { x : arg1, k : X.Callback._HANDLEEVENT };\r
- arg3 = arg2;\r
- } else\r
- if( X.Type.isFunction( arg1 ) ){\r
- arg3 = arg2;\r
- if( alt_context ){\r
- obj = { x : alt_context, f : arg1, k : X.Callback._THIS_FUNC };\r
- } else {\r
- obj = { f : arg1, k : X.Callback._FUNC_ONLY };\r
- };\r
- } else\r
- if( X.Type.isFunction( arg2 ) ){\r
- //console.log( 'X.Callback._classifyCallbackArgs : arg1 が ' + arg1 + 'です' ); ie4 で error\r
- if( alt_context ){\r
- obj = { x : alt_context, f : arg2, k : X.Callback._THIS_FUNC };\r
- } else {\r
- obj = { f : arg2, k : X.Callback._FUNC_ONLY };\r
- };\r
- } else\r
+ if( arg1 && X.Type.isFunction( arg2 ) ){\r
+ obj = { x : arg1, f : arg2, k : X_Callback_THIS_FUNC };\r
+ } else\r
+ if( arg1 && X.Type.isFunction( arg1[ 'handleEvent' ] ) ){\r
+ obj = { x : arg1, k : X_Callback_HANDLEEVENT };\r
+ arg3 = arg2;\r
+ } else\r
+ if( X.Type.isFunction( arg1 ) ){\r
+ arg3 = arg2;\r
if( alt_context ){\r
- obj = { x : alt_context, k : X.Callback._HANDLEEVENT };\r
- arg3 = arg1;\r
+ obj = { x : alt_context, f : arg1, k : X_Callback_THIS_FUNC };\r
} else {\r
- console.log( '不正 ' + arg1 );\r
- console.dir( arg1 );\r
- return;\r
- };\r
- \r
- if( X.Type.isArray( arg3 )){\r
- obj.s = arg3;\r
- };\r
- return ( obj.x || obj.s ) ? obj : arg1;\r
- },\r
-\r
- _proxyCallback : function( xfunc ){\r
- var args = xfunc.a || [],\r
- thisObj = xfunc.x,\r
- func = xfunc.f,\r
- supp = xfunc.s,\r
- temp, ret;\r
- \r
- delete xfunc.a; \r
- \r
- if( supp && supp.length ){\r
- temp = [];\r
- args.length &&\r
- (\r
- args.length === 1 ?\r
- ( temp[ 0 ] = args[ 0 ] ) :\r
- temp.push.apply( temp, args )\r
- );\r
- supp.length === 1 ?\r
- ( temp[ temp.length ] = supp[ 0 ] ) :\r
- temp.push.apply( temp, supp );\r
- args = temp;\r
+ obj = { f : arg1, k : X_Callback_FUNC_ONLY };\r
};\r
- \r
- switch( xfunc.k ){\r
-\r
- case X.Callback._THIS_FUNC :\r
- return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );\r
- \r
- case X.Callback._HANDLEEVENT :\r
- temp = thisObj[ 'handleEvent' ];\r
- if( X.Type.isFunction( temp ) ){\r
- return args.length === 0 ? thisObj[ 'handleEvent' ]() :\r
- args.length === 1 ? thisObj[ 'handleEvent' ]( args[ 0 ] ) : temp.apply( thisObj, args );\r
- };\r
- break;\r
- /*\r
- if( temp !== func && X.Type.isFunction( temp ) ){\r
- return args.length === 0 ? thisObj[ 'handleEvent' ]() : temp.apply( thisObj, args );\r
- } else\r
- if( X.Type.isFunction( thisObj ) ){\r
- return args.length === 0 ? thisObj.call( thisObj ) : thisObj.apply( thisObj, args );\r
- };\r
- return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );*/\r
- \r
- case X.Callback._FUNC_ONLY :\r
- return args.length === 0 ?\r
- func() :\r
- args.length === 1 ?\r
- func( args[ 0 ] ) :\r
- func.apply( null, args );\r
+ } else\r
+ if( X.Type.isFunction( arg2 ) ){\r
+ //console.log( 'X_Callback_classifyCallbackArgs : arg1 が ' + arg1 + 'です' ); ie4 で error\r
+ if( alt_context ){\r
+ obj = { x : alt_context, f : arg2, k : X_Callback_THIS_FUNC };\r
+ } else {\r
+ obj = { f : arg2, k : X_Callback_FUNC_ONLY };\r
};\r
- return X.Callback.NONE;\r
- },\r
+ } else\r
+ if( alt_context ){\r
+ obj = { x : alt_context, k : X_Callback_HANDLEEVENT };\r
+ arg3 = arg1;\r
+ } else {\r
+ console.log( '不正 ' + arg1 );\r
+ console.dir( arg1 );\r
+ return;\r
+ };\r
\r
- _kill : function(){\r
- X.Callback._correct( this );\r
- },\r
- _same : function( arg1, arg2, arg3 ){\r
- var hash;\r
- \r
- if( arg1 && arg1[ 'kill' ] === X.Callback._kill ) return this === arg1;\r
- \r
- hash = X.Callback._classifyCallbackArgs( arg1, arg2, arg3 );\r
- \r
- return hash && this.k === hash.k && this.x === hash.x && this.f === hash.f && this.s === hash.s;\r
- },\r
- _correct : function( f ){\r
- var i = X.Callback._LIVE_LIST.indexOf( f );\r
- //delete f._;\r
- delete f.k;\r
- if( f.x ) delete f.x;\r
- if( f.f ) delete f.f;\r
- if( f.s ) delete f.s;\r
- if( i === -1 ) return;\r
- X.Callback._LIVE_LIST.splice( i, 1 );\r
- X.Callback._POOL_LIST.push( f );\r
- },\r
+ if( X.Type.isArray( arg3 )){\r
+ obj.s = arg3;\r
+ };\r
+ return ( obj.x || obj.s ) ? obj : arg1;\r
+};\r
+\r
+function X_Callback_proxyCallback( xfunc, _args ){\r
+ var args = _args || [],\r
+ thisObj = xfunc.x,\r
+ func = xfunc.f,\r
+ supp = xfunc.s,\r
+ temp, ret; \r
\r
- sys_monitor : function(){\r
- return {\r
- 'Live callback' : X.Callback._LIVE_LIST.length,\r
- 'Pool callback' : X.Callback._POOL_LIST.length\r
- };\r
- },\r
- sys_gc : function(){\r
- var list = X.Callback._POOL_LIST,\r
- f;\r
- while( 0 < list.length ){\r
- f = list.shift();\r
- X.Callback._correct( f );\r
- delete f[ '_' ];\r
- delete f[ 'kill' ];\r
- delete f[ 'same' ];\r
- };\r
- }\r
+ if( supp && supp.length ){\r
+ temp = [];\r
+ args.length &&\r
+ (\r
+ args.length === 1 ?\r
+ ( temp[ 0 ] = args[ 0 ] ) :\r
+ temp.push.apply( temp, args )\r
+ );\r
+ supp.length === 1 ?\r
+ ( temp[ temp.length ] = supp[ 0 ] ) :\r
+ temp.push.apply( temp, supp );\r
+ args = temp;\r
+ };\r
+ \r
+ switch( xfunc.k ){\r
+\r
+ case X_Callback_THIS_FUNC :\r
+ return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );\r
+ \r
+ case X_Callback_HANDLEEVENT :\r
+ temp = thisObj[ 'handleEvent' ];\r
+ if( X.Type.isFunction( temp ) ){\r
+ return args.length === 0 ? thisObj[ 'handleEvent' ]() :\r
+ args.length === 1 ? thisObj[ 'handleEvent' ]( args[ 0 ] ) : temp.apply( thisObj, args );\r
+ };\r
+ break;\r
+ /*\r
+ if( temp !== func && X.Type.isFunction( temp ) ){\r
+ return args.length === 0 ? thisObj[ 'handleEvent' ]() : temp.apply( thisObj, args );\r
+ } else\r
+ if( X.Type.isFunction( thisObj ) ){\r
+ return args.length === 0 ? thisObj.call( thisObj ) : thisObj.apply( thisObj, args );\r
+ };\r
+ return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );*/\r
+ \r
+ case X_Callback_FUNC_ONLY :\r
+ return args.length === 0 ?\r
+ func() :\r
+ args.length === 1 ?\r
+ func( args[ 0 ] ) :\r
+ func.apply( null, args );\r
+ };\r
+ return X_Callback_NONE;\r
+};\r
+\r
+function X_Callback_correct( f ){\r
+ var i = X_Callback_LIVE_LIST.indexOf( f ),\r
+ obj;\r
+ if( i !== -1 ){\r
+ X_Callback_LIVE_LIST.splice( i, 1 );\r
+ X_Callback_POOL_LIST[ X_Callback_POOL_LIST.length ] = f;\r
+ obj = f( X_Closure_COMMAND_BACK );\r
+ delete obj.k;\r
+ if( obj.f ) delete obj.f;\r
+ if( obj.x ) delete obj.x;\r
+ if( obj.s ) delete obj.s;\r
+ return true;\r
+ };\r
+ return false;\r
};\r
\r
-// ------------------------------------------------------------------------- //\r
-// --- implements ---------------------------------------------------------- //\r
-// ------------------------------------------------------------------------- //\r
\r
+// sys\r
+X_TEMP.X_Callback_onSystemReady = function( sys ){\r
+ delete X_TEMP.X_Callback_onSystemReady;\r
+ sys.monitor( X_Callback_monitor );\r
+ sys.gc( X_Callback_gc );\r
+};\r
\r
+function X_Callback_monitor(){\r
+ return {\r
+ 'Callback:Live' : X_Callback_LIVE_LIST.length,\r
+ 'Callback:Pool' : X_Callback_POOL_LIST.length\r
+ };\r
+};\r
+function X_Callback_gc(){\r
+ X_Callback_POOL_LIST.length = 0; // ?\r
+};\r
\r
+X_TEMP.onSystemReady.push( X_TEMP.X_Callback_onSystemReady );\r
\r
\r
console.log( 'X.Core.Callback' );\r