From 3c54df5e0d4f20eb32cfd73480cbc9ae8358ebbf Mon Sep 17 00:00:00 2001 From: itozyun Date: Tue, 5 Jan 2016 11:04:45 +0900 Subject: [PATCH] Version 0.6.205, bug fixes X.Net.Form, update X.HTMLAudio for iOS7+. --- 0.6.x/js/06_net/00_XNet.js | 15 ++++++++----- 0.6.x/js/06_net/02_XNetJSONP.js | 5 +---- 0.6.x/js/06_net/03_XNetForm.js | 45 ++++++++++++++++++++------------------ 0.6.x/js/07_audio/01_XWebAudio.js | 8 ++++--- 0.6.x/js/07_audio/02_XHTMLAudio.js | 41 ++++++++++++++++++++++++---------- 5 files changed, 69 insertions(+), 45 deletions(-) diff --git a/0.6.x/js/06_net/00_XNet.js b/0.6.x/js/06_net/00_XNet.js index 2a75d06..469669d 100644 --- a/0.6.x/js/06_net/00_XNet.js +++ b/0.6.x/js/06_net/00_XNet.js @@ -22,9 +22,10 @@ *

必須プロパティ

*
*
url
URL - *
type
'xhr', 'jsonp', 'image', 'img' + *
type
'xhr', 'jsonp', 'form', 'image', 'img' *
xhr
URL { url : 'hoge', type : 'xhr' } の省略形 *
jsonp
URL { url : 'hoge', type : 'jsonp' } の省略形 + *
form
URL { url : 'hoge', type : 'form' } の省略形 *
image, img
URL { url : 'hoge', type : 'image' } の省略形 *
*

XHR 用プロパティ

@@ -50,14 +51,16 @@ *
params
url パラメータを object で渡すことが出来る。 *
callbackName
callback(json) コールバック名が固定されている際に指定。または &callback=hoge 以外の名前でコールバックを指定する場合に params と callbackName に書いておく。url パラメータに callback が無く、callbackName もない場合、フレームワーク内で自動で設定される *
charset
ページと異なるjsonpを読み込む場合に指定 'EUC-JP', 'Shift-JIS' 等 script タグの charset に入る。https://code.google.com/p/ajaxzip3/issues/detail?id=5 - *
useFireWall
異なるドメインに jsonp を読み込んだ後、xdomain iframe 通信を使ってデータを受け取る。不正なコードの実行を防ぐことが出来る、未実装 + *
useFireWall
異なるドメインに jsonp を読み込んだ後、xdomain iframe 通信を使ってデータを受け取る。不正なコードの実行を防ぐことが出来る(はず)、未実装 * * *

Form 用プロパティ

