From a089699c8915636ba4f158d77dba9b012bc93208 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 4 Mar 2011 19:02:28 +0300 Subject: build custom layer of Dojo to speed up loading of tt-rss (refs #293) --- lib/dojo/_base/_loader/hostenv_browser.js | 684 ++++++++++++++++++++---------- 1 file changed, 457 insertions(+), 227 deletions(-) (limited to 'lib/dojo/_base/_loader/hostenv_browser.js') diff --git a/lib/dojo/_base/_loader/hostenv_browser.js b/lib/dojo/_base/_loader/hostenv_browser.js index 0d746833e..7d92d70e3 100644 --- a/lib/dojo/_base/_loader/hostenv_browser.js +++ b/lib/dojo/_base/_loader/hostenv_browser.js @@ -5,240 +5,470 @@ */ -if(typeof window!="undefined"){ -dojo.isBrowser=true; -dojo._name="browser"; -(function(){ -var d=dojo; -if(document&&document.getElementsByTagName){ -var _1=document.getElementsByTagName("script"); -var _2=/dojo(\.xd)?\.js(\W|$)/i; -for(var i=0;i<_1.length;i++){ -var _3=_1[i].getAttribute("src"); -if(!_3){ -continue; -} -var m=_3.match(_2); -if(m){ -if(!d.config.baseUrl){ -d.config.baseUrl=_3.substring(0,m.index); -} -var _4=_1[i].getAttribute("djConfig"); -if(_4){ -var _5=eval("({ "+_4+" })"); -for(var x in _5){ -dojo.config[x]=_5[x]; -} -} -break; -} -} -} -d.baseUrl=d.config.baseUrl; -var n=navigator; -var _6=n.userAgent,_7=n.appVersion,tv=parseFloat(_7); -if(_6.indexOf("Opera")>=0){ -d.isOpera=tv; -} -if(_6.indexOf("AdobeAIR")>=0){ -d.isAIR=1; -} -d.isKhtml=(_7.indexOf("Konqueror")>=0)?tv:0; -d.isWebKit=parseFloat(_6.split("WebKit/")[1])||undefined; -d.isChrome=parseFloat(_6.split("Chrome/")[1])||undefined; -d.isMac=_7.indexOf("Macintosh")>=0; -var _8=Math.max(_7.indexOf("WebKit"),_7.indexOf("Safari"),0); -if(_8&&!dojo.isChrome){ -d.isSafari=parseFloat(_7.split("Version/")[1]); -if(!d.isSafari||parseFloat(_7.substr(_8+7))<=419.3){ -d.isSafari=2; -} -} -if(_6.indexOf("Gecko")>=0&&!d.isKhtml&&!d.isWebKit){ -d.isMozilla=d.isMoz=tv; -} -if(d.isMoz){ -d.isFF=parseFloat(_6.split("Firefox/")[1]||_6.split("Minefield/")[1])||undefined; -} -if(document.all&&!d.isOpera){ -d.isIE=parseFloat(_7.split("MSIE ")[1])||undefined; -var _9=document.documentMode; -if(_9&&_9!=5&&Math.floor(d.isIE)!=_9){ -d.isIE=_9; -} -} -if(dojo.isIE&&window.location.protocol==="file:"){ -dojo.config.ieForceActiveXXhr=true; -} -d.isQuirks=document.compatMode=="BackCompat"; -d.locale=dojo.config.locale||(d.isIE?n.userLanguage:n.language).toLowerCase(); -d._XMLHTTP_PROGIDS=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"]; -d._xhrObj=function(){ -var _a,_b; -if(!dojo.isIE||!dojo.config.ieForceActiveXXhr){ -try{ -_a=new XMLHttpRequest(); -} -catch(e){ -} -} -if(!_a){ -for(var i=0;i<3;++i){ -var _c=d._XMLHTTP_PROGIDS[i]; -try{ -_a=new ActiveXObject(_c); -} -catch(e){ -_b=e; -} -if(_a){ -d._XMLHTTP_PROGIDS=[_c]; -break; -} -} -} -if(!_a){ -throw new Error("XMLHTTP not available: "+_b); -} -return _a; -}; -d._isDocumentOk=function(_d){ -var _e=_d.status||0,lp=location.protocol; -return (_e>=200&&_e<300)||_e==304||_e==1223||(!_e&&(lp=="file:"||lp=="chrome:"||lp=="chrome-extension:"||lp=="app:")); +/*===== +dojo.isBrowser = { + // example: + // | if(dojo.isBrowser){ ... } }; -var _f=window.location+""; -var _10=document.getElementsByTagName("base"); -var _11=(_10&&_10.length>0); -d._getText=function(uri,_12){ -var _13=d._xhrObj(); -if(!_11&&dojo._Url){ -uri=(new dojo._Url(_f,uri)).toString(); -} -if(d.config.cacheBust){ -uri+=""; -uri+=(uri.indexOf("?")==-1?"?":"&")+String(d.config.cacheBust).replace(/\W+/g,""); -} -_13.open("GET",uri,false); -try{ -_13.send(null); -if(!d._isDocumentOk(_13)){ -var err=Error("Unable to load "+uri+" status:"+_13.status); -err.status=_13.status; -err.responseText=_13.responseText; -throw err; -} -} -catch(e){ -if(_12){ -return null; -} -throw e; -} -return _13.responseText; -}; -var _14=window; -var _15=function(_16,fp){ -var _17=_14.attachEvent||_14.addEventListener; -_16=_14.attachEvent?_16:_16.substring(2); -_17(_16,function(){ -fp.apply(_14,arguments); -},false); -}; -d._windowUnloaders=[]; -d.windowUnloaded=function(){ -var mll=d._windowUnloaders; -while(mll.length){ -(mll.pop())(); -} -d=null; -}; -var _18=0; -d.addOnWindowUnload=function(obj,_19){ -d._onto(d._windowUnloaders,obj,_19); -if(!_18){ -_18=1; -_15("onunload",d.windowUnloaded); -} + +dojo.isFF = { + // example: + // | if(dojo.isFF > 1){ ... } }; -var _1a=0; -d.addOnUnload=function(obj,_1b){ -d._onto(d._unloaders,obj,_1b); -if(!_1a){ -_1a=1; -_15("onbeforeunload",dojo.unloaded); -} + +dojo.isIE = { + // example: + // | if(dojo.isIE > 6){ + // | // we are IE7 + // | } }; -})(); -dojo._initFired=false; -dojo._loadInit=function(e){ -if(dojo._scrollIntervalId){ -clearInterval(dojo._scrollIntervalId); -dojo._scrollIntervalId=0; -} -if(!dojo._initFired){ -dojo._initFired=true; -if(!dojo.config.afterOnLoad&&window.detachEvent){ -window.detachEvent("onload",dojo._loadInit); -} -if(dojo._inFlightCount==0){ -dojo._modulesLoaded(); -} -} + +dojo.isSafari = { + // example: + // | if(dojo.isSafari){ ... } + // example: + // Detect iPhone: + // | if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){ + // | // we are iPhone. Note, iPod touch reports "iPod" above and fails this test. + // | } }; -if(!dojo.config.afterOnLoad){ -if(document.addEventListener){ -document.addEventListener("DOMContentLoaded",dojo._loadInit,false); -window.addEventListener("load",dojo._loadInit,false); -}else{ -if(window.attachEvent){ -window.attachEvent("onload",dojo._loadInit); -if(!dojo.config.skipIeDomLoaded&&self===self.top){ -dojo._scrollIntervalId=setInterval(function(){ -try{ -if(document.body){ -document.documentElement.doScroll("left"); -dojo._loadInit(); -} -} -catch(e){ -} -},30); -} -} -} -} -if(dojo.isIE){ -try{ -(function(){ -document.namespaces.add("v","urn:schemas-microsoft-com:vml"); -var _1c=["*","group","roundrect","oval","shape","rect","imagedata","path","textpath","text"],i=0,l=1,s=document.createStyleSheet(); -if(dojo.isIE>=8){ -i=1; -l=_1c.length; -} -for(;i= 0){ d.isOpera = tv; } + if(dua.indexOf("AdobeAIR") >= 0){ d.isAIR = 1; } + d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0; + d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined; + d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined; + d.isMac = dav.indexOf("Macintosh") >= 0; + + // safari detection derived from: + // http://developer.apple.com/internet/safari/faq.html#anchor2 + // http://developer.apple.com/internet/safari/uamatrix.html + var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0); + if(index && !dojo.isChrome){ + // try to grab the explicit Safari version first. If we don't get + // one, look for less than 419.3 as the indication that we're on something + // "Safari 2-ish". + d.isSafari = parseFloat(dav.split("Version/")[1]); + if(!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){ + d.isSafari = 2; + } + } + + if(dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit){ d.isMozilla = d.isMoz = tv; } + if(d.isMoz){ + //We really need to get away from this. Consider a sane isGecko approach for the future. + d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined; + } + if(document.all && !d.isOpera){ + d.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined; + //In cases where the page has an HTTP header or META tag with + //X-UA-Compatible, then it is in emulation mode. + //Make sure isIE reflects the desired version. + //document.documentMode of 5 means quirks mode. + //Only switch the value if documentMode's major version + //is different from isIE's major version. + var mode = document.documentMode; + if(mode && mode != 5 && Math.floor(d.isIE) != mode){ + d.isIE = mode; + } + } + + //Workaround to get local file loads of dojo to work on IE 7 + //by forcing to not use native xhr. + if(dojo.isIE && window.location.protocol === "file:"){ + dojo.config.ieForceActiveXXhr=true; + } + + d.isQuirks = document.compatMode == "BackCompat"; + + // TODO: is the HTML LANG attribute relevant? + d.locale = dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase(); + + // These are in order of decreasing likelihood; this will change in time. + d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; + + d._xhrObj = function(){ + // summary: + // does the work of portably generating a new XMLHTTPRequest object. + var http, last_e; + if(!dojo.isIE || !dojo.config.ieForceActiveXXhr){ + try{ http = new XMLHttpRequest(); }catch(e){} + } + if(!http){ + for(var i=0; i<3; ++i){ + var progid = d._XMLHTTP_PROGIDS[i]; + try{ + http = new ActiveXObject(progid); + }catch(e){ + last_e = e; + } + + if(http){ + d._XMLHTTP_PROGIDS = [progid]; // so faster next time + break; + } + } + } + + if(!http){ + throw new Error("XMLHTTP not available: "+last_e); + } + + return http; // XMLHTTPRequest instance + } + + d._isDocumentOk = function(http){ + var stat = http.status || 0, + lp = location.protocol; + return (stat >= 200 && stat < 300) || // Boolean + stat == 304 || // allow any 2XX response code + stat == 1223 || // get it out of the cache + // Internet Explorer mangled the status code OR we're Titanium/browser chrome/chrome extension requesting a local file + (!stat && (lp == "file:" || lp == "chrome:" || lp == "chrome-extension:" || lp == "app:") ); + } + + //See if base tag is in use. + //This is to fix http://trac.dojotoolkit.org/ticket/3973, + //but really, we need to find out how to get rid of the dojo._Url reference + //below and still have DOH work with the dojo.i18n test following some other + //test that uses the test frame to load a document (trac #2757). + //Opera still has problems, but perhaps a larger issue of base tag support + //with XHR requests (hasBase is true, but the request is still made to document + //path, not base path). + var owloc = window.location+""; + var base = document.getElementsByTagName("base"); + var hasBase = (base && base.length > 0); + + d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){ + // summary: Read the contents of the specified uri and return those contents. + // uri: + // A relative or absolute uri. If absolute, it still must be in + // the same "domain" as we are. + // fail_ok: + // Default false. If fail_ok and loading fails, return null + // instead of throwing. + // returns: The response text. null is returned when there is a + // failure and failure is okay (an exception otherwise) + + // NOTE: must be declared before scope switches ie. this._xhrObj() + var http = d._xhrObj(); + + if(!hasBase && dojo._Url){ + uri = (new dojo._Url(owloc, uri)).toString(); + } + + if(d.config.cacheBust){ + //Make sure we have a string before string methods are used on uri + uri += ""; + uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,""); + } + + http.open('GET', uri, false); + try{ + http.send(null); + if(!d._isDocumentOk(http)){ + var err = Error("Unable to load "+uri+" status:"+ http.status); + err.status = http.status; + err.responseText = http.responseText; + throw err; + } + }catch(e){ + if(fail_ok){ return null; } // null + // rethrow the exception + throw e; + } + return http.responseText; // String + } + + + var _w = window; + var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){ + // summary: + // non-destructively adds the specified function to the node's + // evtName handler. + // evtName: should be in the form "onclick" for "onclick" handlers. + // Make sure you pass in the "on" part. + var _a = _w.attachEvent || _w.addEventListener; + evtName = _w.attachEvent ? evtName : evtName.substring(2); + _a(evtName, function(){ + fp.apply(_w, arguments); + }, false); + }; + + + d._windowUnloaders = []; + + d.windowUnloaded = function(){ + // summary: + // signal fired by impending window destruction. You may use + // dojo.addOnWindowUnload() to register a listener for this + // event. NOTE: if you wish to dojo.connect() to this method + // to perform page/application cleanup, be aware that this + // event WILL NOT fire if no handler has been registered with + // dojo.addOnWindowUnload. This behavior started in Dojo 1.3. + // Previous versions always triggered dojo.windowUnloaded. See + // dojo.addOnWindowUnload for more info. + var mll = d._windowUnloaders; + while(mll.length){ + (mll.pop())(); + } + d = null; + }; + + var _onWindowUnloadAttached = 0; + d.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ + // summary: + // registers a function to be triggered when window.onunload + // fires. + // description: + // The first time that addOnWindowUnload is called Dojo + // will register a page listener to trigger your unload + // handler with. Note that registering these handlers may + // destory "fastback" page caching in browsers that support + // it. Be careful trying to modify the DOM or access + // JavaScript properties during this phase of page unloading: + // they may not always be available. Consider + // dojo.addOnUnload() if you need to modify the DOM or do + // heavy JavaScript work since it fires at the eqivalent of + // the page's "onbeforeunload" event. + // example: + // | dojo.addOnWindowUnload(functionPointer) + // | dojo.addOnWindowUnload(object, "functionName"); + // | dojo.addOnWindowUnload(object, function(){ /* ... */}); + + d._onto(d._windowUnloaders, obj, functionName); + if(!_onWindowUnloadAttached){ + _onWindowUnloadAttached = 1; + _handleNodeEvent("onunload", d.windowUnloaded); + } + }; + + var _onUnloadAttached = 0; + d.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ + // summary: + // registers a function to be triggered when the page unloads. + // description: + // The first time that addOnUnload is called Dojo will + // register a page listener to trigger your unload handler + // with. + // + // In a browser enviroment, the functions will be triggered + // during the window.onbeforeunload event. Be careful of doing + // too much work in an unload handler. onbeforeunload can be + // triggered if a link to download a file is clicked, or if + // the link is a javascript: link. In these cases, the + // onbeforeunload event fires, but the document is not + // actually destroyed. So be careful about doing destructive + // operations in a dojo.addOnUnload callback. + // + // Further note that calling dojo.addOnUnload will prevent + // browsers from using a "fast back" cache to make page + // loading via back button instantaneous. + // example: + // | dojo.addOnUnload(functionPointer) + // | dojo.addOnUnload(object, "functionName") + // | dojo.addOnUnload(object, function(){ /* ... */}); + + d._onto(d._unloaders, obj, functionName); + if(!_onUnloadAttached){ + _onUnloadAttached = 1; + _handleNodeEvent("onbeforeunload", dojo.unloaded); + } + }; + + })(); + + //START DOMContentLoaded + dojo._initFired = false; + dojo._loadInit = function(e){ + if(dojo._scrollIntervalId){ + clearInterval(dojo._scrollIntervalId); + dojo._scrollIntervalId = 0; + } + + if(!dojo._initFired){ + dojo._initFired = true; + + //Help out IE to avoid memory leak. + if(!dojo.config.afterOnLoad && window.detachEvent){ + window.detachEvent("onload", dojo._loadInit); + } + + if(dojo._inFlightCount == 0){ + dojo._modulesLoaded(); + } + } + } + + if(!dojo.config.afterOnLoad){ + if(document.addEventListener){ + //Standards. Hooray! Assumption here that if standards based, + //it knows about DOMContentLoaded. It is OK if it does not, the fall through + //to window onload should be good enough. + document.addEventListener("DOMContentLoaded", dojo._loadInit, false); + window.addEventListener("load", dojo._loadInit, false); + }else if(window.attachEvent){ + window.attachEvent("onload", dojo._loadInit); + + //DOMContentLoaded approximation. Diego Perini found this MSDN article + //that indicates doScroll is available after DOM ready, so do a setTimeout + //to check when it is available. + //http://msdn.microsoft.com/en-us/library/ms531426.aspx + if(!dojo.config.skipIeDomLoaded && self === self.top){ + dojo._scrollIntervalId = setInterval(function (){ + try{ + //When dojo is loaded into an iframe in an IE HTML Application + //(HTA), such as in a selenium test, javascript in the iframe + //can't see anything outside of it, so self===self.top is true, + //but the iframe is not the top window and doScroll will be + //available before document.body is set. Test document.body + //before trying the doScroll trick + if(document.body){ + document.documentElement.doScroll("left"); + dojo._loadInit(); + } + }catch (e){} + }, 30); + } + } + } + + if(dojo.isIE){ + try{ + (function(){ + document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); + var vmlElems = ["*", "group", "roundrect", "oval", "shape", "rect", "imagedata", "path", "textpath", "text"], + i = 0, l = 1, s = document.createStyleSheet(); + if(dojo.isIE >= 8){ + i = 1; + l = vmlElems.length; + } + for(; i < l; ++i){ + s.addRule("v\\:" + vmlElems[i], "behavior:url(#default#VML); display:inline-block"); + } + })(); + }catch(e){} + } + //END DOMContentLoaded + + + /* + OpenAjax.subscribe("OpenAjax", "onload", function(){ + if(dojo._inFlightCount == 0){ + dojo._modulesLoaded(); + } + }); + + OpenAjax.subscribe("OpenAjax", "onunload", function(){ + dojo.unloaded(); + }); + */ +} //if (typeof window != 'undefined') + +//Register any module paths set up in djConfig. Need to do this +//in the hostenvs since hostenv_browser can read djConfig from a +//script tag's attribute. (function(){ -var mp=dojo.config["modulePaths"]; -if(mp){ -for(var _1d in mp){ -dojo.registerModulePath(_1d,mp[_1d]); -} -} + var mp = dojo.config["modulePaths"]; + if(mp){ + for(var param in mp){ + dojo.registerModulePath(param, mp[param]); + } + } })(); + +//Load debug code if necessary. if(dojo.config.isDebug){ -dojo.require("dojo._firebug.firebug"); + dojo.require("dojo._firebug.firebug"); } + if(dojo.config.debugAtAllCosts){ -dojo.config.useXDomain=true; -dojo.require("dojo._base._loader.loader_xd"); -dojo.require("dojo._base._loader.loader_debug"); -dojo.require("dojo.i18n"); + dojo.config.useXDomain = true; + dojo.require("dojo._base._loader.loader_xd"); + dojo.require("dojo._base._loader.loader_debug"); + dojo.require("dojo.i18n"); } -- cgit v1.2.3