OSDN Git Service

Fix the bug of X.NodeAnime.
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 16_XTimer.js
index 4df6372..b8c50ff 100644 (file)
@@ -44,9 +44,7 @@ var
         */\r
        X_Timer_now = Date.now || ( function(){ return +new Date; } ),\r
 \r
-       X_Timer_SET_TIMEOUT   = window.setTimeout,\r
-       X_Timer_CLEAR_TIMEOUT = window.clearTimeout,\r
-\r
+       // TODO X.AF.request, X.AF.cancel\r
        // http://uupaa.hatenablog.com/entry/2012/02/01/083607\r
        // Firefox 4 partial (request only), Mobile Firefox5 ready (request only), Firefox 11 ready (cancel impl)       \r
        X_Timer_REQ_ANIME_FRAME =\r
@@ -58,6 +56,7 @@ var
                false,\r
 \r
        X_Timer_CANCEL_ANIME_FRAME =\r
+               window.cancelAnimationFrame ||\r
                window.cancelRequestAnimationFrame ||\r
                window.webkitCancelAnimationFrame ||\r
                window.webkitCancelRequestAnimationFrame ||\r
@@ -96,18 +95,18 @@ var
                                f;\r
                        i === 0 && ( X_Timer_requestID = X_Timer_REQ_ANIME_FRAME( X_Timer_onEnterFrame ) );\r
                        f = X_Closure_classifyCallbackArgs( args1, args2, args3 );\r
-                       if( !f.kind ) f = { func : f };\r
+                       if( !f.cbKind ) f = { func : f };\r
                        X_Timer_REQ_FRAME_LIST[ i ] = f;\r
