OSDN Git Service

Version 0.6.94, new X.Callback is fast & light maybe.
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 10_XCallback.js
1 \r
2 // ------------------------------------------------------------------------- //\r
3 // ------------ local variables -------------------------------------------- //\r
4 // ------------------------------------------------------------------------- //\r
5 \r
6 var X_Callback_LIVE_LIST        = [],\r
7         X_Callback_POOL_LIST        = [],\r
8         X_Closure_COMMAND_BACK      = X_Callback_LIVE_LIST,\r
9         X_Closure_COMMAND_DROP      = X_Callback_POOL_LIST,\r
10         \r
11         X_Callback_THIS_FUNC        = 1,\r
12         X_Callback_HANDLEEVENT      = 2,\r
13         X_Callback_FUNC_ONLY        = 3;\r
14 \r
15         X_Callback_NONE             =  0,\r
16         X_Callback_UN_LISTEN        =  1,\r
17         X_Callback_STOP_PROPAGATION =  2,  // 上位階層への伝播のキャンセル\r
18         X_Callback_STOP_NOW         =  4 | 2,  // 同一階層のリスナーのキャンセル(上位へもキャンセル)\r
19         X_Callback_PREVENT_DEFAULT  =  8,  // 結果動作のキャンセル,\r
20         X_Callback_MONOPOLY         = 16,  // move event を独占する\r
21         X_Callback_SYS_CANCEL       = 32 | 4 | 2;\r
22 \r
23 /*\r
24  * handleEvent という関数のメンバーを持つオブジェクト\r
25  * @typedef {{ handleEvent : function }}\r
26  */\r
27 var listener;\r
28 \r
29 /*\r
30  * コールバックに thisObject や、追加の引数を設定するための情報を収めたハッシュ\r
31  * @typedef {{ k : number, f : (function|undefined), x : (listener|undefined), s : (Array|undefined) }}\r
32  */\r
33 var callbackHash;\r
34 \r
35 /*\r
36  * \r
37  * @typedef {(funciton|{ _ : function, same : function, kill : function, a : (Array|undefined) })}\r
38  */\r
39 var functionHash;\r
40 \r
41 X.Callback = {\r
42         \r
43         NONE             : X_Callback_NONE,\r
44         UN_LISTEN        : X_Callback_UN_LISTEN,\r
45         STOP_PROPAGATION : X_Callback_STOP_PROPAGATION,\r
46         STOP_NOW         : X_Callback_STOP_NOW,\r
47         PREVENT_DEFAULT  : X_Callback_PREVENT_DEFAULT,\r
48         MONOPOLY         : X_Callback_MONOPOLY,\r
49         \r
50         create : X_Callback_create,\r
51         \r
52         sys_monitor : function(){\r
53                 return {\r
54                         'Live callback' : X_Callback_LIVE_LIST.length,\r
55                         'Pool callback' : X_Callback_POOL_LIST.length\r
56                 };\r
57         },\r
58         \r
59         sys_gc : function(){\r
60                 var list = X_Callback_POOL_LIST,\r
61                         f;\r
62                 while( 0 < list.length ){\r
63                         f = list.shift();\r
64                         X_Callback_correct( f );\r
65                         delete f[ 'kill' ];\r
66                         delete f[ 'same' ];\r
67                 };\r
68         }\r
69 };\r
70 \r
71 X_TEMP.onSystemReady.push( X_Callback_handleSystemEvent );\r
72 \r
73 // ------------------------------------------------------------------------- //\r
74 // --- implements ---------------------------------------------------------- //\r
75 // ------------------------------------------------------------------------- //\r
76 \r
77 function X_Callback_handleSystemEvent( e ){\r
78         switch( e ){\r
79                 case '':\r
80         };\r
81 };\r
82 \r
83 function X_Callback_create( thisObject, opt_callback, opt_args /* [ listener || ( context + function ) || function ][ args... ] */ ){\r
84         var obj = X_Callback_classifyCallbackArgs( thisObject, opt_callback, opt_args ),\r
85                 l, ret, _obj;\r
86         if( !obj.k ) return obj;\r
87         if( l = X_Callback_POOL_LIST.length ){\r
88                 ret    = X_Callback_POOL_LIST[ l - 1 ]; --X_Callback_POOL_LIST.length; // ret = X_Callback_POOL_LIST.pop();\r
89                 _obj   = ret( X_Closure_COMMAND_BACK );\r
90                 _obj.k = obj.k;\r
91                 _obj.f = obj.f;\r
92                 _obj.x = obj.x;\r
93                 _obj.s = obj.s;\r
94         } else {\r
95                 ret = X_Closure_actualClosure( obj );\r
96                 ret.kill = X_Callback_kill;\r
97                 ret.same = X_Callback_same;\r
98         };\r
99         X_Callback_LIVE_LIST[ X_Callback_LIVE_LIST.length ] = ret;\r
100         return ret;     \r
101 };\r
102 \r
103 function X_Closure_actualClosure( obj ){\r
104         return function(){\r
105                 if( arguments[ 0 ] === X_Closure_COMMAND_BACK ) return obj;\r
106                 if( arguments[ 0 ] !== X_Closure_COMMAND_DROP ) return X_Callback_proxyCallback( obj, arguments );\r
107         };\r
108 };\r
109 \r
110 function X_Callback_classifyCallbackArgs( arg1, arg2, arg3, alt_context ){\r
111         var obj;\r
112         \r
113         if( arg1 && X.Type.isFunction( arg2 ) ){\r
114                 obj  = { x : arg1, f : arg2, k : X_Callback_THIS_FUNC };\r
115         } else\r
116         if( arg1 && X.Type.isFunction( arg1[ 'handleEvent' ] ) ){\r
117                 obj  = { x : arg1, k : X_Callback_HANDLEEVENT };\r
118                 arg3 = arg2;\r
119         } else\r
120         if( X.Type.isFunction( arg1 ) ){\r
121                 arg3 = arg2;\r
122                 if( alt_context ){\r
123                         obj  = { x : alt_context, f : arg1, k : X_Callback_THIS_FUNC };\r
124                 } else {\r
125                         obj  = { f : arg1, k : X_Callback_FUNC_ONLY };\r
126                 };\r
127         } else\r
128         if( X.Type.isFunction( arg2 ) ){\r
129                 //console.log( 'X_Callback_classifyCallbackArgs : arg1 が ' + arg1 + 'です' ); ie4 で error\r
130                 if( alt_context ){\r
131                         obj  = { x : alt_context, f : arg2, k : X_Callback_THIS_FUNC };\r
132                 } else {\r
133                         obj  = { f : arg2, k : X_Callback_FUNC_ONLY };\r
134                 };\r
135         } else\r
136         if( alt_context ){\r
137                 obj  = { x : alt_context, k : X_Callback_HANDLEEVENT };\r
138                 arg3 = arg1;\r
139         } else {\r
140                 console.log( '不正 ' + arg1 );\r
141                 console.dir( arg1 );\r
142                 return;\r
143         };\r
144         \r
145         if( X.Type.isArray( arg3 )){\r
146                 obj.s = arg3;\r
147         };\r
148         return ( obj.x || obj.s ) ? obj : arg1;\r
149 };\r
150 \r
151 function X_Callback_proxyCallback( xfunc, _args ){\r
152         var args    = _args || [],\r
153                 thisObj = xfunc.x,\r
154                 func    = xfunc.f,\r
155                 supp    = xfunc.s,\r
156                 temp, ret;      \r
157         \r
158         if( supp && supp.length ){\r
159                 temp = [];\r
160                 args.length &&\r
161                         (\r
162                                 args.length === 1 ?\r
163                                         ( temp[ 0 ] = args[ 0 ] ) :\r
164                                         temp.push.apply( temp, args )\r
165                         );\r
166                 supp.length === 1 ?\r
167                         ( temp[ temp.length ] = supp[ 0 ] ) :\r
168                         temp.push.apply( temp, supp );\r
169                 args = temp;\r
170         };\r
171         \r
172         switch( xfunc.k ){\r
173 \r
174                 case X_Callback_THIS_FUNC :\r
175                         return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );\r
176                         \r
177                 case X_Callback_HANDLEEVENT :\r
178                         temp = thisObj[ 'handleEvent' ];\r
179                         if( X.Type.isFunction( temp ) ){\r
180                                 return args.length === 0 ? thisObj[ 'handleEvent' ]() :\r
181                                            args.length === 1 ? thisObj[ 'handleEvent' ]( args[ 0 ] ) : temp.apply( thisObj, args );\r
182                         };\r
183                         break;\r
184                         /*\r
185                         if( temp !== func && X.Type.isFunction( temp ) ){\r
186                                 return args.length === 0 ? thisObj[ 'handleEvent' ]() : temp.apply( thisObj, args );\r
187                         } else\r
188                         if( X.Type.isFunction( thisObj ) ){\r
189                                 return args.length === 0 ? thisObj.call( thisObj ) : thisObj.apply( thisObj, args );\r
190                         };\r
191                         return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );*/\r
192                                                 \r
193                 case X_Callback_FUNC_ONLY :\r
194                         return args.length === 0 ?\r
195                                         func() :\r
196                                 args.length === 1 ?\r
197                                         func( args[ 0 ] ) :\r
198                                         func.apply( null, args );\r
199         };\r
200         return X_Callback_NONE;\r
201 };\r
202 \r
203 function X_Callback_same( arg1, arg2, arg3 ){\r
204         var hash;\r
205         \r
206         if( arg1 && arg1[ 'kill' ] === X_Callback_kill ) return this === arg1;\r
207         \r
208         hash = X_Callback_classifyCallbackArgs( arg1, arg2, arg3 );\r
209         \r
210         return hash && this.k === hash.k && this.x === hash.x && this.f === hash.f && this.s === hash.s;\r
211 };\r
212 \r
213 function X_Callback_kill(){\r
214         X_Callback_correct( this );\r
215 };\r
216 \r
217 function X_Callback_correct( f ){\r
218         var i = X_Callback_LIVE_LIST.indexOf( f ),\r
219                 obj;\r
220         if( i !== -1 ){\r
221                 X_Callback_LIVE_LIST.splice( i, 1 );\r
222                 X_Callback_POOL_LIST[ X_Callback_POOL_LIST.length ] = f;\r
223                 obj = f( X_Closure_COMMAND_BACK );\r
224                 delete obj.k;\r
225                 if( obj.f ) delete obj.f;\r
226                 if( obj.x ) delete obj.x;\r
227                 if( obj.s ) delete obj.s;\r
228                 return true;\r
229         };\r
230         return false;\r
231 };\r
232 \r
233 \r
234 \r
235 \r
236 console.log( 'X.Core.Callback' );\r
237 \r