From: itozyun Date: Tue, 12 May 2015 12:03:44 +0000 (+0900) Subject: Version 0.6.147, fix X.UA & X.URL & X.EventDispatcher & X.XHR. X-Git-Url: http://git.osdn.jp/view?p=pettanr%2FclientJs.git;a=commitdiff_plain;h=48e4feb142bc4ae9a9d67e2961b39bd0a331306c Version 0.6.147, fix X.UA & X.URL & X.EventDispatcher & X.XHR. --- diff --git a/0.6.x/js/01_core/02_XUA.js b/0.6.x/js/01_core/02_XUA.js index ad17ef2..eda4818 100644 --- a/0.6.x/js/01_core/02_XUA.js +++ b/0.6.x/js/01_core/02_XUA.js @@ -282,19 +282,20 @@ var X_UA = X[ 'UA' ] = {}, * @type {number} */ X_UA[ 'Trident' ] = parseFloat(dav.split('Trident/')[1]) || 0; - /** - * documentモードを考慮したIEのバージョン - * @alias X.UA.IE - * @type {number} - */ - X_UA[ 'IE' ] = v = document.documentMode || X_UA[ '_IE' ]; + tridentToVer = X_UA[ 'Trident' ] ? ( X_UA[ 'Trident' ] + 4 | 0 ) : X_UA[ '_IE' ]; /** * IE10 以上の互換モードを使用している場合、そのバージョン * @alias X.UA.IECompat * @type {number} */ - if( v = tridentToVer !== X_UA[ '_IE' ] && tridentToVer ) X_UA[ 'IECompat' ] = v; + if( tridentToVer !== X_UA[ '_IE' ] ) X_UA[ 'IECompat' ] = tridentToVer; + /** + * documentモードを考慮したIEのバージョン + * @alias X.UA.IE + * @type {number} + */ + X_UA[ 'IE' ] = v = document.documentMode || tridentToVer; /** * @alias X.UA.IE4 * @type {boolean} @@ -361,7 +362,7 @@ var X_UA = X[ 'UA' ] = {}, */ if( dua.toLowerCase().indexOf( 'windows phone' ) !== -1 || 0 < dav.indexOf( 'ZuneWP' ) ) X_UA[ 'WinPhone' ] = true; // ZuneWP は IEM のデスクトップモードで登場する - console.log( '>> IE : ' + v + ' ActiveX : ' + X_UA[ 'ActiveX' ] ); + console.log( '>> IE : ' + v + ' ActiveX : ' + X_UA[ 'ActiveX' ] + ' IEHost : ' + X_UA[ 'IECompat' ] ); // TODO XBox360, XBox1, Modern or Desktop, Standalone return; }; diff --git a/0.6.x/js/01_core/06_XURL.js b/0.6.x/js/01_core/06_XURL.js index 7d395f4..daa6a8e 100644 --- a/0.6.x/js/01_core/06_XURL.js +++ b/0.6.x/js/01_core/06_XURL.js @@ -39,6 +39,10 @@ X[ 'URL' ] = { 'isSameDomain' : X_URL_isSameDomain, + 'isSameProtocol' : X_URL_isSameProtocol, + + 'isLocal' : X_URL_isLocal, + 'cleanup' : X_URL_cleanup, 'getEXT' : X_URL_getEXT @@ -81,6 +85,14 @@ function X_URL_isSameDomain( path ){ return path === X_URL_BASE_URL || path.indexOf( X_URL_BASE_URL + '/' ) === 0; }; +function X_URL_isSameProtocol( path ){ + return X_URL_toAbsolutePath( path ).indexOf( location.protocol ) === 0; +}; + +function X_URL_isLocal( path ){ + return X_URL_toAbsolutePath( path ).indexOf( 'file:' ) === 0; +}; + function X_URL_cleanup( path ){ return path.split( '?' )[ 0 ].split( '#' )[ 0 ]; }; diff --git a/0.6.x/js/01_core/13_XEventDispatcher.js b/0.6.x/js/01_core/13_XEventDispatcher.js index 0b83d8d..612268f 100644 --- a/0.6.x/js/01_core/13_XEventDispatcher.js +++ b/0.6.x/js/01_core/13_XEventDispatcher.js @@ -192,7 +192,7 @@ var X_EventDispatcher = X[ 'EventDispatcher' ] = if( opt_type === undefined ) return !!listeners; if( !listeners || !( list = listeners[ opt_type ] ) ) return false; - if( opt_arg1 === undefined ) return true; + if( opt_arg1 === undefined ) return X_EventDispatcher_needsIndex ? 0 : true; if( opt_arg1.kind ){ cbHash = opt_arg1; @@ -494,7 +494,7 @@ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){ empty = false; break; }; - if( raw && !X_String_isNumberString( opt_type ) ){ // 数字イベントの除外 + if( raw && !X_String_isNumberString( '' + opt_type ) ){ // 数字イベントの除外 X_EventDispatcher_removeEvent( this, opt_type, raw, list, !empty ); }; if( empty ) delete this[ '_listeners' ]; @@ -592,6 +592,7 @@ var X_EventDispatcher_actualAddEvent = break; case X_EventDispatcher_EVENT_TARGET_XHR : + console.log( 'XHR addEvent ' + type ); // ie8- の XHR は window.event が更新されないため, eventType 毎に callback を指定する raw[ 'on' + type ] = X_Callback_create( that, X_EventDispatcher_dispatch, [ type ] ); break; @@ -710,6 +711,7 @@ var X_EventDispatcher_actualRemoveEvent = X_Callback_correct( raw[ 'on' + type ] ); raw[ 'on' + type ] = X_emptyFunction; raw[ 'on' + type ] = ''; + console.log( 'XHR rmEvent ' + type ); break; default : diff --git a/0.6.x/js/03_plugin/00_XPlugin.js b/0.6.x/js/03_plugin/00_XPlugin.js index a6e6512..be90379 100644 --- a/0.6.x/js/03_plugin/00_XPlugin.js +++ b/0.6.x/js/03_plugin/00_XPlugin.js @@ -38,7 +38,7 @@ var X_Pulgin_FLASH_VERSION = X_Pulgin_SILVER_LIGHT_VERSION = !X_UA[ 'IE' ] && navigator.plugins[ 'Silverlight Plug-In' ] ? parseFloat( navigator.plugins[ 'Silverlight Plug-In' ].version ) : - X_UA[ 'ActiveX' ] && 6 <= X_UA[ 'IE' ] && !X_UA[ 'IECompat' ] ? (function(){ + X_UA[ 'ActiveX' ] && 6 <= X_UA[ 'IE' ] /* && !X_UA[ 'IECompat' ] */ ? (function(){ return eval( 'var a,i=0;try{a=new ActiveXObject("AgControl.AgControl");for(i=5;i;--i)if(a.IsVersionSupported(i+".0"))break;}catch(e){i=0}i' ); })() : 0, diff --git a/0.6.x/js/06_net/00_XNet.js b/0.6.x/js/06_net/00_XNet.js index bafbeef..709f177 100644 --- a/0.6.x/js/06_net/00_XNet.js +++ b/0.6.x/js/06_net/00_XNet.js @@ -230,10 +230,12 @@ function X_NET_shiftQueue(){ switch( X_NET_currentData.netType ){ case X_NET_TYPE_XHR : - X_NET_currentWrapper = X_NET_XHRWrapper || X_TEMP.X_Net_XHR_init(); - // TODO OAuth2 - // oauth2.authState() -> NEED_AUTH -> COMPLETE, refresh 中なら後回し。 + // TODO xProtocol, method -> gadget.io.makeRequset, flash + + X_NET_currentWrapper = X_NET_XHRWrapper || X_TEMP.X_Net_XHR_init(); + + // OAuth2 if( auth = X_NET_currentData[ 'auth' ] ){ authSettings = X_Pair_get( auth ); switch( auth.state() ){ diff --git a/0.6.x/js/06_net/01_XNetXHR.js b/0.6.x/js/06_net/01_XNetXHR.js index cd4d0e6..9b5d7df 100644 --- a/0.6.x/js/06_net/01_XNetXHR.js +++ b/0.6.x/js/06_net/01_XNetXHR.js @@ -31,31 +31,42 @@ basic 認証のかかったhtml を表示して、そのjsが xhr をすると A Android1.6- の XHR で 401 エラーが返った場合は、iframe に xml を表示させてその内容を取ればサーバ側の対応無しでいけるかも? */ var // Opera7.6+, Safari1.2+, khtml3.?+, Gecko0.9.7+ - // ie7 ではローカルリソースには ActiveX の XHR を使う - X_Net_XHR_W3C = ( !X_UA[ 'IE7' ] || !X_URL_IS_LOCAL ) && window[ 'XMLHttpRequest' ] && new XMLHttpRequest(), - X_Net_XHR_progress = X_Net_XHR_W3C && X_Net_XHR_W3C.onprogress !== undefined, - X_Net_XHR_upload = X_Net_XHR_W3C && !!X_Net_XHR_W3C.upload, + // ie7&8 ではローカルリソースには ActiveX の XHR を使う + X_Net_XHR_createW3C = window[ 'XMLHttpRequest' ] && function(){ return X_Net_XHR_w3c || ( X_Net_XHR_w3c = new XMLHttpRequest() ); }, + X_Net_XHR_w3c = X_Net_XHR_createW3C && X_Net_XHR_createW3C(), + X_Net_XHR_progress = X_Net_XHR_w3c && X_Net_XHR_w3c.onprogress !== undefined, + X_Net_XHR_upload = X_Net_XHR_w3c && !!X_Net_XHR_w3c.upload, - X_Net_XHR_X_DOMAIN = window[ 'XDomainRequest' ] && new XDomainRequest(), - X_Net_XHR_VERSION = 0, - X_Net_XHR_ACTIVE_X = !X_UA[ 'IE4' ] && X_UA[ 'IE' ] < 8 && X_UA[ 'ActiveX' ] && ( new Function( [ - 'var x=".XMLHTTP",', - 'm="MSXML2"+x,', - 'n=[m+".6.0",m+".3.0",m+".5.0",m+".4.0",m,"Microsoft"+x],', - 'v=[6,3,5,4,2,1],', - 'i=-1;', - 'for(;i<5;){', - 'try{', - 'return[v[++i],new ActiveXObject(n[i])]', - '}catch(e){}', - '}' - ].join( '' ) ) )(), + X_Net_XHR_createXDR = window[ 'XDomainRequest' ] && function(){ return X_Net_XHR_xdr || ( X_Net_XHR_xdr = new XDomainRequest() ); }, + X_Net_XHR_xdr = X_Net_XHR_createXDR && X_Net_XHR_createXDR(), + + X_Net_XHR_createMSXML = X_UA[ 'ActiveX' ] && ( X_UA[ 'IE5x' ] || X_UA[ 'IE6' ] || ( X_URL_IS_LOCAL && X_UA[ 'IE' ] ) ) && + ( new Function( 'f', [ + 'var x=".XMLHTTP",', + 'm="MSXML2"+x,', + 'n=[m+".6.0",m+".3.0",m+".5.0",m+".4.0",m,"Microsoft"+x],', + 'v=[6,3,5,4,2,1],', + 'a=ActiveXObject,', + 'i=-1;', + 'for(;i<5;){', + 'try{', + 'return f?[v[++i],new a(n[i])]:new a(n[i])', + '}catch(e){}', + '}' + ].join( '' ) ) ), + + X_Net_XHR_VERSION = 0, + X_Net_XHR_msXML = X_Net_XHR_createMSXML && X_Net_XHR_createMSXML( true ), + + X_Net_XHR_unReuseAlways = /* !X_UA[ 'IECompat' ] && */ X_UA[ 'IE' ] < 9, X_Net_XHR_init; -if( X_Net_XHR_ACTIVE_X ){ - X_Net_XHR_VERSION = X_Net_XHR_ACTIVE_X[ 0 ]; - X_Net_XHR_ACTIVE_X = X_Net_XHR_ACTIVE_X[ 1 ]; +if( X_Net_XHR_msXML ){ + X_Net_XHR_VERSION = X_Net_XHR_msXML[ 0 ]; + X_Net_XHR_msXML = X_Net_XHR_msXML[ 1 ]; +} else { + X_Net_XHR_createMSXML = null; }; X[ 'Net' ][ 'XHR' ] = { @@ -72,15 +83,15 @@ X[ 'Net' ][ 'XHR' ] = { * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest * Progress Events Chrome7, firefox3.5, ie10, opera12, Safari?, Chrome for Android 0.16 */ - 'PROGRESS' : X_Net_XHR_progress, // + 'PROGRESS' : X_Net_XHR_progress, 'UL_PROGRESS' : X_Net_XHR_upload, // or gadget proxy - 'CORS' : X_Net_XHR_X_DOMAIN || ( X_Net_XHR_W3C && X_Net_XHR_W3C.withCredentials !== undefined ) + 'CORS' : X_Net_XHR_xdr || ( X_Net_XHR_w3c && X_Net_XHR_w3c.withCredentials !== undefined ) }; -if( X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X ){ +if( X_Net_XHR_w3c || X_Net_XHR_msXML ){ X_TEMP.X_Net_XHR_init = function(){ @@ -91,53 +102,77 @@ X_TEMP.X_Net_XHR_init = function(){ { '_rawType' : X_EventDispatcher_EVENT_TARGET_XHR, - '_rawObject' : X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X, - - _isXDR : false, // for ie8 + // '_rawObject' : X_Net_XHR_w3c || X_Net_XHR_msXML, - _method : '', - _dataType : '', - _busy : false, - _canceled : false, - _error : false, - _percent : 0, - _timerID : 0, + _isXDR : false, + _isMsXML : false, - _auth : null, + _method : '', + _dataType : '', + _busy : false, + _canceled : false, + _error : false, + _percent : 0, + _timerID : 0, load : function( obj ){ var raw = this[ '_rawObject' ], method = obj[ 'method' ], url = obj[ 'url' ], - async = obj[ 'async' ], + async = obj[ 'async' ] !== false, username = obj[ 'username' ], password = obj[ 'password' ], headers = obj[ 'headers' ] || {}, postdata = obj[ 'postdata' ] || '', timeout = obj[ 'timeout' ] || 20000, + xDomain = !X_URL_isSameDomain( url ), + isFile = X_URL_isLocal( url ), tmp; this._dataType = obj[ 'dataType' ] || X_URL_getEXT( url ); - if( X_Net_XHR_X_DOMAIN ){ - if( X_URL_isSameDomain( url ) ){ // isXDomain - if( this._isXDR ){ - X_EventDispatcher_toggleAllEvents( this, false ); - this[ '_rawObject' ] = raw = X_Net_XHR_W3C || X_Net_XHR_ACTIVE_X; - X_EventDispatcher_toggleAllEvents( this, true ); - this._isXDR = false; - }; + if( !raw || xDomain !== this._isXDR || ( X_Net_XHR_createMSXML && isFile !== this._isMsXML ) ){ + + this[ 'unlisten' ]( [ 'load', 'readystatechange', 'progress', 'error', 'timeout' ] ); + + this[ '_rawObject' ] = raw = xDomain ? + X_Net_XHR_createXDR() : + isFile ? + ( X_Net_XHR_createMSXML ? + ( X_Net_XHR_msXML = X_Net_XHR_msXML || X_Net_XHR_createMSXML() ): + X_Net_XHR_createW3C() + ) : + X_Net_XHR_createW3C ? + X_Net_XHR_createW3C() : + ( X_Net_XHR_msXML = X_Net_XHR_msXML || X_Net_XHR_createMSXML() ); + + // raw === XDR これは error になるのでフラグに控える + this._isXDR = X_Net_XHR_createXDR && xDomain; + this._isMsXML = !X_Net_XHR_createW3C || ( isFile && X_Net_XHR_createMSXML ); + + if( this._isMsXML ){ + this[ 'listen' ]( 'readystatechange' ); // TODO ie7 ActiveX の場合、error は不可 toggleAllEvent のあたり + } else + if( X_UA[ 'IE8' ] ){ + this[ 'listen' ]( [ 'readystatechange', 'error', 'timeout' ] ); + } else + if( X_UA[ 'IE7' ] ){ + this[ 'listen' ]( [ 'readystatechange', 'error' ] ); + } else + if( X_Net_XHR_progress ){ + this[ 'listen' ]( [ 'load', 'progress', 'error', 'timeout' ] ); //, 'abort' } else { - if( !this._isXDR ){ - X_EventDispatcher_toggleAllEvents( this, false ); - this[ '_rawObject' ] = raw = X_Net_XHR_X_DOMAIN; - X_EventDispatcher_toggleAllEvents( this, true ); - this._isXDR = true; - }; + this[ 'listen' ]( [ 'load', 'readystatechange', 'error', 'timeout' ] ); //, 'abort' + }; + + X_EventDispatcher_toggleAllEvents( this, true ); + + if( X_Net_XHR_upload ){ + raw.upload.addEventListener( 'progress', this.onUploadProgress ); }; }; - raw.open( method, url, true, username, password ); + raw.open( method, url, async, username, password ); if( raw.responseType !== undefined ){ switch( this._dataType ){ @@ -166,7 +201,7 @@ X_TEMP.X_Net_XHR_init = function(){ }; // http://www.quirksmode.org/blog/archives/2005/09/xmlhttp_notes_r_1.html - if( !X_Net_XHR_ACTIVE_X && X_Type_isFunction( raw.overrideMimeType ) ){ + if( !this._isMsXML && raw.overrideMimeType ){ switch( X_URL_getEXT( url ) ){ case 'html' : case 'xml' : @@ -196,24 +231,30 @@ X_TEMP.X_Net_XHR_init = function(){ tmp = 'audio/webm'; break; }; - if( obj[ 'mimeType' ] || tmp ) raw.overrideMimeType( obj[ 'mimeType' ] || tmp ); - console.log( this._dataType ); - console.log( obj[ 'mimeType' ] || tmp ); + if( tmp = obj[ 'mimeType' ] || tmp ) raw.overrideMimeType( tmp ); }; - if( /* !X_Net_XHR_ACTIVE_X && !this._isXDR && */ X_Type_isFunction( raw.setRequestHeader ) ){ + if( !this._isMsXML && !this._isXDR && raw.setRequestHeader ){ // http://nakigao.sitemix.jp/blog/?p=2040 // json 取得時に SafariでHTTP/412のエラー。但し相手が audio の場合、この指定があるとロードに失敗する。 iOS8.2, iOS7.1 では遭遇せず if( this._dataType === 'json' ){ - console.log( 'If-Modified-Since : ' + this._dataType ); headers[ 'If-Modified-Since' ] = ( new Date ).toUTCString(); }; + // http://boscono.hatenablog.com/entry/2013/12/23/152851 + if ( !xDomain && !headers[ 'X-Requested-With' ] ) { + headers[ 'X-Requested-With' ] = 'XMLHttpRequest'; + }; + + if( method === 'POST' ){ + headers[ 'Content-Type' ] = 'application/x-www-form-urlencoded'; + }; + for( p in headers ){ if( X_EMPTY_OBJECT[ p ] ) continue; - raw.setRequestHeader( p, headers[ p ] ); // Opera8.01+, MSXML3+ - }; + headers[ p ] !== undefined && raw.setRequestHeader( p, headers[ p ] + '' ); // Opera8.01+, MSXML3+ + }; }; if( raw.timeout !== undefined ){ @@ -226,6 +267,10 @@ X_TEMP.X_Net_XHR_init = function(){ this._busy = true; raw.send( X_Type_isString( postdata ) ? postdata : X_String_serialize( postdata ) ); + + if( !async || raw.readyState === 4 ){ // raw.readyState へのアクセスで ie7 実機でerror + this[ 'asyncDispatch' ]( this[ 'listening' ]( 'load' ) ? 'load' : 'readystatechange' ); + }; }, cancel : function(){ @@ -244,28 +289,40 @@ X_TEMP.X_Net_XHR_init = function(){ // Opera 10.10、Safari 4.1 では、同一オリジン制限に違反した XMLHttpRequest オブジェクトは再度 open() しても未送信状態に戻りません。 // Timeout した Gecko の xhr.response に触るとエラー?? - if( X_UA[ 'Opera' ] || X_UA[ 'Webkit' ] || X_UA[ 'Gecko' ] ){ - if( this._error ){ - - if( X_Net_XHR_upload ){ - this[ '_rawObject' ].upload.removeEventListener( 'progress', X_NET_XHRWrapper.onUploadProgress ); - }; - + if( this._error && ( X_UA[ 'Opera' ] || X_UA[ 'Webkit' ] || X_UA[ 'Gecko' ] ) ){ + if( X_Net_XHR_upload ){ + X_Net_XHR_w3c.upload.removeEventListener( 'progress', this.onUploadProgress ); + }; + + X_EventDispatcher_toggleAllEvents( this, false ); + this[ '_rawObject' ] = X_Net_XHR_w3c = null; + //X_EventDispatcher_toggleAllEvents( this, true ); + + } else { + // XMLHttpRequest の使い方 + // http://webos-goodies.jp/archives/50548720.html + // XMLHttpRequest オブジェクトを再利用する際も、 abort メソッドを呼び出す必要があるようです。 + this[ '_rawObject' ].abort && this[ '_rawObject' ].abort(); + + if( X_Net_XHR_unReuseAlways ){ + // ie7 は xhr object を再利用できない。但し send のあとに alert を挟むと動いた、、、 + // ie7モード(IE11) では再利用可能、、、 X_EventDispatcher_toggleAllEvents( this, false ); - this[ '_rawObject' ] = new XMLHttpRequest(); - X_EventDispatcher_toggleAllEvents( this, true ); + this[ '_rawObject' ] = null; - if( X_Net_XHR_upload ){ - this[ '_rawObject' ].upload.addEventListener( 'progress', X_NET_XHRWrapper.onUploadProgress ); + if( this._isXDR ){ + X_Net_XHR_xdr = null; + } else + if( this._isMsXML ){ + X_Net_XHR_msXML = null; + } else { + X_Net_XHR_w3c = null; }; + delete this._isXDR; + delete this._isMsXML; }; }; - // XMLHttpRequest の使い方 - // http://webos-goodies.jp/archives/50548720.html - // XMLHttpRequest オブジェクトを再利用する際も、 abort メソッドを呼び出す必要があるようです。 - this[ '_rawObject' ].abort && this[ '_rawObject' ].abort(); - this._method = this._dataType = ''; this._canceled = this._busy = this._error = false; this._timerID && X_Timer_remove( this._timerID ); @@ -332,7 +389,7 @@ X_TEMP.X_Net_XHR_init = function(){ ( status < 100 ) || ( 200 <= status && status < 400 ) || //status === 304 || - status === 1223 || + ( status === 1223 && ( status = 204 ) ) || ( X_UA[ 'Webkit' ] && status === undefined ) // safari: /webkit/.test(userAgent) ){ /* @@ -400,7 +457,7 @@ X_TEMP.X_Net_XHR_init = function(){ var raw = this[ '_rawObject' ], live = !X_NET_XHRWrapper._canceled || !this._busy; - if( raw.readyState < 3 ){ + if( live || raw.readyState < 3 ){ this._busy = false; live && this[ 'asyncDispatch' ]( X_EVENT_TIMEOUT ); }; @@ -411,34 +468,12 @@ X_TEMP.X_Net_XHR_init = function(){ var raw = X_NET_XHRWrapper[ '_rawObject' ].upload, live = !X_NET_XHRWrapper._canceled, states, data; + live && X_NET_XHRWrapper[ 'asyncDispatch' ]( { type : X_EVENT_PROGRESS, 'percent' : X_NET_XHRWrapper._percent, 'uploadPercent' : ( e.loaded / e.total ) } ); } }, true ); // 同期リクエストでなければならない場合, unload, beforeunload時 - - if( X_UA[ 'IE8' ] ){ - X_NET_XHRWrapper[ 'listen' ]( [ 'readystatechange', 'error', 'timeout' ] ); //, 'abort' - } else - if( X_UA[ 'IE7' ] ){ - if( X_URL_IS_LOCAL ){ - X_NET_XHRWrapper[ 'listen' ]( 'readystatechange' ); // ie7 ActiveX の場合、error は不可 - } else { - X_NET_XHRWrapper[ 'listen' ]( [ 'readystatechange', 'error' ] ); - }; - } else - if( X_Net_XHR_ACTIVE_X ){ // win ie5-6 - X_NET_XHRWrapper[ 'listen' ]( 'readystatechange' ); - } else - if( X_Net_XHR_progress ){ - X_NET_XHRWrapper[ 'listen' ]( [ 'load', 'progress', 'error', 'timeout' ] ); //, 'abort' - } else { - X_NET_XHRWrapper[ 'listen' ]( [ 'load', 'readystatechange', 'error', 'timeout' ] ); //, 'abort' - }; - - if( X_Net_XHR_upload ){ - X_NET_XHRWrapper[ '_rawObject' ].upload.addEventListener( 'progress', X_NET_XHRWrapper.onUploadProgress ); - }; return X_NET_XHRWrapper; };