X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F06_net%2F02_XNetJSONP.js;h=b233d7b9aa6fcc518e0c1750b88b36cc1c42290d;hb=9e04e2a1221a92960a74e550bc3fd809caf3cd1c;hp=45cfec51048ebd332fcf0f4fb2bbded8c504a975;hpb=57e35f063b4a70fcec59db6ec7366b43f41f0ba4;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/06_net/02_XNetJSONP.js b/0.6.x/js/06_net/02_XNetJSONP.js index 45cfec5..b233d7b 100644 --- a/0.6.x/js/06_net/02_XNetJSONP.js +++ b/0.6.x/js/06_net/02_XNetJSONP.js @@ -1,10 +1,11 @@ +//{+jsonp"jsonpによるajax"(jsonpによるクロスドメイン通信。)[+net,+ninjaiframe] + /* * Operaでも非同期リクエストが並列処理できる img-JSONP * http://developer.cybozu.co.jp/takesako/2007/06/opera_img-jsonp.html * * iframe を使った jsonp の読み込みエラー判定の記事、 - * JSONPのエラーを判断する は web archive でも観れない - * http://d.hatena.ne.jp/yuushimizu/20090128/1233146321 + * https://web.archive.org/web/20120917100043/http://d.hatena.ne.jp/yuushimizu/20090128/1233146321 * TODO JSONPの動的取得+エラー処理 * http://d.hatena.ne.jp/NeoCat/20110206/1296934235 * @@ -16,187 +17,212 @@ * * IE6(IETester,localhost) で動かない, * - * TODO postMessage + * TODO iframe 内を他ドメインにして jsonp のセキュリティを強化。他ドメインに jsonp を読み込んで 正しい JSON か?検証後にフレーム間通信で戻す。 */ -X.Net.JSONP = { - cb : function( accessKey, jsonString, time, opt_json2FileSize ){ - if( accessKey !== X_NET_JSONP_ACCESS_KEY || !X_NET_JSONPWrapper._busy ) return; + // TODO chashe + // TODO iframe useful or not. TODO check dynamicIframe + // TODO file: では http: は使えない + +X_TEMP.X_JSONP_cb = function( accessKey, jsonString, time, opt_json2FileSize ){ + if( accessKey !== X_JSONP_ACCESS_KEY || !X_JSONP._busy ) return; - X_NET_JSONPWrapper._busy = false; + X_JSONP._busy = false; - X_NET_JSONPWrapper - .asyncDispatch( { - type : jsonString ? X.Event.SUCCESS : X.Event.ERROR, - data : jsonString //window.JSON ? JSON.parse( jsonString ) : eval( jsonString ) + X_JSONP + [ 'asyncDispatch' ]( { + type : jsonString ? X_EVENT_SUCCESS : X_EVENT_ERROR, + response : X_JSON_parseTrustableString( jsonString ) } ); + X_JSONP_errorTimerID && X_Timer_remove( X_JSONP_errorTimerID ); + console.log( 'ms : ' + time + ' speed : ' + ( ( jsonString.length + ( opt_json2FileSize || 0 ) ) / time * 1000 ) + ' バイト/秒.' ); - } -}; + }; -var X_NET_JSONP_ACCESS_KEY = Math.random(), +var X_JSONP_ACCESS_KEY = Math.random(), - X_NET_JSONP_NinjaIframe, + X_JSONP_maxOnloadCount, - X_Net_JSONP_onloadCount; - + X_JSONP_onloadCount = 0, + + X_JSONP_errorTimerID; -function X_NET_JSONP_loadScriptInNinjaIframe( url ){ - var json2Path = 'js/libs/json2.js', - json2FileSize = 18103, - html; +X_TEMP.X_JSONP_init = function(){ + X[ 'Net' ][ '__json_cb__' ] = X_TEMP.X_JSONP_cb; - X_NET_JSONP_NinjaIframe || ( X_NET_JSONP_NinjaIframe = new X.Util.NinjaIframe() ); + X_JSONP = X_Class_override( X_NinjaIframe(), X_TEMP.X_JSONP_params ); - // TODO ' 化 恐らくアンチウイルスソフトが反応しないための対策 - // TODO postMessage の利用 - - if( X_UA.Opera ){ - html = [ - ( window[ 'JSON' ] ? '' : '' ), - '', - '', - '' - ]; - X_Net_JSONP_onloadCount = 2; - } else - if( X_UA.IE8 ){ - html = [ - // JavaScriptでunicode文字列をunescapeする - // http://perutago.seesaa.net/article/202801583.html - - // http://blog.livedoor.jp/dankogai/archives/51503830.html - // Ajax - IE8にもJSON入ってます。使えるとは限らないけど - // Compatibility mode (別名Quirks mode) では、JSONオブジェクトは無効になります。iframeもだめです - '', - '' - - /* 以下のコードは XP ie8 では動くけど、win8 IE11(8モード)で動かない 開発の便宜を取って,setTimeout を挟む - '', - '' */ - ]; - X_Net_JSONP_onloadCount = 2; - } else - if( X_UA.IE9 ){ - html = [ - '', - '' - ]; - X_Net_JSONP_onloadCount = 2; - } else - if( window[ 'JSON' ] ){ - html = [ - '', - '' - ]; - X_Net_JSONP_onloadCount = 1; - } else - if( X_UA.IE4 || X_UA.MacIE ){ - html = [ - '', - '', - '' - ]; - X_Net_JSONP_onloadCount = 3; - } else - if( X_UA.IE < 8 ){ // ie5-7 - html = [ - '', - '', - '' - ]; - X_Net_JSONP_onloadCount = 3; - } else { - html = [ - '', - '', - '' - ]; - X_Net_JSONP_onloadCount = 1; - }; + delete X_TEMP.X_JSONP_cb; + delete X_TEMP.X_JSONP_init; + delete X_TEMP.X_JSONP_params; - X_NET_JSONP_NinjaIframe - .refresh( html.join( '' ) ) - .listen( [ X.Event.SUCCESS, X.Event.ERROR ], X_NET_JSONPWrapper, X_NET_JSONP_iframeListener ); + return X_JSONP; }; +X_TEMP.X_JSONP_params = { + + _busy : false, + _canceled : false, + + 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', + json2FileSize = 18103, + html; + + // file プロトコルで外部アクセスの禁止 + 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'; + }; + + charset = charset ? ' charset="' + charset + '"' : ''; + + // TODO ' 化 恐らくアンチウイルスソフトが反応しないための対策 + // document.postMessage()→window.postMessage() (Opera 9.50 build 9841 -) + // http://d.hatena.ne.jp/cnrd/20080518/1211099169 + // 最近の仕様変更(引数のtargetOriginとかMessageEventのoriginとか)にはまだ対応してないみたい + + if( X_UA[ 'Opera' ] ){ + html = [ + ( window[ 'JSON' ] ? '' : '' ), + '', + '', + '' + ]; + X_JSONP_maxOnloadCount = 2; + } else + if( X_UA[ 'IE8' ] ){ + html = [ + '', + '' + + /* 以下のコードは XP ie8 では動くけど、win8 IE11(8モード)で動かない 開発の便宜を取って,setTimeout を挟む + '', + '' */ + ]; + X_JSONP_maxOnloadCount = 2; + } else + if( X_UA[ 'IE9' ] ){ + html = [ + '', + '' + ]; + X_JSONP_maxOnloadCount = 2; + } else + if( window[ 'JSON' ] ){ + html = [ + '', + '' + ]; + X_JSONP_maxOnloadCount = 1; + } else + if( X_UA[ 'IE4' ] || X_UA[ 'MacIE' ] ){ + html = [ + '', + '', + '' + ]; + X_JSONP_maxOnloadCount = 3; + } else + if( X_UA[ 'IE' ] < 8 ){ // ie5-7 + html = [ + '', + '', + '' + ]; + X_JSONP_maxOnloadCount = 3; + } else { + html = [ + '', + '', + '' + ]; + X_JSONP_maxOnloadCount = 2; + }; + + X_JSONP + [ 'refresh' ]( html.join( '' ) ) + [ 'listen' ]( [ 'ninjaload', 'ninjaerror' ], X_JSONP_iframeListener ); + + X_JSONP._busy = true; + }, + + cancel : function(){ + X_JSONP.reset(); + X_JSONP._canceled = true; + }, + + reset : function(){ + X_JSONP._busy = X_JSONP._canceled = false; + X_JSONP[ 'unlisten' ]( [ 'ninjaload', 'ninjaerror' ], X_JSONP_iframeListener ); + X_JSONP[ 'refresh' ]( '' ); + X_JSONP_errorTimerID && X_Timer_remove( X_JSONP_errorTimerID ); + X_JSONP_errorTimerID = X_JSONP_onloadCount = 0; + } + }; -function X_NET_JSONP_iframeListener( e ){ +function X_JSONP_iframeListener( e ){ switch( e.type ){ - case X.Event.SUCCESS : - console.log( 'iframe onload, but' ); - if( ++X_NET_JSONPWrapper._onloadCount < X_Net_JSONP_onloadCount ) return; - // TODO callback が無ければ error - X_NET_JSONPWrapper.asyncDispatch( 1000, X.Event.ERROR ); + case 'ninjaload' : + console.log( 'iframe onload, but ' + X_JSONP_onloadCount + ' < ' + X_JSONP_maxOnloadCount ); + if( ++X_JSONP_onloadCount < X_JSONP_maxOnloadCount ) return; + + // TODO callback が無ければ error -> timeout を観る? + X_JSONP_errorTimerID = X_JSONP[ 'asyncDispatch' ]( 1000, X_EVENT_ERROR ); break; - case X.Event.ERROR : + case 'ninjaerror' : console.log( 'iframe onerror' ); - X_NET_JSONPWrapper.asyncDispatch( X.Event.ERROR ); + X_JSONP[ 'asyncDispatch' ]( X_EVENT_ERROR ); break; }; - X_NET_JSONP_NinjaIframe.unlisten(); - return X.Callback.UN_LISTEN; + return X_CALLBACK_UN_LISTEN; }; - - -X_NET_JSONPWrapper = X_Class_override( - new X.EventDispatcher(), - { - - _busy : false, - _canceled : false, - _onloadCount : 0, - - load : function( url, data, timeout ){ - //createURL - X_NET_JSONP_loadScriptInNinjaIframe( url ); - - this._busy = true; - }, - - cancel : function(){ - this._canceled = true; - }, - - reset : function(){ - this._busy = this._canceled = false; - this._onloadCount = 0; - } - } -);