-                       return f.uid = ++X_Timer_uid;\r
+                       return f._uid = ++X_Timer_uid;\r
                }) :\r
                (function( args1, args2, args3 ){\r
                        var i = X_Timer_REQ_FRAME_LIST.length,\r
                                f;\r
                        i === 0 && ( X_Timer_requestID = X_Timer_add( 0, 1, X_Timer_onEnterFrame ) );\r
                        f = X_Closure_classifyCallbackArgs( args1, args2, args3 );\r
-                       if( !f.kind ) f = { func : f };\r
+                       if( !f.cbKind ) f = { func : f };\r
                        X_Timer_REQ_FRAME_LIST[ i ] = f;\r
-                       return f.uid = ++X_Timer_uid;\r
+                       return f._uid = ++X_Timer_uid;\r
                }),\r
 \r
        /**\r
@@ -131,8 +130,8 @@ var
                                X_Timer_removal[ uid ] = true;\r
                        } else {\r
                                for( ; i; ){\r
-                                       if( ( f = list[ --i ] ).uid < uid ) break;\r
-                                       if( f.uid == uid ){\r
+                                       if( ( f = list[ --i ] )._uid < uid ) break;\r
+                                       if( f._uid == uid ){\r
                                                list.splice( i, 1 );\r
                                                // gecko では cancelRequestAnimationFrame が無い場合がある\r
                                                l === 1 && X_Timer_CANCEL_ANIME_FRAME && X_Timer_CANCEL_ANIME_FRAME( X_Timer_requestID );\r
@@ -154,8 +153,8 @@ var
                                X_Timer_removal[ uid ] = true;\r
                        } else {\r
                                for( ; i; ){\r
-                                       if( ( f = list[ --i ] ).uid < uid ) break;\r
-                                       if( f.uid == uid ){\r
+                                       if( ( f = list[ --i ] )._uid < uid ) break;\r
+                                       if( f._uid == uid ){\r
                                                list.splice( i, 1 );\r
                                                l === 1 && X_Timer_remove( X_Timer_requestID );\r
                                                break;\r
@@ -182,6 +181,8 @@ var
  * @alias X.Timer\r
  */ \r
 X[ 'Timer' ] = {\r
+       // TODO IE4 の resolution は 64ms\r
+       'RESOLUTION'   : X_Timer_INTERVAL_TIME,\r
 \r
        'now'          : X_Timer_now,\r
        \r
@@ -215,6 +216,7 @@ X[ 'Timer' ] = {
        function X_Timer_add( time, opt_count, args1, args2, args3 ){\r
                var list = X_Timer_TICKET_LIST,\r
                        hash, obj;\r
+\r
                time = time < X_Timer_INTERVAL_TIME ? 1 : time / X_Timer_INTERVAL_TIME | 0; // 正の数で使える「Math.floor(x)」を「(x | 0)」に;\r
                \r
                if( !X_Type_isNumber( opt_count ) ){\r
@@ -227,11 +229,11 @@ X[ 'Timer' ] = {
                hash = X_Closure_classifyCallbackArgs( args1, args2, args3 );\r
                if( !hash ) return -1; // dev only\r
                \r
-               if( !hash.kind ) hash = { func : hash };\r
-               hash.time  = time;\r
-               hash.last  = time;\r
-               hash.count = opt_count;\r
-               hash.uid   = ++X_Timer_uid;\r
+               if( !hash.cbKind ) hash = { func : hash };\r
+               hash._time  = time;\r
+               hash.last   = time;\r
+               hash._count = opt_count;\r
+               hash._uid   = ++X_Timer_uid;\r
                list[ list.length ] = hash;\r
                \r
            !X_Timer_busyTimeout && X_Timer_update();\r
@@ -270,7 +272,7 @@ X[ 'Timer' ] = {
                        X_Timer_removal[ uid ] = true;\r
                } else {\r
                        for( ; i; ){\r
-                               if( ( q = list[ --i ] ).uid == uid ){ // 数字の場合と文字の場合がある\r
+                               if( ( q = list[ --i ] )._uid == uid ){ // 数字の場合と文字の場合がある\r
                                        list.splice( i, 1 );\r
                                        \r
                                        /*\r
@@ -289,7 +291,7 @@ X[ 'Timer' ] = {
        };\r
 \r
 if( X_UA[ 'IE4' ] || X_UA[ 'MacIE' ] ){\r
-       X.Timer[ '_' ] = X_Timer_onTimeout;\r
+       X[ 'Timer' ][ '_' ] = X_Timer_onTimeout;\r
        X_Timer_onTimeout = 'X.Timer._()';\r
 };\r
 \r
@@ -314,17 +316,17 @@ function X_Timer_onTimeout(){
     for( ; i < l; ++i ){\r
        q = list[ i ];\r
        if(\r
-               ( X_Timer_removal && X_Timer_removal[ q.uid ] ) || // timerId は remove 登録されている\r
+               ( X_Timer_removal && X_Timer_removal[ q._uid ] ) || // timerId は remove 登録されている\r
                        0 < ( q.last -= minus ) || // 時間が経過していない\r
                        heavy && ( q.last = 1 ) // 時間は経過したが、ヘビーフラグが立っている\r
                ){\r
                        continue;\r
                };\r
-               c = q.count;\r
+               c = q._count;\r
                \r
-               X_Timer_currentUID = q.uid;\r
+               X_Timer_currentUID = q._uid;\r
                \r
-               if( q.kind ){\r
+               if( q.cbKind ){\r
                        r = X_Closure_proxyCallback( q, [] );\r
                } else {\r
                        r = q.func();\r
@@ -344,8 +346,8 @@ function X_Timer_onTimeout(){
                        --l;\r
                        continue;\r
                } else\r
-               if( 1 < c ) --q.count;\r
-               q.last = q.time;\r
+               if( 1 < c ) --q._count;\r
+               q.last = q._time;\r
     };\r
     X_Timer_timerId     = X_Timer_currentUID = 0;\r
     X_Timer_busyTimeout = false;\r
@@ -360,6 +362,8 @@ function X_Timer_onTimeout(){
        X_Timer_removal = null;\r
     };\r
     X_Timer_update();\r
+    \r
+    ExecuteAtEnd_onEnd();\r
 };\r
 \r
 function X_Timer_update(){\r
@@ -367,30 +371,35 @@ function X_Timer_update(){
                i    = list.length,\r
                n;\r
        if( i === 0 ){\r
-               X_Timer_timerId && X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+               X_Timer_timerId && clearTimeout( X_Timer_timerId );\r
                X_Timer_timerId = 0;\r
                return;\r
        };\r
        \r
        1 < i && list.sort( X_Timer_compareQueue );\r
        \r
-    n = list[ i - 1 ].last;\r
+    n = list[ 0 ].last;\r
     \r
     if( n < X_Timer_waitTime || X_Timer_timerId === 0 ){\r
        if( X_Timer_timerId ){\r
-               X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
-               n -= ( X_Timer_now() - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME | 0;\r
+               clearTimeout( X_Timer_timerId );\r
+               n -= ( X_Timer_now() - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME;\r
                0 <= n || ( n = 0 ); // 負の数は 0 に\r
        };\r
        X_Timer_timeStamp = X_Timer_now();\r
-       X_Timer_timerId   = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n );\r
+       X_Timer_timerId   = setTimeout( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n | 0 );\r
        X_Timer_waitTime  = n;\r
     };\r
 };\r
 \r
-// 大きい -> 小さい\r
+// 小さい -> 大きい、 同値の場合  uid の小さいものが先\r
+// http://jsfiddle.net/warby_/X8YUZ/ Chrome で return が 0 の場合の挙動が他のブラウザと異なる\r
 function X_Timer_compareQueue( a, b ){\r
-       return a.last < b.last ? 1 : a.last === b.last ? 0 : -1;\r
+    if( a.last === b.last ){ // Chrome のみ\r
+        return a._uid - b._uid;\r
+    };\r
+    return a.last - b.last;\r
+       // return a.last <= b.last ? -1 : 1; //a.last === b.last ? 0 : 1;\r
 };\r
 \r
 // http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
@@ -399,10 +408,10 @@ if( X_UA[ 'iOS' ] ){
        window.addEventListener( 'scroll', function(){\r
                var last, now;\r
                if( X_Timer_timerId ){\r
-                       X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+                       clearTimeout( X_Timer_timerId );\r
                        now               = X_Timer_now();\r
                        last              = X_Timer_timeStamp + X_Timer_INTERVAL_TIME * X_Timer_waitTime - now;\r
-                       X_Timer_timerId   = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, 0 < last ? last : 0 );\r
+                       X_Timer_timerId   = setTimeout( X_Timer_onTimeout, 0 < last ? last : 0 );\r
                        // 更新\r
                        X_Timer_timeStamp = now;\r
                        X_Timer_waitTime  = last / X_Timer_INTERVAL_TIME | 0;\r
@@ -424,9 +433,9 @@ function X_Timer_onEnterFrame( time ){
     for( ; i < l; ++i ){\r
        q = list[ i ];\r
        \r
-       if( X_Timer_removal && X_Timer_removal[ q.uid ] ) continue;\r
+       if( X_Timer_removal && X_Timer_removal[ q._uid ] ) continue;\r
        \r
-               if( q.kind ){\r
+               if( q.cbKind ){\r
                        X_Closure_proxyCallback( q, args || ( args = [ time ] ) );\r
                } else {\r
                        q.func( time );\r
@@ -446,6 +455,8 @@ function X_Timer_onEnterFrame( time ){
        };\r
        X_Timer_removal = null;\r
     };\r
+    \r
+    ExecuteAtEnd_onEnd();\r
 };\r
 \r
 console.log( 'X.Core.Timer' );\r