OSDN Git Service

b9cc825a1318b5221d6c5e3620fb5e5a3daf493d
[pettanr/clientJs.git] / 0.6.x / js / 00_core / 03_XCallback.js
1 \r
2 \r
3 X.Callback = {\r
4         \r
5         NONE             :  0,\r
6         UN_LISTEN        :  1,\r
7         STOP_PROPAGATION :  2,  // 上位階層への伝播のキャンセル\r
8         STOP_NOW         :  4 | 2,  // 同一階層のリスナーのキャンセル(上位へもキャンセル)\r
9         PREVENT_DEFAULT  :  8,  // 結果動作のキャンセル,\r
10         MONOPOLY         : 16,  // move event を独占する\r
11         SYS_CANCEL       : 32 | 4 | 2,\r
12         \r
13         _USE_CLOSURE     : false,\r
14         \r
15         _LIVE_LIST       : [],\r
16         _POOL_LIST       : [],\r
17         \r
18         _THIS_FUNC       : 1,\r
19         _HANDLEEVENT     : 2,\r
20         _FUNC_ONLY       : 3,\r
21         \r
22         create : function( arg1, arg2, arg3 /* [ listener || ( context + function ) || function ][ args... ] */ ){\r
23                 var live = X.Callback._LIVE_LIST,\r
24                         hash = X.Callback._classifyCallbackArgs( arg1, arg2, arg3 ),\r
25                         f;\r
26                 \r
27                 if( !hash.k ) return hash;\r
28                 \r
29                 f = X.Callback._POOL_LIST.pop();\r
30                 if( !f ){\r
31                         f = new Function( 'var a=arguments,f=a.callee;f.a=a;return f._(f)' ); // f.x=this;\r
32                         f[ 'kill' ] = X.Callback._kill;\r
33                         f[ 'same' ] = X.Callback._same;\r
34                         f._ = X.Callback._proxyCallback;\r
35                 };\r
36                 \r
37                 live[ live.length ] = f;\r
38                 \r
39                 switch( f.k = hash.k ){\r
40                         case X.Callback._THIS_FUNC :\r
41                                 f.x = hash.x;\r
42                                 f.f = hash.f;\r
43                                 break;\r
44                         case X.Callback._HANDLEEVENT :\r
45                                 f.x = hash.x;\r
46                                 break;\r
47                         case X.Callback._FUNC_ONLY :\r
48                                 f.f = hash.f;\r
49                                 break;\r
50                 };\r
51 \r
52                 if( hash.s ) f.s = hash.s;\r
53                 return f;\r
54         },\r
55         \r
56         _createClosure : function( obj ){\r
57                 return function(){\r
58                         obj.a = arguments;\r
59                         return obj._( obj );\r
60                 };\r
61         },\r
62         \r
63         _classifyCallbackArgs : function( arg1, arg2, arg3, alt_context ){\r
64                 var obj;\r
65                 \r
66                 if( arg1 && X.Type.isFunction( arg2 ) ){\r
67                         obj  = { x : arg1, f : arg2, k : X.Callback._THIS_FUNC };\r
68                 } else\r
69                 if( arg1 && X.Type.isFunction( arg1[ 'handleEvent' ] ) ){\r
70                         obj  = { x : arg1, k : X.Callback._HANDLEEVENT };\r
71                         arg3 = arg2;\r
72                 } else\r
73                 if( X.Type.isFunction( arg1 ) ){\r
74                         arg3 = arg2;\r
75                         if( alt_context ){\r
76                                 obj  = { x : alt_context, f : arg1, k : X.Callback._THIS_FUNC };\r
77                         } else {\r
78                                 obj  = { f : arg1, k : X.Callback._FUNC_ONLY };\r
79                         };\r
80                 } else\r
81                 if( X.Type.isFunction( arg2 ) ){\r
82                         //console.log( 'X.Callback._classifyCallbackArgs : arg1 が ' + arg1 + 'です' ); ie4 で error\r
83                         if( alt_context ){\r
84                                 obj  = { x : alt_context, f : arg2, k : X.Callback._THIS_FUNC };\r
85                         } else {\r
86                                 obj  = { f : arg2, k : X.Callback._FUNC_ONLY };\r
87                         };\r
88                 } else\r
89                 if( alt_context ){\r
90                         obj  = { x : alt_context, k : X.Callback._HANDLEEVENT };\r
91                         arg3 = arg1;\r
92                 } else {\r
93                         console.log( '不正 ' + arg1 );\r
94                         console.dir( arg1 );\r
95                         return;\r
96                 };\r
97                 \r
98                 if( X.Type.isArray( arg3 )){\r
99                         obj.s = arg3;\r
100                 };\r
101                 return ( obj.x || obj.s ) ? obj : arg1;\r
102         },\r
103 \r
104         _proxyCallback : function( xfunc ){\r
105                 var args    = xfunc.a || [],\r
106                         thisObj = xfunc.x,\r
107                         func    = xfunc.f,\r
108                         supp    = xfunc.s,\r
109                         temp, ret;\r
110                 \r
111                 delete xfunc.a;         \r
112                 \r
113                 if( supp && supp.length ){\r
114                         temp = [];\r
115                         args.length &&\r
116                                 (\r
117                                         args.length === 1 ?\r
118                                                 ( temp[ 0 ] = args[ 0 ] ) :\r
119                                                 temp.push.apply( temp, args )\r
120                                 );\r
121                         supp.length === 1 ?\r
122                                 ( temp[ temp.length ] = supp[ 0 ] ) :\r
123                                 temp.push.apply( temp, supp );\r
124                         args = temp;\r
125                 };\r
126                 \r
127                 switch( xfunc.k ){\r
128 \r
129                         case X.Callback._THIS_FUNC :\r
130                                 return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );\r
131                                 \r
132                         case X.Callback._HANDLEEVENT :\r
133                                 temp = thisObj[ 'handleEvent' ];\r
134                                 if( X.Type.isFunction( temp ) ){\r
135                                         return args.length === 0 ? thisObj[ 'handleEvent' ]() :\r
136                                                    args.length === 1 ? thisObj[ 'handleEvent' ]( args[ 0 ] ) : temp.apply( thisObj, args );\r
137                                 };\r
138                                 break;\r
139                                 /*\r
140                                 if( temp !== func && X.Type.isFunction( temp ) ){\r
141                                         return args.length === 0 ? thisObj[ 'handleEvent' ]() : temp.apply( thisObj, args );\r
142                                 } else\r
143                                 if( X.Type.isFunction( thisObj ) ){\r
144                                         return args.length === 0 ? thisObj.call( thisObj ) : thisObj.apply( thisObj, args );\r
145                                 };\r
146                                 return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );*/\r
147                                                         \r
148                         case X.Callback._FUNC_ONLY :\r
149                                 return args.length === 0 ?\r
150                                                 func() :\r
151                                         args.length === 1 ?\r
152                                                 func( args[ 0 ] ) :\r
153                                                 func.apply( null, args );\r
154                 };\r
155                 return X.Callback.NONE;\r
156         },\r
157         \r
158         _kill : function(){\r
159                 X.Callback._correct( this );\r
160         },\r
161         _same : function( arg1, arg2, arg3 ){\r
162                 var hash;\r
163                 \r
164                 if( arg1 && arg1[ 'kill' ] === X.Callback._kill ) return this === arg1;\r
165                 \r
166                 hash = X.Callback._classifyCallbackArgs( arg1, arg2, arg3 );\r
167                 \r
168                 return hash && this.k === hash.k && this.x === hash.x && this.f === hash.f && this.s === hash.s;\r
169         },\r
170         _correct : function( f ){\r
171                 var i = X.Callback._LIVE_LIST.indexOf( f );\r
172                 //delete f._;\r
173                 delete f.k;\r
174                 if( f.x ) delete f.x;\r
175                 if( f.f ) delete f.f;\r
176                 if( f.s ) delete f.s;\r
177                 if( i === -1 ) return;\r
178                 X.Callback._LIVE_LIST.splice( i, 1 );\r
179                 X.Callback._POOL_LIST.push( f );\r
180         },\r
181         \r
182         sys_monitor : function(){\r
183                 return {\r
184                         'Live callback' : X.Callback._LIVE_LIST.length,\r
185                         'Pool callback' : X.Callback._POOL_LIST.length\r
186                 };\r
187         },\r
188         sys_gc : function(){\r
189                 var list = X.Callback._POOL_LIST,\r
190                         f;\r
191                 while( 0 < list.length ){\r
192                         f = list.shift();\r
193                         X.Callback._correct( f );\r
194                         delete f[ '_' ];\r
195                         delete f[ 'kill' ];\r
196                         delete f[ 'same' ];\r
197                 };\r
198         }\r
199 };\r
200 \r
201 console.log( 'X.Core.Callback' );\r
202 \r