*
- *
params
url パラメータを object で渡すことが出来る。 *
method
'GET' or 'POST' - *
target
'_self', '_parent', '_top' の場合、ページから離脱する。target を指定せず同一ドメインの場合 response に body.innerHTML が返る。 + *
params
パラメータ object は input タグの name & value に展開される。object を入れ子にすることはできない。 + *
target
'_self', '_parent', '_top' の場合、ページから離脱する。target を指定せず同一ドメインの場合 response に body.innerHTML が返る。TODO X.Window + *
timeout
ms タイムアウト時間、省略可能 + *
charset
未実装 *
* * @alias X.Net @@ -155,8 +158,8 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ]( opt[ 'auth' ] = auth; // auth は deep copy されるとまずい }; - // params を url に追加 - if( opt[ 'params' ] ){ + // params を url に追加 但し form は除く + if( opt[ 'params' ] && type !== X_NET_TYPE_FORM ){ url = X_URL_create( url, opt[ 'params' ] ); delete opt[ 'params' ]; }; diff --git a/0.6.x/js/06_net/02_XNetJSONP.js b/0.6.x/js/06_net/02_XNetJSONP.js index b233d7b..ed9b2d3 100644 --- a/0.6.x/js/06_net/02_XNetJSONP.js +++ b/0.6.x/js/06_net/02_XNetJSONP.js @@ -68,7 +68,6 @@ X_TEMP.X_JSONP_params = { load : function( option ){ //createURL var url = option[ 'url' ], - params = option[ 'params' ], callback = option[ 'callbackName' ], charset = option[ 'charset' ], json2Path = window.RegExp ? 'js/libs/json2.js' : 'js/libs/json2_regfree.js', @@ -79,9 +78,7 @@ X_TEMP.X_JSONP_params = { if( !X_URL_isSameProtocol( url ) ){ return X_JSONP[ 'asyncDispatch' ]( X_EVENT_ERROR ); }; - - url = X_URL_create( url, params ); - + if( !callback && !( callback = X_URL_paramToObj( url.split( '?' )[ 1 ] )[ 'callback' ] ) ){ url += '&callback=cb'; callback = 'cb'; diff --git a/0.6.x/js/06_net/03_XNetForm.js b/0.6.x/js/06_net/03_XNetForm.js index 244e5d3..66a1bac 100644 --- a/0.6.x/js/06_net/03_XNetForm.js +++ b/0.6.x/js/06_net/03_XNetForm.js @@ -1,6 +1,8 @@ //{+netform"
によるGETとPOST"(動的に生成したフォームによるGETとPOST。)[+net,+ninjaiframe] -var X_FormSender_errorTimerID, X_FormSender_onloadCount = 0; +var X_FormSender_errorTimerID, + X_FormSender_isLeave, + X_FormSender_onloadCount = 0; X_TEMP.X_FormSender_init = function(){ X_FormSender = X_Class_override( X_NinjaIframe(), X_TEMP.X_FormSender_params ); @@ -13,7 +15,7 @@ X_TEMP.X_FormSender_init = function(){ /* * form 構築時に ">' ); - + X_FormSender [ 'refresh' ]( html.join( '' ) ) [ 'listen' ]( [ 'ninjaload', 'ninjaerror' ], X_FormSender_iframeListener ); - + + if( 0 < timeout ){ + X_FormSender_errorTimerID = X_FormSender[ 'asyncDispatch' ]( timeout, { type : X_EVENT_ERROR, 'timeout' : true } ); + }; + X_FormSender._busy = true; }, @@ -66,8 +73,9 @@ X_TEMP.X_FormSender_params = { reset : function(){ X_FormSender._busy = X_FormSender._canceled = false; - X_FormSender[ 'unlisten' ]( [ 'ninjaload', 'ninjaerror' ], X_FormSender_iframeListener ); - X_FormSender[ 'refresh' ]( '' ); + X_FormSender + [ 'unlisten' ]( [ 'ninjaload', 'ninjaerror' ], X_FormSender_iframeListener ) + [ 'refresh' ]( '' ); X_FormSender_errorTimerID && X_Timer_remove( X_FormSender_errorTimerID ); X_FormSender_errorTimerID = X_FormSender_onloadCount = 0; } @@ -78,18 +86,13 @@ function X_FormSender_iframeListener( e ){ switch( e.type ){ case 'ninjaload' : - if( X_FormSender.isJump ){ + if( X_FormSender_isLeave ){ return; }; if( ++X_FormSender_onloadCount === 1 ){ - X_FormSender_errorTimerID = X_FormSender[ 'asyncDispatch' ]( X_FormSender.timeout, { type : X_EVENT_ERROR, 'timeout' : true } ); - - // TODO レスポンスの html にアクセスしたい場合 - // TODO samedomain or xiframe-sender - idoc = this[ '_rawObject' ].contentDocument || this._iwin.document, - + X_FormSender[ 'asyncDispatch' ]( { type : X_EVENT_SUCCESS, response : idoc && idoc.body ? idoc.body.innerHTML : '' } ); }; break; diff --git a/0.6.x/js/07_audio/01_XWebAudio.js b/0.6.x/js/07_audio/01_XWebAudio.js index 5d7124e..a59f2d2 100644 --- a/0.6.x/js/07_audio/01_XWebAudio.js +++ b/0.6.x/js/07_audio/01_XWebAudio.js @@ -79,7 +79,9 @@ if( X_Audio_constructor ){ var X_WebAudio_context = // 4s 以下ではない iPad 2G または iPad mini 1G 以下ではない, iPod touch 4G 以下ではない - !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] && + !X_UA[ 'iPhone_4s' ] && !X_UA[ 'iPad_2Mini1' ] && !X_UA[ 'iPod_4' ] && + // iOS7 以上で HTML Audio が鳴らない問題を見ていくよ + // !X_UA[ 'iOS' ] && // Android2 + Gecko で WebAudio が極めて不安定 !( X_UA[ 'Fennec' ] && X_UA[ 'Android' ] < 3 ) && // AOSP でも WebAudio を不完全に実装するものがある, touch の有無も不明のため一律に切ってしまう @@ -166,7 +168,7 @@ if( X_WebAudio_context ){ _onDecodeSuccess : function( buffer ){ this.onDecodeSuccess && this._onDecodeComplete(); - if ( !buffer ) { + if( !buffer ){ this.errorState = 2; this[ 'asyncDispatch' ]( X_EVENT_COMPLETE ); return; @@ -198,6 +200,7 @@ if( X_WebAudio_context ){ unregister : function( webAudio ){ var list = this.webAudioList, i = list.indexOf( webAudio ); + if( 0 < i ){ list.splice( i, 1 ); if( !list.length ){ @@ -289,7 +292,6 @@ if( X_WebAudio_context ){ if ( !buffer ) { this.error = loader.errorState; - this.disatcher[ 'dispatch' ]({ type : X_EVENT_ERROR, error : loader.errorState, diff --git a/0.6.x/js/07_audio/02_XHTMLAudio.js b/0.6.x/js/07_audio/02_XHTMLAudio.js index 7acc1e0..f9b82f5 100644 --- a/0.6.x/js/07_audio/02_XHTMLAudio.js +++ b/0.6.x/js/07_audio/02_XHTMLAudio.js @@ -39,8 +39,9 @@ var X_HTMLAudio, - - // ended が発生しない timeupdate 内で play() を呼ぶ (未検証) 不具合確認は iOS4,6 + // iOS7.1, 8.3 で確認.seeking -> seeked の間の currentTime の値が全くあてにならないので無視する。 + X_HTMLAudio_seekingFixIOS = 7 <= X_UA[ 'iOS' ], + // ended が発生しない timeupdate 内で play() を呼ぶ (未検証) 不具合確認は iOS4,6 iOS7.1,8.3ではpause->ended起きてる 但し iOS7.1 でも 6 と同じ症状になることがある X_HTMLAudio_endedFixIOS = X_UA[ 'iOS' ] < 7, // Android 2.3.5 で ended 時に audio.src='';audio.src=src;audio.load() を実施。 2.3.4 でも問題なし。 X_HTMLAudio_endedFixAOSP2 = X_UA[ 'AOSP' ] < 3, @@ -59,17 +60,21 @@ var * win opera12 volume, mute の変更が2度目以降できない */ X_HTMLAudio_volumeEnabled = !( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) && !X_UA[ 'Opera' ], - // Gecko PC + Android でseek時に再生がしばしば止まる問題の修正 + // Gecko PC + Android でseek時に再生がしばしば止まる問題の修正、iOS8でも確認 X_HTMLAudio_needPlayForSeek = X_UA[ 'iOS' ] || X_UA[ 'Gecko' ], // X_HTMLAudio_pauseFix = 12 <= X_UA[ 'Opera' ] && 0 < ' XP XPSP2 2003|XP64'.indexOf( X_UA[ 'Windows' ] ), // XP + Opera12 のみ? X_HTMLAudio_need1stTouch = X_UA[ 'iOS' ] || 4.2 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ] || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ), - X_HTMLAudio_playTrigger = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ? 'canplay' : X_UA[ 'iOS' ] ? 'suspend' : X_UA[ 'Blink' ] < 32 ? 'stalled' : 'canplaythrough', + X_HTMLAudio_playTrigger = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ? 'canplay' : + X_UA[ 'iOS' ] < 8 ? 'suspend' : // iOS7.x以下 + X_UA[ 'iOS' ] ? 'loadedmetadata' : // iOS8以上は + X_UA[ 'Blink' ] < 32 ? 'stalled' : 'canplaythrough', - X_HTMLAudio_durationFix = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) || - ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'Blink' ] < 36 && X_UA[ 'Android' ] ), + X_HTMLAudio_durationFix = // iOS8.1(シュミレータでは不要) + X_UA[ 'iOS' ] < 8 || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) || + ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'Blink' ] < 36 && X_UA[ 'Android' ] ), X_HTMLAudio_shortPlayFix = X_UA[ 'AOSP' ], @@ -109,6 +114,8 @@ if( X_Audio_constructor ){ _endedFixON : false, + _seekingFixON : false, + 'Constructor' : function( disatcher, source, option ){ var raw; @@ -146,7 +153,8 @@ if( X_Audio_constructor ){ //'loadstart', 'load', 'progress', //'error', // 'suspend', 'abort', 'emptied', 'stalled', - // 'play', 'pause', 'seeked', 'ratechange', 'volumechange', + // 'play', 'pause', 'ratechange', 'volumechange', + 'seeked', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'seeking', 'durationchange', 'timeupdate', 'ended' ] ); @@ -161,7 +169,7 @@ if( X_Audio_constructor ){ 'durationchange', 'timeupdate', 'ended' ], this.onDebug ); if( X_HTMLAudio_endedFixAOSP2 || X_HTMLAudio_endedFixAOSP4 ){ - raw.loop = true; // loop を使えば ended で止まること回避できるかも 但し ended イベントが起きなくなる + raw.loop = true; // loop を使えば ended で止まること回避できる 但し ended イベントが起きなくなる }; if( X_HTMLAudio_need1stTouch ){ @@ -252,6 +260,9 @@ if( X_Audio_constructor ){ // TODO firefox で 短い音声でtimeupdate, ended が発火しない <- 最後の音に無音部分を追加する case 'timeupdate' : // 通常の再生が行われ現在の再生位置の変化が起こった場合に発生 + if( this._seekingFixON ){ + eventType = X_EVENT_MEDIA_SEEKING; + } else if( this._durationFixPhase === 8 ){ this._durationFixPhase = 0; this._readyState |= 1; @@ -271,9 +282,13 @@ if( X_Audio_constructor ){ end = X_Audio_getEndTime( this ) + this._shortPlayFixTime; //console.log( now + ' / ' + end ); if( ( 0 + end <= 0 + now ) || // 0+ なぜか iem9 で必要,,, - ( now < this._lastCurrentTime ) ){ // loop した場合 + ( now < this._lastCurrentTime && now < 2000 ) ){ + //( ( X_HTMLAudio_endedFixAOSP2 || X_HTMLAudio_endedFixAOSP4 ) && ( now < this._lastCurrentTime && now < 1000 ) ) ){ + // loop して0付近に戻った場合 + // iOS8.4 ではこのタイミングで now が last より 0.1秒後退している場合がある + // iOS7.1 ではもっと小さい場合がある,,, if( this.autoLoop ){ - console.log( '☆★☆ 曲の最後に到達 @timeupdate now-end:' + ( now - end ) ); + console.log( '☆★☆ 曲の最後に到達 @timeupdate now-end:' + ( now - end ) + ' now:' + now + ' last:' + this._lastCurrentTime ); ended = true; //if( X_HTMLAudio_endedFixIOS ) actualEnded = true; } else { @@ -310,16 +325,20 @@ if( X_Audio_constructor ){ eventType = !this._durationFixPhase && !this._endedFixON ? X_EVENT_MEDIA_PLAYING : X_EVENT_MEDIA_WAITING; //case 'play' : // 再生が開始された。play()メソッドからの復帰後に発生する場合に発生 //case 'pause' : // 再生が一時停止された。pauseメソッドからの復帰後に発生する場合に発生 - //case 'seeked' : //case 'ratechange' : // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生 //case 'volumechange' : // volume属性とmuted属性のどちらかが変化した場合に発生 break; + case 'seeked' : + if( this._seekingFixON ) this._seekingFixON = false; + break; + case 'waiting' : // 次のフレームが利用不可のため再生を停止したが、そのフレームがやがて利用可能になると想定している場合に発生 eventType = X_EVENT_MEDIA_WAITING; break; case 'seeking' : // シークがtrueに変化し、イベントを発生させるのに十分な時間がシーク操作にかかっている場合に発生 eventType = X_EVENT_MEDIA_SEEKING; + if( X_HTMLAudio_seekingFixIOS ) this._seekingFixON = true; break; }; -- 2.11.0