OSDN Git Service

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