OSDN Git Service

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