OSDN Git Service

Version 0.6.67, rename folders.
[pettanr/clientJs.git] / 0.6.x / js / 00_core / 05_XTimer.js
1 /**\r
2  * use X.Callback\r
3  */\r
4 \r
5 var _enterFrame =\r
6                 window.requestAnimationFrame ||\r
7                 window.webkitRequestAnimationFrame ||\r
8                 window.mozRequestAnimationFrame ||\r
9                 window.oRequestAnimationFrame ||\r
10                 window.msRequestAnimationFrame ||\r
11                 false,\r
12         _cancelFrame =\r
13                 window.cancelRequestAnimationFrame ||\r
14                 window.webkitCancelAnimationFrame ||\r
15                 window.webkitCancelRequestAnimationFrame ||\r
16                 window.mozCancelRequestAnimationFrame ||\r
17                 window.oCancelRequestAnimationFrame ||\r
18                 window.msCancelRequestAnimationFrame ||\r
19                 false;\r
20 \r
21 X.Timer = {\r
22         INTERVAL_TIME  : 16,\r
23         TICKET_LIST    : [],\r
24         uid            : 0,\r
25         timerId        : 0,\r
26         endTime        : 0, // iOS\r
27         next           : 0,\r
28         busy           : false, // for Opera7\r
29 \r
30         REQ_FRAME_LIST : [],\r
31         requestID      : 0,\r
32         \r
33         _loop : function(){\r
34                 var next = X.Timer.next,\r
35                         list = X.Timer.TICKET_LIST,\r
36                         i    = list.length,\r
37                         q, f, c, r;\r
38                 \r
39                 if( X.Timer.busy ){\r
40                         alert( 'busy!' );\r
41                 };\r
42                 \r
43                 X.Timer.busy = true;\r
44                 \r
45             for( ; i; ){\r
46                 q = list[ --i ];\r
47                         if( 0 < ( q.last -= next ) ) continue;\r
48                         c = q.count;\r
49                         \r
50                         if( q.k ){\r
51                                 q.a = [];\r
52                                 r = X.Callback._proxyCallback( q );\r
53                         } else {\r
54                                 r = q.f();\r
55                         };\r
56                         \r
57                         if( r & X.Callback.UN_LISTEN || c === 1 ){\r
58                                 list.splice( i, 1 );\r
59                                 //f.kill && f.kill();\r
60                                 continue;\r
61                         } else\r
62                         if( 1 < c ) --q.count;\r
63                         q.last = q.time;\r
64             };\r
65             X.Timer.timerId = 0;\r
66             X.Timer.busy = false;\r
67             X.Timer._update();  \r
68         },\r
69         _update : function(){\r
70                 var list = X.Timer.TICKET_LIST,\r
71                         i    = list.length,\r
72                         n    = Infinity,\r
73                         l;\r
74                 if( i === 0 ){\r
75                         X.Timer.timerId && window.clearTimeout( X.Timer.timerId );\r
76                         X.Timer.timerId = 0;\r
77                         return;\r
78                 };\r
79             for( ; i; ){\r
80                 ( l = list[ --i ].last ) < n && ( n = l );\r
81             };\r
82             if( n < X.Timer.next || X.Timer.timerId === 0 ){\r
83                 X.Timer.timerId && window.clearTimeout( X.Timer.timerId );\r
84                 X.Timer.timerId = window.setTimeout( X.Timer._loop, X.Timer.INTERVAL_TIME * n );\r
85                 X.Timer.endTime = X.getTime() + X.Timer.INTERVAL_TIME * n; // iOS\r
86                 X.Timer.next = n;\r
87             };\r
88         },\r
89         \r
90         _onEnterFrame : function ( time ){\r
91                 var list = X.Timer.REQ_FRAME_LIST,\r
92                         i    = list.length,\r
93                         q;\r
94                 time = time || ( Date.now ? Date.now() : +new Date );\r
95             for( ; i; ){\r
96                 q = list[ --i ];\r
97                 \r
98                         if( q.k ){\r
99                                 q.a = [ time ];\r
100                                 X.Callback._proxyCallback( q );\r
101                         } else {\r
102                                 q.f( time );\r
103                         };\r
104                 //delete f.uid;\r
105                 //f.kill && f.kill();\r
106             };\r
107             list.length = 0;\r
108         },\r
109         \r
110         add : function( time, opt_count, args1, args2, args3 ){\r
111                 var list = X.Timer.TICKET_LIST,\r
112                         hash, obj;\r
113                 time = time < X.Timer.INTERVAL_TIME ? 1 : time / X.Timer.INTERVAL_TIME | 0; // 正の数で使える「Math.floor(x)」を「(x | 0)」に;\r
114                 \r
115                 if( !X.Type.isNumber( opt_count ) ){\r
116                         args3 = args2;\r
117                         args2 = args1;\r
118                         args1 = opt_count;\r
119                         opt_count = 0;\r
120                 };\r
121                 \r
122                 hash = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
123                 if( !hash ) return -1; // dev only\r
124                 \r
125                 if( !hash.k ) hash = { f : hash };\r
126                 hash.time  = time;\r
127                 hash.last  = time;\r
128                 hash.count = opt_count;\r
129                 hash.uid   = ++X.Timer.uid;\r
130                 list[ list.length ] = hash;\r
131                 \r
132             !X.Timer.busy && X.Timer._update();\r
133             return X.Timer.uid;\r
134         },\r
135         once : function( time, args1, args2, args3 ){\r
136                 return X.Timer.add( time, 1, args1, args2, args3 );\r
137         },\r
138         remove : function( uid ){\r
139                 var list = X.Timer.TICKET_LIST,\r
140                         i    = list.length,\r
141                         l    = i,\r
142                         f, q;\r
143                 for( ; i; ){\r
144                         // TODO\r
145                         // fire 中の cancel\r
146                         if( ( q = list[ --i ] ).uid === uid ){\r
147                                 list.splice( i, 1 );\r
148                                 //f = q.f;\r
149                                 //f.kill && f.kill();\r
150                                 !X.Timer.busy && ( /* q[ INDEX_COUNT ] <= next  || */ l === 1 ) && X.Timer._update();\r
151                                 //q.length = 0;\r
152                                 break;\r
153                         };\r
154                 };\r
155         },\r
156         \r
157         requestFrame : _enterFrame ?\r
158                 (function( args1, args2, args3 ){\r
159                         var i = X.Timer.REQ_FRAME_LIST.length,\r
160                                 f;\r
161                         i === 0 && ( X.Timer.requestID = _enterFrame( X.Timer._onEnterFrame ) );\r
162                         f = X.Timer.REQ_FRAME_LIST[ i ] = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
163                         return f.uid = ++X.Timer.uid;\r
164                 }) :\r
165                 (function( args1, args2, args3 ){\r
166                         var i = X.Timer.REQ_FRAME_LIST.length,\r
167                                 f;\r
168                         i === 0 && ( X.Timer.requestID = X.Timer.add( 0, 1, X.Timer._onEnterFrame ) );\r
169                         f = X.Timer.REQ_FRAME_LIST[ i ] = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
170                         return f.uid = ++X.Timer.uid;\r
171                 }),\r
172         \r
173         cancelFrame : _cancelFrame ?\r
174                 (function( uid ){\r
175                         var list = X.Timer.REQ_FRAME_LIST,\r
176                                 l    = list.length,\r
177                                 i    = l,\r
178                                 f;\r
179                         for( ; i; ){\r
180                                 if( ( f = list[ --i ] ).uid < uid ) break;\r
181                                 if( f.uid === uid ){\r
182                                         // TODO\r
183                                         // fire 中の cancel\r
184                                         list.splice( i, 1 );\r
185                                         //delete f.uid;\r
186                                         //f.kill && f.kill();\r
187                                         l === 1 && _cancelFrame( X.Timer.requestID );\r
188                                         break;\r
189                                 };\r
190                         };\r
191                 }) :\r
192                 (function( uid ){\r
193                         var list = X.Timer.REQ_FRAME_LIST,\r
194                                 l    = list.length,\r
195                                 i    = l,\r
196                                 f;\r
197                         for( ; i; ){\r
198                                 if( ( f = list[ --i ] ).uid < uid ) break;\r
199                                 if( f.uid === uid ){\r
200                                         list.splice( i, 1 );\r
201                                         //delete f.uid;\r
202                                         //f.kill && f.kill();\r
203                                         l === 1 && X.Timer.remove( X.Timer.requestID );\r
204                                         break;\r
205                                 };\r
206                         };\r
207                 })\r
208         \r
209 };\r
210 \r
211 // http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
212 // iOS6 スクロール中のタイマー発火絡みのバグ備忘\r
213 if( X.UA.iOS ){\r
214         window.addEventListener( 'scroll', function(){\r
215                 if( X.Timer.timerId ){\r
216                         window.clearTimeout( X.Timer.timerId );\r
217                         X.Timer.timerId = window.setTimeout( X.Timer._loop, Math.max( 0, X.Timer.endTime - X.getTime() ) );\r
218                 };\r
219         });\r
220 };\r
221 \r
222 if( X.UA.IE < 5 || X.UA.MacIE ){\r
223         X.Timer[ '_ie_loop' ] = X.Timer._loop;\r
224         X.Timer._loop = 'X.Timer._ie_loop()';\r
225 };\r
226 \r
227 console.log( 'X.Core.Timer' );\r