OSDN Git Service

Version 0.6.37, X.Dom.Anime removed.
[pettanr/clientJs.git] / 0.6.x / js / core / 05_XTimer.js
1 /**\r
2  * use X.Callback\r
3  */\r
4 \r
5 X.Timer = ( function(){\r
6         var setTimeout     = window.setTimeout,\r
7                 clearTimeout   = window.clearTimeout,\r
8                 INTERVAL_TIME  = 16,\r
9                 TICKET_LIST    = [],\r
10                 uid            = 0,\r
11                 timerId        = 0,\r
12                 endTime        = 0,\r
13                 next           = 0,\r
14                 INDEX_TIME     = 0,\r
15                 INDEX_LAST     = 1,\r
16                 INDEX_COUNT    = 2,\r
17                 INDEX_CALLBACK = 3,\r
18                 INDEX_UID      = 4;\r
19         \r
20         function loop(){\r
21                 var c    = next,\r
22                         list = TICKET_LIST,\r
23                         i    = list.length,\r
24                         queue, f, ret;\r
25             for( ; i; ){\r
26                 queue = list[ --i ];\r
27                         if( 0 < ( queue[ INDEX_LAST ] -= c ) ) continue;\r
28                         f   = queue[ INDEX_CALLBACK ];\r
29                         c   = queue[ INDEX_COUNT ];\r
30                         ret = f();\r
31                         if( ret & X.Callback.UN_LISTEN || c === 1 ){\r
32                                 list.splice( i, 1 );\r
33                                 f.kill && f.kill();\r
34                                 queue.length = 0;\r
35                                 continue;\r
36                         } else\r
37                         if( 1 < c ) --queue[ INDEX_COUNT ];\r
38                         queue[ INDEX_LAST ] = queue[ INDEX_TIME ];\r
39             };\r
40             timerId = 0;\r
41             update();\r
42         };\r
43         function update(){\r
44                 var list = TICKET_LIST,\r
45                         l    = list.length,\r
46                         n    = 99999999,\r
47                         last;\r
48                 if( l === 0 ){\r
49                         timerId !== -1 && clearTimeout( timerId );\r
50                         timerId = 0;\r
51                         return;\r
52                 };\r
53             for( ; l; ){\r
54                 ( last = list[ --l ][ INDEX_LAST ] ) < n && ( n = last );\r
55             };\r
56             if( n < next || timerId === 0 ){\r
57                 timerId !== 0 && clearTimeout( timerId );\r
58                 timerId   = setTimeout( loop, INTERVAL_TIME * n );\r
59                 endTime   = X.getTime() + INTERVAL_TIME * n;\r
60                 next = n;\r
61             };\r
62         };\r
63         \r
64         // http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
65         // iOS6 スクロール中のタイマー発火絡みのバグ備忘\r
66         if( X.UA.iOS ){\r
67                  window.addEventListener( 'scroll', function(){\r
68                         if( timerId ){\r
69                                 clearTimeout( timerId );\r
70                                 timerId = setTimeout( loop, Math.max( 0, endTime - X.getTime() ) );\r
71                         };\r
72                  } );\r
73         };\r
74         \r
75         var enterFrame =\r
76                         window.requestAnimationFrame ||\r
77                         window.webkitRequestAnimationFrame ||\r
78                         window.mozRequestAnimationFrame ||\r
79                         window.oRequestAnimationFrame ||\r
80                         window.msRequestAnimationFrame ||\r
81                         0,\r
82                 cancelFrame =\r
83                         window.cancelRequestAnimationFrame ||\r
84                         window.webkitCancelAnimationFrame ||\r
85                         window.webkitCancelRequestAnimationFrame ||\r
86                         window.mozCancelRequestAnimationFrame ||\r
87                         window.oCancelRequestAnimationFrame ||\r
88                         window.msCancelRequestAnimationFrame ||\r
89                         0,\r
90                 REQUEST_FRAME_LIST = [],\r
91                 requestID;\r
92         \r
93         function onEnterFrame( time ){\r
94                 var list = REQUEST_FRAME_LIST,\r
95                         i    = list.length,\r
96                         f;\r
97                 time = time || ( Date.now ? Date.now() : +new Date );\r
98             for( ; i; ){\r
99                 ( f = list[ --i ] )( time );\r
100                 delete f.uid;\r
101                 f.kill && f.kill();\r
102             };\r
103             list.length = 0;\r
104         };\r
105         \r
106         return {\r
107                 add : function( time, opt_count, args1, args2, args3 ){\r
108                         time = time < INTERVAL_TIME ? 1 : ( time / INTERVAL_TIME ) | 0; // 正の数で使える「Math.floor(x)」を「(x | 0)」に;\r
109 \r
110                         if( typeof opt_count !== 'number' ){\r
111                                 args3 = args2;\r
112                                 args2 = args1;\r
113                                 args1 = opt_count;\r
114                                 opt_count = 0;\r
115                         };\r
116 \r
117                         TICKET_LIST[ TICKET_LIST.length ] = [ time, time, opt_count, X.Callback.create( args1, args2, args3 ), ++uid ];\r
118                     update();\r
119                     return uid;\r
120                 },\r
121                 once : function( time, args1, args2, args3 ){\r
122                         return X.Timer.add( time, 1, args1, args2, args3 );\r
123                 },\r
124                 remove : function( uid ){\r
125                         var list = TICKET_LIST,\r
126                                 i    = list.length,\r
127                                 l    = i,\r
128                                 f, q;\r
129                         for( ; i; ){\r
130                                 if( ( q = list[ --i ] )[ INDEX_UID ] === uid ){\r
131                                         list.splice( i, 1 );\r
132                                         f = q[ INDEX_CALLBACK ];\r
133                                         f.kill && f.kill();\r
134                                         ( /* q[ INDEX_COUNT ] <= next  || */ l === 1 ) && update();\r
135                                         q.length = 0;\r
136                                         break;\r
137                                 };\r
138                         };\r
139                 },\r
140                 \r
141                 // string only ie4-\r
142                 _loop : X.UA.IE && X.UA.IE < 5 && (function( r ){\r
143                         loop = 'X.Timer._loop()';\r
144                         return r;\r
145                 })( loop ),\r
146                 \r
147                 requestFrame : function( args1, args2, args3 ){\r
148                         var i = REQUEST_FRAME_LIST.length,\r
149                                 f;\r
150                         i === 0 && ( requestID = ( enterFrame ? enterFrame( onEnterFrame ) : X.Timer.add( 0, 1, onEnterFrame ) ) );\r
151                         f = REQUEST_FRAME_LIST[ i ] = X.Callback.create( args1, args2, args3 );\r
152                         return f.uid = ++uid;\r
153                 },\r
154                 cancelFrame : function( uid ){\r
155                         var list = REQUEST_FRAME_LIST,\r
156                                 l    = list.length,\r
157                                 i    = l,\r
158                                 f;\r
159                         for( ; i; ){\r
160                                 if( ( f = list[ --i ] ).uid < uid ) break;\r
161                                 if( f.uid === uid ){\r
162                                         list.splice( i, 1 );\r
163                                         delete f.uid;\r
164                                         f.kill && f.kill();\r
165                                         l === 1 && ( cancelFrame ? cancelFrame( requestID ) : X.Timer.remove( requestID ) );\r
166                                         break;\r
167                                 };\r
168                         };\r
169                 }\r
170         };\r
171 })();