X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F06_net%2F02_XNetJSONP.js;h=ed9b2d315e18f3c5c755cb904473f61df773876c;hb=HEAD;hp=69252c7d9217b5e10916d0cf86b441448d760344;hpb=7911fddcbb190b99ad11412d283776ddbf77b479;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 69252c7..ed9b2d3 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,199 +17,209 @@ * * 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 ) + ' バイト/秒.' ); - } -}; - -function X_Net_JSONP_reciveMessage( data ){ - console.log( data ); -}; + }; -var X_NET_JSONP_ACCESS_KEY = Math.random(), +var X_JSONP_ACCESS_KEY = Math.random(), - X_NET_JSONP_SEND_MSG_KEY = X_System.message( 'X.Net.JSONP', X_Net_JSONP_reciveMessage ), + X_JSONP_maxOnloadCount, - X_NET_JSONP_NinjaIframe, + X_JSONP_onloadCount = 0, - X_Net_JSONP_onloadCount; + X_JSONP_errorTimerID; +X_TEMP.X_JSONP_init = function(){ + X[ 'Net' ][ '__json_cb__' ] = X_TEMP.X_JSONP_cb; - -function X_NET_JSONP_loadScriptInNinjaIframe( url ){ - var json2Path = 'js/libs/json2.js', - json2FileSize = 18103, - html; + X_JSONP = X_Class_override( X_NinjaIframe(), X_TEMP.X_JSONP_params ); - X_NET_JSONP_NinjaIframe || ( X_NET_JSONP_NinjaIframe = new X.Util.NinjaIframe() ); + delete X_TEMP.X_JSONP_cb; + delete X_TEMP.X_JSONP_init; + delete X_TEMP.X_JSONP_params; - // TODO ' 化 恐らくアンチウイルスソフトが反応しないための対策 - // TODO postMessage の利用 - // document.postMessage()→window.postMessage() (Opera 9.50 build 9841 -) - // http://d.hatena.ne.jp/cnrd/20080518/1211099169 - // 最近の仕様変更(引数のtargetOriginとかMessageEventのoriginとか)にはまだ対応してないみたい + return X_JSONP; +}; - 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; - }; +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 ); -}; + _busy : false, + _canceled : false, + + load : function( option ){ + //createURL + var url = option[ 'url' ], + 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 ); + }; + 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; - } - } -);