OSDN Git Service

Version 0.6.205, bug fixes X.Net.Form, update X.HTMLAudio for iOS7+.
authoritozyun <itozyun@user.sourceforge.jp>
Tue, 5 Jan 2016 02:04:45 +0000 (11:04 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Tue, 5 Jan 2016 02:04:45 +0000 (11:04 +0900)
0.6.x/js/06_net/00_XNet.js
0.6.x/js/06_net/02_XNetJSONP.js
0.6.x/js/06_net/03_XNetForm.js
0.6.x/js/07_audio/01_XWebAudio.js
0.6.x/js/07_audio/02_XHTMLAudio.js

index 2a75d06..469669d 100644 (file)
  * <h4>必須プロパティ</h4>\r
  * <dl>\r
  * <dt>url<dd>URL\r
- * <dt>type<dd>'xhr', 'jsonp', 'image', 'img'\r
+ * <dt>type<dd>'xhr', 'jsonp', 'form', 'image', 'img'\r
  * <dt>xhr<dd>URL { url : 'hoge', type : 'xhr' } の省略形\r
  * <dt>jsonp<dd>URL { url : 'hoge', type : 'jsonp' } の省略形\r
+ * <dt>form<dd>URL { url : 'hoge', type : 'form' } の省略形\r
  * <dt>image, img<dd>URL { url : 'hoge', type : 'image' } の省略形\r
  * </dl>\r
  * <h4>XHR 用プロパティ</h4>\r
  * <dt>params<dd>url パラメータを object で渡すことが出来る。\r
  * <dt>callbackName<dd>callback(json) コールバック名が固定されている際に指定。または &callback=hoge 以外の名前でコールバックを指定する場合に params と callbackName に書いておく。url パラメータに callback が無く、callbackName もない場合、フレームワーク内で自動で設定される\r
  * <dt>charset<dd>ページと異なるjsonpを読み込む場合に指定 'EUC-JP', 'Shift-JIS' 等 script タグの charset に入る。https://code.google.com/p/ajaxzip3/issues/detail?id=5\r
- * <dt>useFireWall<dd>異なるドメインに jsonp を読み込んだ後、xdomain iframe 通信を使ってデータを受け取る。不正なコードの実行を防ぐことが出来る、未実装\r
+ * <dt>useFireWall<dd>異なるドメインに jsonp を読み込んだ後、xdomain iframe 通信を使ってデータを受け取る。不正なコードの実行を防ぐことが出来る(はず)、未実装\r
  * </dl>\r
  * \r
  * <h4>Form 用プロパティ</h4>\r
  * <dl>\r
- * <dt>params<dd>url パラメータを object で渡すことが出来る。\r
  * <dt>method<dd>'GET' or 'POST'\r
- * <dt>target<dd>'_self', '_parent', '_top' の場合、ページから離脱する。target を指定せず同一ドメインの場合 response に body.innerHTML が返る。\r
+ * <dt>params<dd>パラメータ object は input タグの name & value に展開される。object を入れ子にすることはできない。\r
+ * <dt>target<dd>'_self', '_parent', '_top' の場合、ページから離脱する。target を指定せず同一ドメインの場合 response に body.innerHTML が返る。TODO X.Window\r
+ * <dt>timeout<dd>ms タイムアウト時間、省略可能\r
+ * <dt>charset<dd>未実装\r
  * </dl>\r
  * \r
  * @alias X.Net\r
@@ -155,8 +158,8 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ](
                                        opt[ 'auth' ] = auth; // auth は deep copy されるとまずい\r
                                };\r
                                \r
