OSDN Git Service

Version 0.6.60, fix X.Timer for iOS.
[pettanr/clientJs.git] / 0.6.x / js / 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         REQUEST_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
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.l -= next ) ) continue;\r
48                         f = q.f;\r
49                         c = q.c;\r
50                         if( f() & X.Callback.UN_LISTEN || c === 1 ){\r
51                                 list.splice( i, 1 );\r
52                                 f.kill && f.kill();\r
53                                 //queue.length = 0;\r
54                                 continue;\r
55                         } else\r
56                         if( 1 < c ) --q.c;\r
57                         q.l = q.t;\r
58             };\r
59             X.Timer.timerId = 0;\r
60             X.Timer.busy = false;\r
61             X.Timer._update();  \r
62         },\r
63         _update : function(){\r
64                 var list = X.Timer.TICKET_LIST,\r
65                         i    = list.length,\r
66                         n    = Infinity,\r
67                         l;\r
68                 if( i === 0 ){\r
69                         X.Timer.timerId && window.clearTimeout( X.Timer.timerId );\r
70                         X.Timer.timerId = 0;\r
71                         return;\r
72                 };\r
73             for( ; i; ){\r
74                 ( l = list[ --i ].l ) < n && ( n = l );\r
75             };\r
76             if( n < X.Timer.next || X.Timer.timerId === 0 ){\r
77                 X.Timer.timerId && window.clearTimeout( X.Timer.timerId );\r
78                 X.Timer.timerId = window.setTimeout( X.Timer._loop, X.Timer.INTERVAL_TIME * n );\r
79                 X.Timer.endTime = X.getTime() + X.Timer.INTERVAL_TIME * n; // iOS\r
80                 X.Timer.next = n;\r
81             };\r
82         },\r
83         \r
84         _onEnterFrame : function ( time ){\r
85                 var list = X.Timer.REQUEST_FRAME_LIST,\r
86                         i    = list.length,\r
87                         f;\r
88                 time = time || ( Date.now ? Date.now() : +new Date );\r
89             for( ; i; ){\r
90                 ( f = list[ --i ] )( time );\r
91                 delete f.uid;\r
92                 f.kill && f.kill();\r
93             };\r
94             list.length = 0;\r
95         },\r
96         \r
97         add : function( time, opt_count, args1, args2, args3 ){\r
98                 var list = X.Timer.TICKET_LIST;\r
99                 time = time < X.Timer.INTERVAL_TIME ? 1 : ( time / X.Timer.INTERVAL_TIME ) | 0; // 正の数で使える「Math.floor(x)」を「(x | 0)」に;\r
100                 \r
101                 if( typeof opt_count !== 'number' ){\r
102                         args3 = args2;\r
103                         args2 = args1;\r
104                         args1 = opt_count;\r
105                         opt_count = 0;\r
106                 };\r
107 \r
108                 list[ list.length ] = {\r
109                         t : time,\r
110                         l : time,\r
111                         c : opt_count,\r
112                         f : X.Callback.create( args1, args2, args3 ),\r
113                         u : ++X.Timer.uid\r
114                 };\r
115             !X.Timer.busy && X.Timer._update();\r
116             return X.Timer.uid;\r
117         },\r
118         once : function( time, args1, args2, args3 ){\r
119                 return X.Timer.add( time, 1, args1, args2, args3 );\r
120         },\r
121         remove : function( uid ){\r
122                 var list = X.Timer.TICKET_LIST,\r
123                         i    = list.length,\r
124                         l    = i,\r
125                         f, q;\r
126                 for( ; i; ){\r
127                         // TODO\r
128                         // fire 中の cancel\r
129                         if( ( q = list[ --i ] ).u === uid ){\r
130                                 list.splice( i, 1 );\r
131                                 f = q.f;\r
132                                 f.kill && f.kill();\r
133                                 !X.Timer.busy && ( /* q[ INDEX_COUNT ] <= next  || */ l === 1 ) && X.Timer._update();\r
134                                 //q.length = 0;\r
135                                 break;\r
136                         };\r
137                 };\r
138         },\r
139         \r
140         requestFrame : _enterFrame ?\r
141                 (function( args1, args2, args3 ){\r
142                         var i = X.Timer.REQUEST_FRAME_LIST.length,\r
143                                 f;\r
144                         i === 0 && ( X.Timer.requestID = _enterFrame( X.Timer._onEnterFrame ) );\r
145                         f = X.Timer.REQUEST_FRAME_LIST[ i ] = X.Callback.create( args1, args2, args3 );\r
146                         return f.uid = ++X.Timer.uid;\r
147                 }) :\r
148                 (function( args1, args2, args3 ){\r
149                         var i = X.Timer.REQUEST_FRAME_LIST.length,\r
150                                 f;\r
151                         i === 0 && ( X.Timer.requestID = X.Timer.add( 0, 1, X.Timer._onEnterFrame ) );\r
152                         f = X.Timer.REQUEST_FRAME_LIST[ i ] = X.Callback.create( args1, args2, args3 );\r
153                         return f.uid = ++X.Timer.uid;\r
154                 }),\r
155         \r
156         cancelFrame : _cancelFrame ?\r
157                 (function( uid ){\r
158                         var list = X.Timer.REQUEST_FRAME_LIST,\r
159                                 l    = list.length,\r
160                                 i    = l,\r
161                                 f;\r
162                         for( ; i; ){\r
163                                 if( ( f = list[ --i ] ).uid < uid ) break;\r
164                                 if( f.uid === uid ){\r
165                                         // TODO\r
166                                         // fire 中の cancel\r
167                                         list.splice( i, 1 );\r
168                                         delete f.uid;\r
169                                         f.kill && f.kill();\r
170                                         l === 1 && _cancelFrame( X.Timer.requestID );\r
171                                         break;\r
172                                 };\r
173                         };\r
174                 }) :\r
175                 (function( uid ){\r
176                         var list = X.Timer.REQUEST_FRAME_LIST,\r
177                                 l    = list.length,\r
178                                 i    = l,\r
179                                 f;\r
180                         for( ; i; ){\r
181                                 if( ( f = list[ --i ] ).uid < uid ) break;\r
182                                 if( f.uid === uid ){\r
183                                         list.splice( i, 1 );\r
184                                         delete f.uid;\r
185                                         f.kill && f.kill();\r
186                                         l === 1 && X.Timer.remove( X.Timer.requestID );\r
187                                         break;\r
188                                 };\r
189                         };\r
190                 })\r
191         \r
192 };\r
193 \r
194 // http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
195 // iOS6 スクロール中のタイマー発火絡みのバグ備忘\r
196 if( X.UA.iOS ){\r
197          window.addEventListener( 'scroll', function(){\r
198                 if( X.Timer.timerId ){\r
199                         window.clearTimeout( X.Timer.timerId );\r
200                         X.Timer.timerId = window.setTimeout( X.Timer._loop, Math.max( 0, X.Timer.endTime - X.getTime() ) );\r
201                 };\r
202          } );\r
203 };\r
204 \r
205 if( X.UA.IE && ( X.UA.IE < 5 || X.UA.MacIE ) ){\r
206         X.Timer[ '_ie_loop' ] = X.Timer._loop;\r
207         X.Timer._loop = 'X.Timer._ie_loop()';\r
208 };\r
209 \r
210 console.log( 'X.Core.Timer' );\r