OSDN Git Service

Version 0.6.41, fix for Opera8 & NN7.2+.
[pettanr/clientJs.git] / 0.6.x / js / core / 05_XTimer.js
index 7f3900c..6df8821 100644 (file)
@@ -7,12 +7,15 @@ X.Timer = ( function(){
                clearTimeout   = window.clearTimeout,\r
                INTERVAL_TIME  = 16,\r
                TICKET_LIST    = [],\r
-               timerId        = -1,\r
+               uid            = 0,\r
+               timerId        = 0,\r
+               endTime        = 0,\r
                next           = 0,\r
                INDEX_TIME     = 0,\r
                INDEX_LAST     = 1,\r
                INDEX_COUNT    = 2,\r
-               INDEX_CALLBACK = 3;\r
+               INDEX_CALLBACK = 3,\r
+               INDEX_UID      = 4;\r
        \r
        function loop(){\r
                var c    = next,\r
@@ -25,16 +28,16 @@ X.Timer = ( function(){
                        f   = queue[ INDEX_CALLBACK ];\r
                        c   = queue[ INDEX_COUNT ];\r
                        ret = f();\r
-                       if( ret === false || ret & X.Callback.UN_LISTEN || c === 1 ){\r
+                       if( ret & X.Callback.UN_LISTEN || c === 1 ){\r
                                list.splice( i, 1 );\r
-                               f.kill();\r
+                               f.kill && f.kill();\r
                                queue.length = 0;\r
                                continue;\r
                        } else\r
                        if( 1 < c ) --queue[ INDEX_COUNT ];\r
                        queue[ INDEX_LAST ] = queue[ INDEX_TIME ];\r
            };\r
-           timerId = -1;\r
+           timerId = 0;\r
            update();\r
        };\r
        function update(){\r
@@ -44,19 +47,62 @@ X.Timer = ( function(){
                        last;\r
                if( l === 0 ){\r
                        timerId !== -1 && clearTimeout( timerId );\r
-                       timerId = -1;\r
+                       timerId = 0;\r
                        return;\r
                };\r
            for( ; l; ){\r
                ( last = list[ --l ][ INDEX_LAST ] ) < n && ( n = last );\r
            };\r
-           if( n < next || timerId === -1 ){\r
-               timerId !== -1 && clearTimeout( timerId );\r
-               timerId = setTimeout( loop, INTERVAL_TIME * n );\r
+           if( n < next || timerId === 0 ){\r
+               timerId !== 0 && clearTimeout( timerId );\r
+               timerId   = setTimeout( loop, INTERVAL_TIME * n );\r
+               endTime   = X.getTime() + INTERVAL_TIME * n;\r
                next = n;\r
            };\r
        };\r
        \r
+       // http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
+       // iOS6 スクロール中のタイマー発火絡みのバグ備忘\r
+       if( X.UA.iOS ){\r
+                window.addEventListener( 'scroll', function(){\r
+                       if( timerId ){\r
+                               clearTimeout( timerId );\r
+                               timerId = setTimeout( loop, Math.max( 0, endTime - X.getTime() ) );\r
+                       };\r
+                } );\r
+       };\r
+       \r
+       var enterFrame =\r
+                       window.requestAnimationFrame ||\r
+                       window.webkitRequestAnimationFrame ||\r
+                       window.mozRequestAnimationFrame ||\r
+                       window.oRequestAnimationFrame ||\r
+                       window.msRequestAnimationFrame ||\r
+                       0,\r
+               cancelFrame =\r
+                       window.cancelRequestAnimationFrame ||\r
+                       window.webkitCancelAnimationFrame ||\r
+                       window.webkitCancelRequestAnimationFrame ||\r
+                       window.mozCancelRequestAnimationFrame ||\r
+                       window.oCancelRequestAnimationFrame ||\r
+                       window.msCancelRequestAnimationFrame ||\r
+                       0,\r
+               REQUEST_FRAME_LIST = [],\r
+               requestID;\r
+       \r
+       function onEnterFrame( time ){\r
+               var list = REQUEST_FRAME_LIST,\r
+                       i    = list.length,\r
+                       f;\r
+               time = time || ( Date.now ? Date.now() : +new Date );\r
+           for( ; i; ){\r
+               ( f = list[ --i ] )( time );\r
+               delete f.uid;\r
+               f.kill && f.kill();\r
+           };\r
+           list.length = 0;\r
+       };\r
+       \r
        return {\r
                add : function( time, opt_count, args1, args2, args3 ){\r
                        time = time < INTERVAL_TIME ? 1 : ( time / INTERVAL_TIME ) | 0; // 正の数で使える「Math.floor(x)」を「(x | 0)」に;\r
@@ -68,35 +114,58 @@ X.Timer = ( function(){
                                opt_count = 0;\r
                        };\r
 \r
-                       TICKET_LIST[ TICKET_LIST.length ] = [ time, time, opt_count, X.Callback.create( args1, args2, args3 ) ];\r
+                       TICKET_LIST[ TICKET_LIST.length ] = [ time, time, opt_count, X.Callback.create( args1, args2, args3 ), ++uid ];\r
                    update();\r
+                   return uid;\r
                },\r
                once : function( time, args1, args2, args3 ){\r
-                       X.Timer.add( time, 1, args1, args2, args3 );\r
+                       return X.Timer.add( time, 1, args1, args2, args3 );\r
                },\r
-               remove : function( args1, args2 ){\r
-                       var queue,\r
-                               i    = 0,\r
-                               list = TICKET_LIST;\r
-                       if( !callback ) return;\r
-                       while( queue = list[ i ] ){\r
-                               if( queue[ INDEX_CALLBACK ].same( args1, args2 ) === true ){\r
-                                       callback.kill();\r
+               remove : function( uid ){\r
+                       var list = TICKET_LIST,\r
+                               i    = list.length,\r
+                               l    = i,\r
+                               f, q;\r
+                       for( ; i; ){\r
+                               if( ( q = list[ --i ] )[ INDEX_UID ] === uid ){\r
                                        list.splice( i, 1 );\r
+                                       f = q[ INDEX_CALLBACK ];\r
+                                       f.kill && f.kill();\r
+                                       ( /* q[ INDEX_COUNT ] <= next  || */ l === 1 ) && update();\r
+                                       q.length = 0;\r
                                        break;\r
-                               } else {\r
-                                       ++i;\r
                                };\r
                        };\r
-                   update();\r
-               }\r
+               },\r
                \r
                // string only ie4-\r
-               ,_loop : X.UA.IE && X.UA.IE < 5 && (function(){\r
-                       var _loop = loop;\r
+               _loop : X.UA.IE && X.UA.IE < 5 && (function( r ){\r
                        loop = 'X.Timer._loop()';\r
-                       return _loop;\r
-               })()\r
+                       return r;\r
+               })( loop ),\r
                \r
+               requestFrame : function( args1, args2, args3 ){\r
+                       var i = REQUEST_FRAME_LIST.length,\r
+                               f;\r
+                       i === 0 && ( requestID = ( enterFrame ? enterFrame( onEnterFrame ) : X.Timer.add( 0, 1, onEnterFrame ) ) );\r
+                       f = REQUEST_FRAME_LIST[ i ] = X.Callback.create( args1, args2, args3 );\r
+                       return f.uid = ++uid;\r
+               },\r
+               cancelFrame : function( uid ){\r
+                       var list = REQUEST_FRAME_LIST,\r
+                               l    = list.length,\r
+                               i    = l,\r
+                               f;\r
+                       for( ; i; ){\r
+                               if( ( f = list[ --i ] ).uid < uid ) break;\r
+                               if( f.uid === uid ){\r
+                                       list.splice( i, 1 );\r
+                                       delete f.uid;\r
+                                       f.kill && f.kill();\r
+                                       l === 1 && ( cancelFrame ? cancelFrame( requestID ) : X.Timer.remove( requestID ) );\r
+                                       break;\r
+                               };\r
+                       };\r
+               }\r
        };\r
 })();
\ No newline at end of file