console.log( '>> Android : ' + X_UA[ 'Android' ] );\r
} else\r
if( dua.indexOf( 'Android;' ) !== -1 ){\r
- // Fennec 用\r
- X_UA[ 'Android' ] = 2;\r
+ // Fennec41- 用\r
+ // https://developer.mozilla.org/ja/docs/Gecko_user_agent_string_reference\r
+ // バージョン 41 以降の Android 版 Firefox では platform トークンに Android バージョンが含まれます。\r
+ // 相互運用性向上のため、Android 4 以前のバージョンでブラウザが動作している場合は 4.4 と出力します。\r
+ // Android バージョン 4 以降では実際のバージョン番号が出力されます。\r
+ // なお、Gecko エンジンはすべての Android バージョンに対して同じ機能を提供しています。\r
+ X_UA[ 'Android' ] = 2.2;\r
};\r
};\r
\r
*/\r
X_UA[ 'NDS' ] = dua.indexOf( 'Nitro' ) !== -1;\r
console.log( '>> Opera : ' + v );\r
- return;\r
- };\r
+ } else\r
\r
// Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko\r
if( document.all || dav.indexOf( 'Trident/' ) !== -1 ){\r
\r
console.log( '>> IE : ' + v + ' ActiveX : ' + X_UA[ 'ActiveX' ] + ' IEHost : ' + X_UA[ 'IEHost' ] );\r
// TODO XBox360, XBox1, Modern or Desktop, Standalone\r
- return;\r
- };\r
+ } else\r
\r
// \r
if( ( i = dua.indexOf( 'NetFront\/' ) !== -1 ) ){\r
*/\r
X_UA[ 'NetFront' ] = parseFloat( dua.substr( i + 9 ) ) || 0.1;\r
console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] );\r
- return;\r
- };\r
+ } else\r
\r
if( X_UA[ 'Linux' ] && tv === 2 && dua.indexOf( 'Sony\/COM2\/' ) !== -1 ){\r
X_UA[ 'NetFront' ] = 3.4;\r
console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] );\r
- return;\r
- };\r
+ } else\r
\r
if( ( i = dua.toUpperCase().indexOf( 'PLAYSTATION 3' ) !== -1 ) ){\r
/**\r
*/\r
X_UA[ 'PS3' ] = parseFloat( dua.substr( i + 15 ) ) || 0.1;\r
console.log( '>> PS3 : ' + X_UA[ 'PS3' ] );\r
- return;\r
- };\r
+ } else\r
\r
if( ( i = dua.indexOf( 'iCab' ) !== -1 ) ){\r
/**\r
*/\r
X_UA[ 'iCab' ] = parseFloat( dua.substr( i + 5 ) ) || 0.1;\r
console.log( '>> iCab : ' + X_UA[ 'iCab' ] );\r
- return;\r
- };\r
+ } else\r
\r
if( 0 < dua.indexOf( 'Gecko\/' ) && ( i = dua.indexOf( 'rv:' ) ) ){\r
v = dua.substr( i + 3 ).split( '.' );\r
* @type {number}\r
*/\r
X_UA[ 'Gecko' ] = parseFloat( v[ 0 ] ) || 0 +\r
- ( parseFloat( v[ 1 ] ) || 0 ) / 10 +\r
- ( parseFloat( v[ 2 ] ) || 0 ) / 100;\r
+ ( parseFloat( v[ 1 ] ) || 0 ) / 10;\r
/**\r
* @alias X.UA.GeckoMajor\r
* @type {number}\r
*/\r
X_UA[ 'Fennec' ] = parseFloat( dua.substr( i + 7 ) );\r
console.log( '>> Fennec : ' + X_UA[ 'Fennec' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );\r
- return;\r
- };\r
+ } else\r
+ if( X_UA[ 'Android' ] ){\r
+ X_UA[ 'Fennec' ] = X_UA[ 'Gecko' ];\r
+ } else\r
//Firefox\r
\r
//Netscape\r
*/\r
X_UA[ 'NN6' ] = true;\r
console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );\r
- return;\r
} else\r
//Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)\r
//Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3\r
if( ( i = dua.indexOf( 'Netscape/' ) ) !== -1 ){\r
X_UA[ 'NN' ] = parseFloat( dua.substr( i + 9 ) ) || 7;\r
console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );\r
- return;\r
} else\r
//Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6\r
if( ( i = dua.indexOf( 'Navigator/' ) ) !== -1 ){\r
X_UA[ 'NN' ] = parseFloat( dua.substr( i + 10 ) ) || 9;\r
console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );\r
- return;\r
};\r
\r
console.log( '>> Gecko : ' + X_UA[ 'Gecko' ] );\r
}; \r
\r
console.log( '>> Webkit : ' + X_UA[ 'WebKit' ] + ' Safari : ' + X_UA[ 'Safari' ] );\r
- };\r
- \r
- if( dua.toLowerCase().indexOf( 'iris' ) !== -1 ){\r
- /**\r
- * http://www.useragentstring.com/pages/Iris/\r
- * @alias X.UA.Iris\r
- * @type {boolean}\r
- */\r
- X_UA[ 'Iris' ] = true;\r
- };\r
- \r
- if( // Kobo Mozilla/5.0 (Linux; U; Android 2.0; en-us;) AppleWebKit/533.1 (KHTML, like Gecko) Verson/4.0 Mobile Safari/533.1 (Kobo Touch)\r
- dua.indexOf( 'Kobo' ) !== -1 ||\r
- // Kindle paperwhite Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+\r
- dua.indexOf( 'Kindle' ) !== -1 ||\r
- // Sony Reader Mozilla/5.0 (Linux; U; ja-jp; EBRD1101; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\r
- dua.indexOf( 'EBRD' ) !== -1\r
- ){\r
+ \r
+ if( dua.toLowerCase().indexOf( 'iris' ) !== -1 ){\r
/**\r
- * Kobo, Kindle, Sony Reader\r
- * @alias X.UA.EInk\r
+ * http://www.useragentstring.com/pages/Iris/\r
+ * @alias X.UA.Iris\r
* @type {boolean}\r
*/\r
- X_UA[ 'EInk' ] = true;\r
+ X_UA[ 'Iris' ] = true;\r
};\r
+ \r
+ if( // Kobo Mozilla/5.0 (Linux; U; Android 2.0; en-us;) AppleWebKit/533.1 (KHTML, like Gecko) Verson/4.0 Mobile Safari/533.1 (Kobo Touch)\r
+ dua.indexOf( 'Kobo' ) !== -1 ||\r
+ // Kindle paperwhite Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+\r
+ dua.indexOf( 'Kindle' ) !== -1 ||\r
+ // Sony Reader Mozilla/5.0 (Linux; U; ja-jp; EBRD1101; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\r
+ dua.indexOf( 'EBRD' ) !== -1\r
+ ){\r
+ /**\r
+ * Kobo, Kindle, Sony Reader\r
+ * @alias X.UA.EInk\r
+ * @type {boolean}\r
+ */\r
+ X_UA[ 'EInk' ] = true;\r
+ }; \r
+ };\r
+\r
})();\r
\r
(function(){\r
X_EVENT_MEDIA_ENDED = 46,\r
X_EVENT_MEDIA_WAITING = 47,\r
X_EVENT_MEDIA_SEEKING = 48,\r
+ X_EVENT_MEDIA_CAN_TOUCH_LOAD = 49,\r
\r
- X_EVENT_NEED_AUTH = 49,\r
+ X_EVENT_NEED_AUTH = 50,\r
\r
- X_EVENT_DEBUG = 50,\r
+ X_EVENT_DEBUG = 51,\r
\r
- X_Event_last = 50;\r
+ X_Event_last = 51;\r
\r
// in_page_jump\r
// on_screen_keyboard_show\r
'MEDIA_ENDED' : X_EVENT_MEDIA_ENDED,\r
'MEDIA_WAITING' : X_EVENT_MEDIA_WAITING,\r
'MEDIA_SEEKING' : X_EVENT_MEDIA_SEEKING,\r
+ 'MEDIA_CAN_TOUCH_LOAD' : X_EVENT_MEDIA_CAN_TOUCH_LOAD,\r
\r
'NEED_AUTH' : X_EVENT_NEED_AUTH,\r
\r
// ------------------------------------------------------------------------- //\r
// ------------ local variables -------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
-\r
-var X_EventDispatcher_once = false,\r
- X_EventDispatcher_lock = false,\r
- X_EventDispatcher_unlock = false,\r
- X_EventDispatcher_needsIndex = false,\r
- \r
- X_EventDispatcher_safariPreventDefault = false, // Safari3-\r
- \r
- /** @const */\r
+var /** @const */\r
X_EventDispatcher_EVENT_TARGET_OTHER = 0,\r
/** @const */\r
X_EventDispatcher_EVENT_TARGET_XHR = 1,\r
/** @const */\r
- X_EventDispatcher_EVENT_TARGET_SILVER_LIGHT = 2,\r
+ X_EventDispatcher_EVENT_TARGET_SILVER_LIGHT = 2;\r
+\r
+var X_EventDispatcher_once = false,\r
+ X_EventDispatcher_lock = false,\r
+ X_EventDispatcher_unlock = false,\r
+ X_EventDispatcher_needsIndex = false,\r
\r
- X_EventDispatcher_LAZY_TIMERS = {}; // Object.<number, X.EventDispatcher> number は timerID\r
+ X_EventDispatcher_safariPreventDefault = false, // Safari3-\r
+\r
+ X_EventDispatcher_LAZY_TIMERS = {},// Object.<number, X.EventDispatcher> number は timerID\r
+ \r
+ // iOS と MacOSX Iron36 で発生。連続してアニメーションが起こると、クロージャの束縛された obj へのアクセスに失敗する。Win では起きない?\r
+ // むしろ、MacOSX のブラウザ全般で起こる??\r
+ X_EventDispatcher_ANIME_EVENTS = ( X_UA[ 'WebKit' ] || X_UA[ 'Blink' ] ) && {\r
+ 'transitionend' : true, 'webkitTransitionEnd' : true, 'mozTransitionEnd' : true, 'oTransitionEnd' : true, 'otransitionEnd' : true,\r
+ 'animationend' : true, 'webkitAnimationEnd' : true, 'oAnimationEnd' : true,\r
+ 'animationstart' : true, 'webkitAnimationStart' : true, 'oAnimationStart' : true,\r
+ 'animationiteration' : true, 'webkitAnimationIteration' : true, 'oAnimationIteration' : true\r
+ };\r
\r
// ------------------------------------------------------------------------- //\r
// --- interface ----------------------------------------------------------- //\r
\r
function X_EventDispatcher_actualAddEvent( that, type, raw, list ){\r
var i, f;\r
+\r
X_EventDispatcher_lock || ( type = X_Event_Rename[ type ] || type );\r
\r
if( X_Type_isArray( type ) ){\r
};\r
\r
default :\r
- // iOS と MacOSX Iron36 で発生。連続してアニメーションが起こると、クロージャの束縛された obj へのアクセスに失敗する。Win では起きない?\r
- // むしろ、MacOSX のブラウザ全般で起こる??\r
- if( ( X_UA[ 'WebKit' ] || X_UA[ 'Blink' ] ) &&\r
- ( type === 'webkitTransitionEnd' || type === 'transitionend' ||\r
- type === 'animationend' || type === 'webkitAnimationEnd' ||\r
- type === 'animationstart' || type === 'webkitAnimationStart' ||\r
- type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){\r
+ if( X_EventDispatcher_ANIME_EVENTS && X_EventDispatcher_ANIME_EVENTS[ type ] ){\r
raw.addEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false );\r
} else {\r
f = that[ '_listeners' ][ X_LISTENERS_ACTUAL_HANDLER ] || ( that[ '_listeners' ][ X_LISTENERS_ACTUAL_HANDLER ] = X_Closure_create( that, X_EventDispatcher_actualHandleEvent ) );\r
\r
function X_EventDispatcher_actualRemoveEvent( that, type, raw, list, skip ){\r
var i;\r
+\r
X_EventDispatcher_unlock || ( type = X_Event_Rename[ type ] || type );\r
\r
if( X_Type_isArray( type ) ){\r
};\r
\r
default :\r
- if( ( X_UA[ 'WebKit' ] || X_UA[ 'Blink' ] ) &&\r
- ( type === 'webkitTransitionEnd' || type === 'transitionend' ||\r
- type === 'animationend' || type === 'webkitAnimationEnd' ||\r
- type === 'animationstart' || type === 'webkitAnimationStart' ||\r
- type === 'animationiteration' || type === 'webkitAnimationIteration' ) ){\r
+ if( X_EventDispatcher_ANIME_EVENTS && X_EventDispatcher_ANIME_EVENTS[ type ] ){\r
raw.removeEventListener( type, X_EventDispatcher_iOSTransitionEndDispatch, false );\r
- } else \r
+ } else\r
if( raw.addEventListener ){\r
raw.removeEventListener( type, that[ '_listeners' ][ X_LISTENERS_ACTUAL_HANDLER ], false );\r
} else {\r
\r
\r
// TODO ブラウザからの呼び出しの最後に登録された関数を呼び出す機能(例えば画面の更新)\r
+var X_EventDispatcher_CURRENT_EVENTS = [];\r
\r
// handleEvent を拡張可能にするために、クロージャに移動した\r
// Is this in regard to the Safari 1.x preventDefault bug on click/dblclick?\r
var X_EventDispatcher_actualHandleEvent =\r
X_UA_EVENT.IE4 || X_UA_EVENT.IE ? // ie45678 EVENT_IE & EVENT_DOM0 for ie4\r
(function(){\r
- var e = event, ret;\r
+ var e = event, ret,\r
+ ev = new X_DomEvent( e, this, this[ '_rawObject' ] );\r
+ \r
+ X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length ] = ev;\r
\r
- ret = this[ 'dispatch' ]( new X_DomEvent( e, this, this[ '_rawObject' ] ) );\r
+ ret = this[ 'dispatch' ]( ev );\r
+\r
+ --X_EventDispatcher_CURRENT_EVENTS.length;\r
\r
if( ret & X_CALLBACK_STOP_PROPAGATION ){\r
e.cancelBubble = true;\r
var ev = new X_DomEvent( e, this ),\r
ret = X_CALLBACK_NONE,\r
i, l;\r
- //console.log( '>>>>>>>>>> ' + e.type );\r
+ \r
+ X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length ] = ev;\r
+\r
// touch event -> pointer\r
if( X_Type_isArray( ev ) ){\r
if( ev.length === 0 ){\r
ret = this[ 'dispatch' ]( ev );\r
};\r
\r
+ --X_EventDispatcher_CURRENT_EVENTS.length;\r
+ \r
if( ret & X_CALLBACK_STOP_PROPAGATION ){\r
e.stopPropagation();\r
};\r
\r
// http://msdn.microsoft.com/ja-jp/library/ie/dn255104%28v=vs.85%29.aspx\r
var X_Dom_Event_devicePixelRatio = window.devicePixelRatio || ( window.screen.deviceXDPI / window.screen.logicalXDPI ),\r
- X_Dom_Event_convertMSPointerType = window.MSPointerEvent && [ 0, 0, 'touch', 'pen', 'mouse' ],/*{\r
+\r
+ X_Dom_Event_convertMSPointerType = ( !window.PointerEvent && window.MSPointerEvent ) && [ 0, 0, 'touch', 'pen', 'mouse' ], // WP8.1 は PointerEvent と MSPointerEvent 両方ある\r
+ /*{\r
'2' : 'touch',\r
'3' : 'pen',\r
'4' : 'mouse'\r
this[ 'pressure' ] = e.pressure || ( e.button !== -1 ? 0.5 : 0 );\r
// ポインターの接触形状の スクリーン ピクセル単位の幅と高さ なので変換。(多分、、、)\r
this[ 'width' ] = e.width / X_Dom_Event_devicePixelRatio;\r
- this[ 'height' ] = e.height / X_Dom_Event_devicePixelRatio; \r
+ this[ 'height' ] = e.height / X_Dom_Event_devicePixelRatio;\r
} else {\r
this[ 'pointerType' ] = e.pointerType;\r
this[ 'pressure' ] = e.pressure;\r
\r
if( type = X_Event_toPointer[ originalType ] ){\r
this[ 'type' ] = type;\r
+ this[ 'pointerType' ] = 'mouse';\r
this[ 'clientX' ] = e.clientX;\r
this[ 'clientY' ] = e.clientY;\r
//this[ 'screenX' ] = e.screenX;\r
var X_WebAudio_context = !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] &&
// Android2 + Gecko で WebAudio が極めて不安定
- !( X_UA[ 'Gecko' ] && X_UA[ 'Android' ] ) &&
+ !X_UA[ 'Fennec' ] &&
// Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる
// Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる
!( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 42 && X_UA[ 'Windows' ] ) &&
* \r
* memo\r
* 1. AOSP4.1 iframe 内の Audio は親に focus が移っても再生を継続する\r
- * 2. AOSP4.2(Genymotion) どこかのタイミングでタッチによる play を行う\r
- * 3. AOSP oggはシークが乱れる m4a, mp3 は優秀\r
+ * 2. AOSP oggはシークが乱れる m4a, mp3 は優秀\r
*/\r
/*\r
* durationFix\r
* -> opera11、10.54 WinXP はまとも、、、 portable が怪しい??\r
*/\r
\r
-var X_HTMLAudio_playTrigger =\r
- X_UA[ 'iOS' ] < 5 ? 'stalled' :\r
- X_UA[ 'iOS' ] < 6 ? 'suspend' :\r
- X_UA[ 'iOS' ] < 7 ? 'suspend' :\r
- X_UA[ 'iOS' ] ? 'loadeddata' :\r
- X_UA[ 'Safari' ] < 4 ? 'canplaythrough' :\r
- X_UA[ 'ChromeWV' ] ? 'canplaythrough' :\r
- // Android 2.3.5(SBM101SH) では stalled は発生しない,,, ので必ず loadeddata もチェックする\r
- //X_UA[ 'AOSP' ] < 3 ? 'stalled' :\r
- //X_UA[ 'AOSP' ] ? 'playing' :\r
- X_UA[ 'OperaMobile' ] || X_UA[ 'OperaTablet' ] ? 'loadeddata' :\r
- 'loadeddata', //'canplay',\r
+var\r
X_HTMLAudio,\r
\r
// ended が発生しない timeupdate 内で play() を呼ぶ (未検証) 不具合確認は iOS4,6\r
// ended 時に play() を実施, currentTime が duration に張り付き更新されなければ src='';src=src を実施。\r
X_HTMLAudio_endedFixAOSP4 = 4 <= X_UA[ 'AOSP' ],\r
// ended 時に play() を実施\r
- X_HTMLAudio_endedFixCWV = X_UA[ 'ChromeWV' ],\r
+ X_HTMLAudio_endedFixCWV = X_UA[ 'ChromeWV' ] || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ),\r
\r
// Opera Mobile 12 は 2回目以降の currentTime へのセットで currentTime が更新されなくなるため、タイマーを使用する\r
X_HTMLAudio_currentTimeFix = !!X_UA[ 'OperaMobile' ] || !!X_UA[ 'OperaTablet' ],\r
// \r
X_HTMLAudio_pauseFix = ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] && 0 < ' XP XPSP2 2003|XP64'.indexOf( X_UA[ 'Windows' ] ) ), // XP + Opera12 のみ?\r
\r
- X_HTMLAudio_need1stTouch = X_UA[ 'iOS' ] || 4 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ], \r
- X_HTMLAudio_durationFix = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ),\r
+ X_HTMLAudio_need1stTouch = X_UA[ 'iOS' ] || 4 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ] || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ),\r
\r
- X_HTMLAudio_shortPlayFix = X_UA[ 'AOSP' ]; // Android 4.1.1 でも遭遇\r
+ X_HTMLAudio_playTrigger = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ? 'canplay' : X_UA[ 'iOS' ] ? 'suspend' : X_UA[ 'Blink' ] ? 'stalled' : 'canplaythrough',\r
\r
+ X_HTMLAudio_durationFix = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ),\r
\r
+ X_HTMLAudio_shortPlayFix = X_UA[ 'AOSP' ]; // Android 4.1.1 でも遭遇\r
\r
if( X_Audio_constructor ){\r
\r
_ready : false, \r
_src : '',\r
\r
+ _touchRequested : false,\r
+ _touched : false,\r
+ \r
_currentFixStart : 0,\r
_currentFixBegin : 0,\r
\r
var raw = this[ '_rawObject' ],\r
actualEnded = e.type === 'ended',\r
ended = actualEnded,\r
- ready = e.type === X_HTMLAudio_playTrigger,\r
+ ready,\r
eventType, duration, end, now;\r
\r
// global に公開\r
break;\r
\r
case 'loadeddata' : // コンテンツの表示を現在の再生位置で初めて行えるようになった場合に発生\r
+ case 'canplaythrough' : // 今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生\r
if( !this._endedFixON ){\r
ready = true;\r
};\r
raw.play();\r
raw.currentTime = 0; // 必要!\r
};\r
- case 'canplaythrough' : // 今すぐに再生を開始してもバッファリングで停止することなく最後まで表示できると予測している場合に発生\r
if( this._endedFixON ){\r
console.log( '▽ onEndedFix の終了 @' + e.type );\r
this._endedFixON = false;\r
};\r
case 'loadedmetadata' : // ブラウザがメディアリソースの長さと寸法を判定した場合に発生\r
case 'durationchange' : // duration属性が更新された場合に発生\r
- if( !this.duration ){\r
+ if( !this.duration || this.duration !== raw.duration * 1000 ){ // Blink28 duration が変わる\r
duration = raw.duration;\r
};\r
break;\r
\r
this._loaded = this._loaded || ready;\r
\r
- // \r
+ //\r
+ if( X_HTMLAudio_need1stTouch && !this._touchRequested ){\r
+ if( e.type === X_HTMLAudio_playTrigger ){\r
+ this._touchRequested = true;\r
+ this.disatcher[ 'asyncDispatch' ]( X_EVENT_MEDIA_CAN_TOUCH_LOAD ); \r
+ };\r
+ } else\r
if( ended ){\r
if( !this._closed && this.autoLoop ){\r
if( !( this.disatcher[ 'dispatch' ]( X_EVENT_MEDIA_BEFORE_LOOP ) & X_CALLBACK_PREVENT_DEFAULT ) ){\r
\r
actualPlay : function( forcePlay, forceReload ){\r
var raw = this[ '_rawObject' ],\r
- begin, end;\r
+ e, begin, end;\r
\r
// もし kill 後に autoplayTimer で呼ばれても、_closed==true なので平気\r
if( this._closed ) return;\r
//return;\r
}; \r
\r
+ if( this._touchRequested && !this._touched ){\r
+ e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ];\r
+ if( !e || !e[ 'pointerType' ] ){\r
+ alert( 'タッチイベント以外での play! ' + e.type );\r
+ return;\r
+ };\r
+ this._touched = true;\r
+ } else\r
if( !this._ready && ( !X_HTMLAudio_durationFix || !X_HTMLAudio_need1stTouch ) ){\r
this.autoplay = true;\r
return;\r
\r
//http://himaxoff.blog111.fc2.com/blog-entry-97.html\r
//Firefox3.6では一度も play() していない状態で currentTime = 0 を実行するとエラーになる。\r
- //また、GoogleChrome7 では currentTime = 0 直後に play() すると、pause()した位置前後の音が混ざることがある。(少なくとも自分の環境では) \r
- raw.currentTime = this._lastCurrentTime;\r
+ //また、GoogleChrome7 では currentTime = 0 直後に play() すると、pause()した位置前後の音が混ざることがある。(少なくとも自分の環境では)\r
+\r
+ // iOS で duration が 0 の時に触ると error\r
+ if( !X_HTMLAudio_durationFix || this.duration ) raw.currentTime = this._lastCurrentTime;\r
+\r
console.log( '[HTMLAudio] play ' + begin + ' -> ' + end + ' crt:' + ( raw.currentTime | 0 ) + ' last:' + this._lastCurrentTime );\r
\r
if( forceReload || ( X_HTMLAudio_endedFixAOSP4 && raw.duration && raw.currentTime === raw.duration ) ){\r
};\r
\r
time -= X_Audio_getEndTime( this );\r
- if( time < 0 ){\r
+ if( time < -50 ){\r
console.log( ' > まだ終わらない ' + time );\r
this._ended && this[ '_rawObject' ].play();\r
this._ended = false;\r
var i = 0, l = X_AudioSprite_TEMP.tracks.length;\r
\r
for( ; i < l; ++i ){\r
- if( X_UA[ 'iOS' ] ){\r
- X_AudioSprite_TEMP.tracks[ i ][ '_rawObject' ].load();\r
- } else {\r
+ //if( X_UA[ 'iOS' ] ){\r
+ // X_AudioSprite_TEMP.tracks[ i ][ '_rawObject' ].load();\r
+ //} else {\r
X_AudioSprite_instance[ 'pause' ]( i );\r
- };\r
+ //};\r
};\r
},\r
\r
};\r
\r
function X_AudioSprite_backendHandler( e ){\r
- var i, backend, option, src, name, last, _e, touch;\r
+ var i, backend, option, src, name, last, _e;\r
\r
switch( e.type ){\r
case X_EVENT_BACKEND_READY :\r
// touch 可能で backend ready\r
\r
if( name === 'WebAudio' ){\r
- _e[ 'needTouchForPlay' ] = touch = X_WebAudio_need1stTouch;\r
+ if( _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch ){\r
+ last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_instance[ 'asyncDispatch' ], [ _e ] );\r
+ } else {\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
+ };\r
+ last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
} else\r
if( name === 'HTMLAudio' ){\r
- _e[ 'needTouchForLoad' ] = touch = X_HTMLAudio_need1stTouch;\r
- };\r
-\r
- X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
- \r
- console.log( 'AudioSprite - X_EVENT_BACKEND_READY' );\r
- \r
- last[ 'listenOnce' ]( touch && !X_HTMLAudio_durationFix ? X_EVENT_MEDIA_PLAYING : X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
-\r
- // READY, needTouchForPlay, needTouchForLoad\r
- if( /* X_HTMLAudio_durationFix && */ !touch ){\r
- for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){\r
- X_AudioSprite_instance[ 'pause' ]( i );\r
+ if( _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch ){\r
+ last[ 'listenOnce' ]( X_EVENT_MEDIA_CAN_TOUCH_LOAD, X_AudioSprite_instance, X_AudioSprite_instance[ 'asyncDispatch' ], [ _e ] );\r
+ last[ 'listenOnce' ]( !X_HTMLAudio_durationFix ? X_EVENT_MEDIA_PLAYING : X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
+ } else {\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
+ last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
+ \r
+ // READY, needTouchForPlay, needTouchForLoad\r
+ if( X_HTMLAudio_durationFix ){\r
+ for( i = 0; i < X_AudioSprite_TEMP.tracks.length; ++i ){\r
+ X_AudioSprite_instance[ 'pause' ]( i );\r
+ };\r
+ }; \r
};\r
+ \r
+ } else {\r
+ X_AudioSprite_instance[ 'asyncDispatch' ]( _e );\r
+ \r
+ console.log( 'AudioSprite - X_EVENT_BACKEND_READY' );\r
+ \r
+ last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_instance, X_AudioSprite_backendHandler );\r
};\r
- \r
return X_CALLBACK_STOP_NOW;\r
\r
case X_EVENT_BACKEND_NONE :\r