-/**\r
+/*\r
* use X.Callback\r
*/\r
\r
// ------------ local variables -------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
\r
-var X_Timer_now = Date.now || function(){ return +new Date; },\r
+var\r
+\r
+ /**\r
+ * 現在時の ms を返します。 new Date().getTime() の値です。\r
+ * @alias X.Timer.now\r
+ * @function\r
+ * @return {number} ミリ秒\r
+ */\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
X_Timer_REQ_ANIME_FRAME =\r
window.requestAnimationFrame ||\r
window.webkitRequestAnimationFrame ||\r
- window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame ||\r
+ window.mozRequestAnimationFrame ||\r
window.oRequestAnimationFrame ||\r
window.msRequestAnimationFrame ||\r
false,\r
X_Timer_busyTimeout = false,\r
X_Timer_timeStamp = 0, // setTimeout に登録した時間\r
X_Timer_waitTime = 0, // 待ち時間\r
+ X_Timer_currentUID = 0, // 現在発火中の uid\r
\r
X_Timer_REQ_FRAME_LIST = [],\r
X_Timer_requestID = 0,\r
// ------------------------------------------------------------------------- //\r
// --- interface ----------------------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
+\r
+/**\r
+ * <p>setTimeout をラップします。複数のタイマーを登録しても Web ブラウザにはひとつのタイマーを登録します。\r
+ * <p>参考:<a href="http://d.hatena.ne.jp/amachang/20060924/1159084608" target="_blank">複雑で重くなった JavaScript を超高速化する方法3</a>,\r
+ * <a href="http://d.hatena.ne.jp/sawat/20070329" target="_blank">[JavaScript]setIntervalを実験する</a>\r
+ * <p>指定時間の経過したタイマーは、より過去のものから順番にコールバックされます。\r
+ * <p>setTimeout のコールバックに文字列しか指定できないブラウザがあり対策しています。\r
+ * <p>requestAnimationFrame をラップします。ベンダープレフィックス付の requestAnimationFrame もない場合、setTimeout にフォールバックします。\r
+ * \r
+ * @example X.Timer.add( 1000, 5, thisContext, onTimer );\r
+ * \r
+ * @namespace X.Timer\r
+ * @alias X.Timer\r
+ */ \r
X.Timer = {\r
- \r
+\r
now : X_Timer_now,\r
\r
+ /**\r
+ * タイマーをセットします。\r
+ * @param {number} time ミリ秒\r
+ * @param {number} opt_count 回数。省略可能。指定回数で自動でタイマーを破棄します。0 を指定した場合無限にタイマーが呼ばれます。省略した場合 0 と同じです。\r
+ * @param {*} args1 コールバックのための最大で 3 つの引数を指定します。参考:__CallbackHash__\r
+ * @param {*} args2\r
+ * @param {*} args3\r
+ * @return {number} タイマーID。1 以上の数値。タイマーの解除に使用。\r
+ */\r
add : function( time, opt_count, args1, args2, args3 ){\r
var list = X_Timer_TICKET_LIST,\r
hash, obj;\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
+ if( !X_Type_isNumber( opt_count ) ){\r
args3 = args2;\r
args2 = args1;\r
args1 = opt_count;\r
return X_Timer_uid;\r
},\r
\r
+ /**\r
+ * 1 回呼ばれたら解除されるタイマーをセットします。\r
+ * @param {number} time ミリ秒\r
+ * @param {*} args1 コールバックのための最大で 3 つの引数を指定します。参考:__CallbackHash__\r
+ * @param {*} args2\r
+ * @param {*} args3\r
+ * @return {number} タイマーID。1 以上の数値。タイマーの解除に使用。\r
+ */\r
once : function( time, args1, args2, args3 ){\r
return X.Timer.add( time, 1, args1, args2, args3 );\r
},\r
\r
+ /**\r
+ * タイマーを解除します。登録時に受け取ったタイマーIDを使用します。\r
+ * @param {number} タイマーID\r
+ */\r
remove : function( uid ){\r
var list = X_Timer_TICKET_LIST,\r
i = list.length,\r
l = i,\r
- f, q;\r
+ f, q, eventDispatcher, lazy, listeners;\r
// fire 中の cancel\r
if( X_Timer_busyTimeout ){\r
if( !X_Timer_removal ) X_Timer_removal = {};\r
for( ; i; ){\r
if( ( q = list[ --i ] ).uid === uid ){\r
list.splice( i, 1 );\r
+ \r
+ /*\r
+ * lazyDispatch 中の EventDispatcher の有無を調べる\r
+ */\r
+ if( X_EventDispatcher_LAZY_TIMERS[ uid ] ){\r
+ // eventDispatcher = X_EventDispatcher_LAZY_TIMERS[ uid ];\r
+ delete X_EventDispatcher_LAZY_TIMERS[ uid ];\r
+ /*\r
+ listeners = eventDispatcher[ '_listeners' ];\r
+ if( listeners && !listeners[ X_Listeners_.DISPATCHING ] && listeners[ X_Listeners_.KILL_RESERVED ] ){\r
+ for( uid in X_EventDispatcher_LAZY_TIMERS ){\r
+ if( X_EventDispatcher_LAZY_TIMERS[ uid ] === eventDispatcher ){\r
+ lazy = true;\r
+ break;\r
+ };\r
+ }; \r
+ !lazy && eventDispatcher.kill();\r
+ }; */\r
+ };\r
+ \r
!X_Timer_skipUpdate && ( q.last <= X_Timer_waitTime || l === 1 ) && X_Timer_update();\r
break;\r
};\r
};\r
},\r
\r
+ /**\r
+ * requestAnimationFrame をセットします。\r
+ * @function\r
+ * @param {*} args1 コールバックのための最大で 3 つの引数を指定します。参考:__CallbackHash__\r
+ * @param {*} args2\r
+ * @param {*} args3\r
+ * @return {number} タイマーID。1 以上の数値。タイマーの解除に使用。\r
+ */\r
requestFrame : X_Timer_REQ_ANIME_FRAME ?\r
(function( args1, args2, args3 ){\r
var i = X_Timer_REQ_FRAME_LIST.length,\r
f = X_Timer_REQ_FRAME_LIST[ i ] = X_Callback_classifyCallbackArgs( args1, args2, args3 );\r
return f.uid = ++X_Timer_uid;\r
}),\r
- \r
+\r
+ /**\r
+ * requestAnimationFrame を解除します。登録時に受け取ったタイマーIDを使用します。\r
+ * @function\r
+ * @param {number} タイマーID\r
+ */\r
cancelFrame : X_Timer_CANCEL_ANIME_FRAME ?\r
(function( uid ){\r
var list = X_Timer_REQ_FRAME_LIST,\r
if( ( f = list[ --i ] ).uid < uid ) break;\r
if( f.uid === uid ){\r
list.splice( i, 1 );\r
- l === 1 && X_Timer_CANCEL_ANIME_FRAME( X_Timer_requestID );\r
+ // gecko では無い場合がある\r
+ l === 1 && X_Timer_CANCEL_ANIME_FRAME && X_Timer_CANCEL_ANIME_FRAME( X_Timer_requestID );\r
break;\r
};\r
}; \r
// --- implements ---------------------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
\r
-if( X_UA.IE4 || X_UA.MacIE ){\r
+if( X_UA[ 'IE4' ] || X_UA[ 'MacIE' ] ){\r
X.Timer[ '_' ] = X_Timer_onTimeout;\r
X_Timer_onTimeout = 'X.Timer._()';\r
};\r
list = X_Timer_TICKET_LIST,\r
i = 0,\r
l = list.length,\r
- limit = X_Timer_now() + X_Timer_INTERVAL_TIME / 2,\r
+ limit = now + X_Timer_INTERVAL_TIME / 2,\r
heavy,\r
q, f, c, r, uid;\r
\r
};\r
c = q.count;\r
\r
+ X_Timer_currentUID = q.uid;\r
+ \r
if( q.k ){\r
- //q.a = [];\r
r = X_Callback_proxyCallback( q, [] );\r
} else {\r
r = q.f();\r
if( 1 < c ) --q.count;\r
q.last = q.time;\r
};\r
- X_Timer_timerId = 0;\r
+ X_Timer_timerId = X_Timer_currentUID = 0;\r
X_Timer_busyTimeout = false;\r
\r
if( X_Timer_removal ){\r
X_Timer_skipUpdate = true;\r
for( uid in X_Timer_removal ){\r
+ //if( X_EMPTY_OBJECT[ uid ] ) continue;\r
X.Timer.remove( uid );\r
};\r
X_Timer_skipUpdate = false;\r
\r
// http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
// iOS6 スクロール中のタイマー発火絡みのバグ備忘\r
-if( X_UA.iOS ){\r
+if( X_UA[ 'iOS' ] ){\r
window.addEventListener( 'scroll', function(){\r
var last, now;\r
if( X_Timer_timerId ){\r
X_Timer_CLEAR_TIMEOUT( 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
+ 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
// 更新\r
X_Timer_timeStamp = now;\r
X_Timer_waitTime = last / X_Timer_INTERVAL_TIME | 0;\r
X_Timer_busyOnFrame = false;\r
if( X_Timer_removal ){\r
for( uid in X_Timer_removal ){\r
+ //if( X_EMPTY_OBJECT[ uid ] ) continue;\r
X.Timer.cancelFrame( X_Timer_removal[ uid ] );\r
};\r
X_Timer_removal = null;\r