OSDN Git Service

bf00497ffab2ed96ea03358da3aed2651c7ab83e
[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         NONE             : X_Callback_NONE,\r
43         UN_LISTEN        : X_Callback_UN_LISTEN,\r
44         STOP_PROPAGATION : X_Callback_STOP_PROPAGATION,\r
45         STOP_NOW         : X_Callback_STOP_NOW,\r
46         PREVENT_DEFAULT  : X_Callback_PREVENT_DEFAULT,\r
47         MONOPOLY         : X_Callback_MONOPOLY\r
48 };\r
49 \r
50 // ------------------------------------------------------------------------- //\r
51 // --- implements ---------------------------------------------------------- //\r
52 // ------------------------------------------------------------------------- //\r
53 \r
54 function X_Callback_create( thisObject, opt_callback, opt_args /* [ listener || ( context + function ) || function ][ args... ] */ ){\r
55         var obj = X_Callback_classifyCallbackArgs( thisObject, opt_callback, opt_args ),\r
56                 l, ret, _obj;\r
57         if( !obj.k ) return obj;\r
58         if( l = X_Callback_POOL_LIST.length ){\r
59                 ret    = X_Callback_POOL_LIST[ l - 1 ]; --X_Callback_POOL_LIST.length; // ret = X_Callback_POOL_LIST.pop();\r
60                 _obj   = ret( X_Closure_COMMAND_BACK );\r
61                 _obj.k = obj.k;\r
62                 _obj.f = obj.f;\r
63                 _obj.x = obj.x;\r
64                 _obj.s = obj.s;\r
65                 _obj._ = X_Callback_proxyCallback;\r
66         } else {\r
67                 ret = X_Closure_actualClosure( obj );\r
68                 obj._ = X_Callback_proxyCallback;\r
69         };\r
70         X_Callback_LIVE_LIST[ X_Callback_LIVE_LIST.length ] = ret;\r
71         return ret;\r
72 };\r
73 \r
74 \r
75 function X_Callback_classifyCallbackArgs( arg1, arg2, arg3, alt_context ){\r
76         var obj;\r
77         \r
78         if( arg1 && X.Type.isFunction( arg2 ) ){\r
79                 obj  = { x : arg1, f : arg2, k : X_Callback_THIS_FUNC };\r
80         } else\r
81         if( arg1 && X.Type.isFunction( arg1[ 'handleEvent' ] ) ){\r
82                 obj  = { x : arg1, k : X_Callback_HANDLEEVENT };\r
83                 arg3 = arg2;\r
84         } else\r
85         if( X.Type.isFunction( arg1 ) ){\r
86                 arg3 = arg2;\r
87                 if( alt_context ){\r
88                         obj  = { x : alt_context, f : arg1, k : X_Callback_THIS_FUNC };\r
89                 } else {\r
90                         obj  = { f : arg1, k : X_Callback_FUNC_ONLY };\r
91                 };\r
92         } else\r
93         if( X.Type.isFunction( arg2 ) ){\r
94                 //console.log( 'X_Callback_classifyCallbackArgs : arg1 が ' + arg1 + 'です' ); ie4 で error\r
95                 if( alt_context ){\r
96                         obj  = { x : alt_context, f : arg2, k : X_Callback_THIS_FUNC };\r
97                 } else {\r
98                         obj  = { f : arg2, k : X_Callback_FUNC_ONLY };\r
99                 };\r
100         } else\r
101         if( alt_context ){\r
102                 obj  = { x : alt_context, k : X_Callback_HANDLEEVENT };\r
103                 arg3 = arg1;\r
104         } else {\r
105                 console.log( '不正 ' + arg1 );\r
106                 console.dir( arg1 );\r
107                 return;\r
108         };\r
109         \r
110         if( X.Type.isArray( arg3 )){\r
111                 obj.s = arg3;\r
112         };\r
113         return ( obj.x || obj.s ) ? obj : arg1;\r
114 };\r
115 \r
116 function X_Closure_actualClosure( obj ){\r
117         return function(){\r
118                 if( arguments[ 0 ] === X_Closure_COMMAND_BACK ) return obj;\r
119                 if( arguments[ 0 ] !== X_Closure_COMMAND_DROP ) return obj._( obj, arguments );\r
120         };\r
121 };\r
122 \r
123 function X_Callback_proxyCallback( xfunc, _args ){\r
124         var args    = _args || [],\r
125                 thisObj = xfunc.x,\r
126                 func    = xfunc.f,\r
127                 supp    = xfunc.s,\r
128                 temp, ret;      \r
129         \r
130         if( supp && supp.length ){\r
131                 temp = [];\r
132                 args.length &&\r
133                         (\r
134                                 args.length === 1 ?\r
135                                         ( temp[ 0 ] = args[ 0 ] ) :\r
136                                         temp.push.apply( temp, args )\r
137                         );\r
138                 supp.length === 1 ?\r
139                         ( temp[ temp.length ] = supp[ 0 ] ) :\r
140                         temp.push.apply( temp, supp );\r
141                 args = temp;\r
142         };\r
143         \r
144         switch( xfunc.k ){\r
145 \r
146                 case X_Callback_THIS_FUNC :\r
147                         return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );\r
148                         \r
149                 case X_Callback_HANDLEEVENT :\r
150                         temp = thisObj[ 'handleEvent' ];\r
151                         if( X.Type.isFunction( temp ) ){\r
152                                 return args.length === 0 ? thisObj[ 'handleEvent' ]() :\r
153                                            args.length === 1 ? thisObj[ 'handleEvent' ]( args[ 0 ] ) : temp.apply( thisObj, args );\r
154                         };\r
155                         break;\r
156                         /*\r
157                         if( temp !== func && X.Type.isFunction( temp ) ){\r
158                                 return args.length === 0 ? thisObj[ 'handleEvent' ]() : temp.apply( thisObj, args );\r
159                         } else\r
160                         if( X.Type.isFunction( thisObj ) ){\r
161                                 return args.length === 0 ? thisObj.call( thisObj ) : thisObj.apply( thisObj, args );\r
162                         };\r
163                         return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );*/\r
164                                                 \r
165                 case X_Callback_FUNC_ONLY :\r
166                         return args.length === 0 ?\r
167                                         func() :\r
168                                 args.length === 1 ?\r
169                                         func( args[ 0 ] ) :\r
170                                         func.apply( null, args );\r
171         };\r
172         return X_Callback_NONE;\r
173 };\r
174 \r
175 function X_Callback_correct( f ){\r
176         var i = X_Callback_LIVE_LIST.indexOf( f ),\r
177                 obj;\r
178         if( i !== -1 ){\r
179                 X_Callback_LIVE_LIST.splice( i, 1 );\r
180                 X_Callback_POOL_LIST[ X_Callback_POOL_LIST.length ] = f;\r
181                 obj = f( X_Closure_COMMAND_BACK );\r
182                 delete obj.k;\r
183                 if( obj.f ) delete obj.f;\r
184                 if( obj.x ) delete obj.x;\r
185                 if( obj.s ) delete obj.s;\r
186                 delete obj._;\r
187                 return true;\r
188         };\r
189         return false;\r
190 };\r
191 \r
192 \r
193 // sys\r
194 X_TEMP.X_Callback_onSystemReady = function( sys ){\r
195         delete X_TEMP.X_Callback_onSystemReady;\r
196         sys.monitor( X_Callback_monitor );\r
197         sys.gc( X_Callback_gc );\r
198 };\r
199 \r
200 function X_Callback_monitor(){\r
201         return {\r
202                 'Callback:Live' : X_Callback_LIVE_LIST.length,\r
203                 'Callback:Pool' : X_Callback_POOL_LIST.length\r
204         };\r
205 };\r
206 function X_Callback_gc(){\r
207         X_Callback_POOL_LIST.length = 0; // ?\r
208 };\r
209 \r
210 X_TEMP.onSystemReady.push( X_TEMP.X_Callback_onSystemReady );\r
211 \r
212 \r
213 console.log( 'X.Core.Callback' );\r
214 \r