-                               // params を url に追加\r
-                               if( opt[ 'params' ] ){\r
+                               // params を url に追加 但し form は除く\r
+                               if( opt[ 'params' ] && type !== X_NET_TYPE_FORM ){\r
                                        url = X_URL_create( url, opt[ 'params' ] );\r
                                        delete opt[ 'params' ];\r
                                };                              \r
index b233d7b..ed9b2d3 100644 (file)
@@ -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';
index 244e5d3..66a1bac 100644 (file)
@@ -1,6 +1,8 @@
 //{+netform"<form>によるGETとPOST"(動的に生成したフォームによるGETとPOST。)[+net,+ninjaiframe]\r
 \r
-var X_FormSender_errorTimerID, X_FormSender_onloadCount = 0;\r
+var X_FormSender_errorTimerID,\r
+       X_FormSender_isLeave,\r
+       X_FormSender_onloadCount = 0;\r
 \r
 X_TEMP.X_FormSender_init = function(){\r
        X_FormSender = X_Class_override( X_NinjaIframe(), X_TEMP.X_FormSender_params );\r
@@ -13,7 +15,7 @@ X_TEMP.X_FormSender_init = function(){
 \r
 /*\r
  * form 構築時に "><script> といった文字列の挿入を禁止するために " を エスケープする\r
- * TODO 改行文字を消す\r
+ * TODO 改行文字を消す escape?\r
  */\r
 function X_FormSender_escapeQuote( str ){\r
        \r
@@ -21,28 +23,29 @@ function X_FormSender_escapeQuote( str ){
 };\r
 \r
 X_TEMP.X_FormSender_params = {\r
-       \r
+\r
                        _busy     : false,\r
                        _canceled : false,\r
                        \r
-                       timeout   : 1000,\r
-                       isJump    : false, // ページを離脱するか?\r
-                       \r
                        load : function( option ){\r
                                //createURL\r
-                               var params  = option[ 'params' ] || {},\r
-                                       target  = option[ 'target' ],\r
+                               var params  = option[ 'params'  ] || {},\r
+                                       target  = option[ 'target'  ],\r
+                                       timeout = option[ 'timeout' ],\r
+                                       // http://search.web-sun.com/zatu/charset.html\r
+                                       // charset = option[ 'charset' ],\r
                                        html, k;\r
                                        \r
                                target = target === '_self' ? '_parent' : target === '_blank' ? '_self' : target || '_self',\r
                                html   = [\r
+                                       // <meta http-equiv="Content-Type" content="text/html; charset=euc-jp">\r
                                        '<form method="', X_FormSender_escapeQuote( option[ 'method' ] || 'GET' ), \r
                                                '" action="', X_FormSender_escapeQuote( option[ 'url' ] || '' ), \r
                                                '" target="', X_FormSender_escapeQuote( target ),\r
                                                '">' ];\r
                                \r
-                               if( target === '_top' || target === '_parent' ) X_FormSender.isJump = true;\r
-                               if( 0 <= option[ 'timeout' ] ) X_FormSender.timeout = option[ 'timeout' ];\r
+                               X_FormSender_isLeave = target === '_top' || target === '_parent';\r
+\r
                                \r
                                for( k in params ){\r
                                        // TODO 使用すべきでない name\r
@@ -51,11 +54,15 @@ X_TEMP.X_FormSender_params = {
                                };\r
                                \r
                                html.push( '</form><script>document.forms[0].submit();</script>' );\r
-                               \r
+\r
                                X_FormSender\r
                                        [ 'refresh' ]( html.join( '' ) )\r
                                        [ 'listen' ]( [ 'ninjaload', 'ninjaerror' ], X_FormSender_iframeListener );\r
-                                                       \r
+                               \r
+                               if( 0 < timeout ){\r
+                                       X_FormSender_errorTimerID = X_FormSender[ 'asyncDispatch' ]( timeout, { type : X_EVENT_ERROR, 'timeout' : true } );\r
+                               };\r
+                                               \r
                                X_FormSender._busy = true;\r
                        },\r
                        \r
@@ -66,8 +73,9 @@ X_TEMP.X_FormSender_params = {
                        \r
                        reset : function(){\r
                                X_FormSender._busy = X_FormSender._canceled = false;\r
-                               X_FormSender[ 'unlisten' ]( [ 'ninjaload', 'ninjaerror' ], X_FormSender_iframeListener );\r
-                               X_FormSender[ 'refresh' ]( '' );\r
+                               X_FormSender\r
+                                       [ 'unlisten' ]( [ 'ninjaload', 'ninjaerror' ], X_FormSender_iframeListener )\r
+                                       [ 'refresh' ]( '' );\r
                                X_FormSender_errorTimerID && X_Timer_remove( X_FormSender_errorTimerID );\r
                                X_FormSender_errorTimerID = X_FormSender_onloadCount = 0;\r
                        }\r
@@ -78,18 +86,13 @@ function X_FormSender_iframeListener( e ){
        \r
        switch( e.type ){\r
                case 'ninjaload' :\r
-                       if( X_FormSender.isJump ){\r
+                       if( X_FormSender_isLeave ){\r
                                return;\r
                        };\r
                        \r
                        if( ++X_FormSender_onloadCount === 1 ){\r
-                               X_FormSender_errorTimerID = X_FormSender[ 'asyncDispatch' ]( X_FormSender.timeout, { type : X_EVENT_ERROR, 'timeout' : true } );\r
-\r
-                               // TODO レスポンスの html にアクセスしたい場合\r
-                               // TODO samedomain or xiframe-sender\r
-                               \r
                                idoc = this[ '_rawObject' ].contentDocument || this._iwin.document,\r
-                               \r
+\r
                                X_FormSender[ 'asyncDispatch' ]( { type : X_EVENT_SUCCESS, response : idoc && idoc.body ? idoc.body.innerHTML : '' } );\r
                        };\r
                        break;\r
index 5d7124e..a59f2d2 100644 (file)
@@ -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,
index 7acc1e0..f9b82f5 100644 (file)
@@ -39,8 +39,9 @@
 \r
 var\r
        X_HTMLAudio,\r
-       \r
-       // ended が発生しない timeupdate 内で play() を呼ぶ (未検証) 不具合確認は iOS4,6\r
+       // iOS7.1, 8.3 で確認.seeking -> seeked の間の currentTime の値が全くあてにならないので無視する。\r
+       X_HTMLAudio_seekingFixIOS   = 7 <= X_UA[ 'iOS' ],\r
+       // ended が発生しない timeupdate 内で play() を呼ぶ (未検証) 不具合確認は iOS4,6 iOS7.1,8.3ではpause->ended起きてる 但し iOS7.1 でも 6 と同じ症状になることがある\r
        X_HTMLAudio_endedFixIOS     = X_UA[ 'iOS' ] < 7,\r
        // Android 2.3.5 で ended 時に audio.src='';audio.src=src;audio.load() を実施。 2.3.4 でも問題なし。\r
        X_HTMLAudio_endedFixAOSP2   = X_UA[ 'AOSP' ] < 3,\r
@@ -59,17 +60,21 @@ var
         * win opera12 volume, mute の変更が2度目以降できない\r
         */\r
        X_HTMLAudio_volumeEnabled   = !( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) && !X_UA[ 'Opera' ],\r
-       // Gecko PC + Android でseek時に再生がしばしば止まる問題の修正\r
+       // Gecko PC + Android でseek時に再生がしばしば止まる問題の修正、iOS8でも確認\r
        X_HTMLAudio_needPlayForSeek = X_UA[ 'iOS' ] || X_UA[ 'Gecko' ],\r
        // \r
        X_HTMLAudio_pauseFix            = 12 <= X_UA[ 'Opera' ] && 0 < ' XP XPSP2 2003|XP64'.indexOf( X_UA[ 'Windows' ] ), // XP + Opera12 のみ?\r
 \r
        X_HTMLAudio_need1stTouch        = X_UA[ 'iOS' ] || 4.2 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ] || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ),\r
 \r
-       X_HTMLAudio_playTrigger     = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ? 'canplay' : X_UA[ 'iOS' ] ? 'suspend' : X_UA[ 'Blink' ] < 32 ? 'stalled' : 'canplaythrough',\r
+       X_HTMLAudio_playTrigger     = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ? 'canplay' :\r
+                                                                       X_UA[ 'iOS' ] < 8 ? 'suspend' :    // iOS7.x以下\r
+                                                                       X_UA[ 'iOS' ] ? 'loadedmetadata' : // iOS8以上は\r
+                                                                       X_UA[ 'Blink' ] < 32 ? 'stalled' : 'canplaythrough',\r
 \r
-       X_HTMLAudio_durationFix     = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ||\r
-                                                               ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'Blink' ] < 36 && X_UA[ 'Android' ] ),\r
+       X_HTMLAudio_durationFix     = // iOS8.1(シュミレータでは不要)\r
+                                                                 X_UA[ 'iOS' ] < 8 || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ||\r
+                                                                 ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'Blink' ] < 36 && X_UA[ 'Android' ] ),\r
 \r
        X_HTMLAudio_shortPlayFix        = X_UA[ 'AOSP' ],\r
        \r
@@ -109,6 +114,8 @@ if( X_Audio_constructor ){
                        \r
                        _endedFixON               : false,\r
                        \r
+                       _seekingFixON     : false,\r
+                       \r
                        'Constructor' : function( disatcher, source, option ){\r
                                var raw;\r
                                \r
@@ -146,7 +153,8 @@ if( X_Audio_constructor ){
                                                //'loadstart', 'load',\r
                                                'progress', //'error',\r
                                                // 'suspend', 'abort', 'emptied', 'stalled',\r
-                                               // 'play', 'pause', 'seeked', 'ratechange', 'volumechange',\r
+                                               // 'play', 'pause', 'ratechange', 'volumechange',\r
+                                               'seeked',\r
                                                'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough',\r
                                                'playing', 'waiting', 'seeking',\r
                                                'durationchange', 'timeupdate', 'ended' ] );\r
@@ -161,7 +169,7 @@ if( X_Audio_constructor ){
                                                'durationchange', 'timeupdate', 'ended' ], this.onDebug );\r
 \r
                                if( X_HTMLAudio_endedFixAOSP2 || X_HTMLAudio_endedFixAOSP4 ){\r
-                                       raw.loop = true; // loop を使えば ended で止まること回避できるかも 但し ended イベントが起きなくなる\r
+                                       raw.loop = true; // loop を使えば ended で止まること回避できる 但し ended イベントが起きなくなる\r
                                };\r
 \r
                                if( X_HTMLAudio_need1stTouch ){\r
@@ -252,6 +260,9 @@ if( X_Audio_constructor ){
        \r
                                        // TODO firefox で 短い音声でtimeupdate, ended が発火しない <- 最後の音に無音部分を追加する\r
                                        case 'timeupdate' :      //     通常の再生が行われ現在の再生位置の変化が起こった場合に発生\r
+                                               if( this._seekingFixON ){\r
+                                                       eventType = X_EVENT_MEDIA_SEEKING;\r
+                                               } else\r
                                                if( this._durationFixPhase === 8 ){\r
                                                        this._durationFixPhase = 0;\r
                                                        this._readyState |= 1;\r
@@ -271,9 +282,13 @@ if( X_Audio_constructor ){
                                                        end = X_Audio_getEndTime( this ) + this._shortPlayFixTime;\r
                                                        //console.log( now + ' / ' + end );\r
                                                        if( ( 0 + end <= 0 + now ) || // 0+ なぜか iem9 で必要,,,\r
-                                                               ( now < this._lastCurrentTime ) ){ // loop した場合\r
+                                                               ( now < this._lastCurrentTime && now < 2000 ) ){\r
+                                                               //( ( X_HTMLAudio_endedFixAOSP2 || X_HTMLAudio_endedFixAOSP4 ) && ( now < this._lastCurrentTime && now < 1000 ) ) ){\r
+                                                                       // loop して0付近に戻った場合\r
+                                                                       // iOS8.4 ではこのタイミングで now が last より 0.1秒後退している場合がある\r
+                                                                       // iOS7.1 ではもっと小さい場合がある,,,\r
                                                                if( this.autoLoop ){\r
-                                                                       console.log( '☆★☆ 曲の最後に到達 @timeupdate now-end:' + ( now - end ) );\r
+                                                                       console.log( '☆★☆ 曲の最後に到達 @timeupdate now-end:' + ( now - end ) + ' now:' + now + ' last:' + this._lastCurrentTime );\r
                                                                        ended = true;\r
                                                                        //if( X_HTMLAudio_endedFixIOS ) actualEnded = true;\r
                                                                } else {\r
@@ -310,16 +325,20 @@ if( X_Audio_constructor ){
                                                eventType = !this._durationFixPhase && !this._endedFixON ? X_EVENT_MEDIA_PLAYING : X_EVENT_MEDIA_WAITING;\r
                                        //case 'play' :            //   再生が開始された。play()メソッドからの復帰後に発生する場合に発生\r
                                        //case 'pause' :                  //    再生が一時停止された。pauseメソッドからの復帰後に発生する場合に発生\r
-                                       //case 'seeked' : \r
                                        //case 'ratechange' :    // defaultPlaybackRate属性とplaybackRate属性のどちらかが更新された場合に発生\r
                                        //case 'volumechange' :   // volume属性とmuted属性のどちらかが変化した場合に発生\r
                                                break;\r
                                        \r
+                                       case 'seeked' :\r
+                                               if( this._seekingFixON ) this._seekingFixON = false;\r
+                                               break;\r
+                                       \r
                                        case 'waiting' :                //      次のフレームが利用不可のため再生を停止したが、そのフレームがやがて利用可能になると想定している場合に発生\r
                                                eventType = X_EVENT_MEDIA_WAITING;\r
                                                break;\r
                                        case 'seeking' :                //      シークがtrueに変化し、イベントを発生させるのに十分な時間がシーク操作にかかっている場合に発生\r
                                                eventType = X_EVENT_MEDIA_SEEKING;\r
+                                               if( X_HTMLAudio_seekingFixIOS ) this._seekingFixON = true;\r
                                                break;\r
                                };\r
                                \r