1
0
mirror of https://git.tt-rss.org/git/tt-rss.git synced 2025-12-13 22:25:55 +00:00

build custom layer of Dojo to speed up loading of tt-rss (refs #293)

This commit is contained in:
Andrew Dolgov
2011-03-04 19:02:28 +03:00
parent cfad9259a6
commit a089699c89
144 changed files with 55627 additions and 13766 deletions

View File

@@ -5,133 +5,235 @@
*/
if(!dojo._hasResource["dojo.hash"]){
dojo._hasResource["dojo.hash"]=true;
if(!dojo._hasResource["dojo.hash"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojo.hash"] = true;
dojo.provide("dojo.hash");
//TODOC: where does this go?
// summary:
// Methods for monitoring and updating the hash in the browser URL.
//
// example:
// dojo.subscribe("/dojo/hashchange", context, callback);
//
// function callback (hashValue){
// // do something based on the hash value.
// }
(function(){
dojo.hash=function(_1,_2){
if(!arguments.length){
return _3();
}
if(_1.charAt(0)=="#"){
_1=_1.substring(1);
}
if(_2){
_4(_1);
}else{
location.href="#"+_1;
}
return _1;
};
var _5=null,_6=null,_7=dojo.config.hashPollFrequency||100;
function _8(_9,_a){
var i=_9.indexOf(_a);
return (i>=0)?_9.substring(i+1):"";
};
function _3(){
return _8(location.href,"#");
};
function _b(){
dojo.publish("/dojo/hashchange",[_3()]);
};
function _c(){
if(_3()===_5){
return;
}
_5=_3();
_b();
};
function _4(_d){
if(_6){
if(_6.isTransitioning()){
setTimeout(dojo.hitch(null,_4,_d),_7);
return;
}
var _e=_6.iframe.location.href;
var _f=_e.indexOf("?");
_6.iframe.location.replace(_e.substring(0,_f)+"?"+_d);
return;
}
location.replace("#"+_d);
_c();
};
function _10(){
var ifr=document.createElement("iframe"),_11="dojo-hash-iframe",_12=dojo.config.dojoBlankHtmlUrl||dojo.moduleUrl("dojo","resources/blank.html");
ifr.id=_11;
ifr.src=_12+"?"+_3();
ifr.style.display="none";
document.body.appendChild(ifr);
this.iframe=dojo.global[_11];
var _13,_14,_15,_16,_17,_18=this.iframe.location;
function _19(){
_5=_3();
_13=_17?_5:_8(_18.href,"?");
_14=false;
_15=null;
};
this.isTransitioning=function(){
return _14;
};
this.pollLocation=function(){
if(!_17){
try{
var _1a=_8(_18.href,"?");
if(document.title!=_16){
_16=this.iframe.document.title=document.title;
}
}
catch(e){
_17=true;
console.error("dojo.hash: Error adding history entry. Server unreachable.");
}
}
var _1b=_3();
if(_14&&_5===_1b){
if(_17||_1a===_15){
_19();
_b();
}else{
setTimeout(dojo.hitch(this,this.pollLocation),0);
return;
}
}else{
if(_5===_1b&&(_17||_13===_1a)){
}else{
if(_5!==_1b){
_5=_1b;
_14=true;
_15=_1b;
ifr.src=_12+"?"+_15;
_17=false;
setTimeout(dojo.hitch(this,this.pollLocation),0);
return;
}else{
if(!_17){
location.href="#"+_18.search.substring(1);
_19();
_b();
}
}
}
}
setTimeout(dojo.hitch(this,this.pollLocation),_7);
};
_19();
setTimeout(dojo.hitch(this,this.pollLocation),_7);
};
dojo.addOnLoad(function(){
if("onhashchange" in dojo.global&&(!dojo.isIE||(dojo.isIE>=8&&document.compatMode!="BackCompat"))){
dojo.connect(dojo.global,"onhashchange",_b);
}else{
if(document.addEventListener){
_5=_3();
setInterval(_c,_7);
}else{
if(document.attachEvent){
_6=new _10();
}
}
}
});
dojo.hash = function(/* String? */ hash, /* Boolean? */ replace){
// summary:
// Gets or sets the hash string.
// description:
// Handles getting and setting of location.hash.
// - If no arguments are passed, acts as a getter.
// - If a string is passed, acts as a setter.
// hash:
// String: the hash is set - #string.
// replace:
// Boolean: If true, updates the hash value in the current history
// state instead of creating a new history state.
// returns:
// when used as a getter, returns the current hash string.
// when used as a setter, returns the new hash string.
// getter
if(!arguments.length){
return _getHash();
}
// setter
if(hash.charAt(0) == "#"){
hash = hash.substring(1);
}
if(replace){
_replace(hash);
}else{
location.href = "#" + hash;
}
return hash; // String
}
// Global vars
var _recentHash = null,
_ieUriMonitor = null,
_pollFrequency = dojo.config.hashPollFrequency || 100;
//Internal functions
function _getSegment(str, delimiter){
var i = str.indexOf(delimiter);
return (i >= 0) ? str.substring(i+1) : "";
}
function _getHash(){
return _getSegment(location.href, "#");
}
function _dispatchEvent(){
dojo.publish("/dojo/hashchange", [_getHash()]);
}
function _pollLocation(){
if(_getHash() === _recentHash){
return;
}
_recentHash = _getHash();
_dispatchEvent();
}
function _replace(hash){
if(_ieUriMonitor){
if(_ieUriMonitor.isTransitioning()){
setTimeout(dojo.hitch(null,_replace,hash), _pollFrequency);
return;
}
var href = _ieUriMonitor.iframe.location.href;
var index = href.indexOf('?');
// main frame will detect and update itself
_ieUriMonitor.iframe.location.replace(href.substring(0, index) + "?" + hash);
return;
}
location.replace("#"+hash);
_pollLocation();
}
function IEUriMonitor(){
// summary:
// Determine if the browser's URI has changed or if the user has pressed the
// back or forward button. If so, call _dispatchEvent.
//
// description:
// IE doesn't add changes to the URI's hash into the history unless the hash
// value corresponds to an actual named anchor in the document. To get around
// this IE difference, we use a background IFrame to maintain a back-forward
// history, by updating the IFrame's query string to correspond to the
// value of the main browser location's hash value.
//
// E.g. if the value of the browser window's location changes to
//
// #action=someAction
//
// ... then we'd update the IFrame's source to:
//
// ?action=someAction
//
// This design leads to a somewhat complex state machine, which is
// described below:
//
// s1: Stable state - neither the window's location has changed nor
// has the IFrame's location. Note that this is the 99.9% case, so
// we optimize for it.
// Transitions: s1, s2, s3
// s2: Window's location changed - when a user clicks a hyperlink or
// code programmatically changes the window's URI.
// Transitions: s4
// s3: Iframe's location changed as a result of user pressing back or
// forward - when the user presses back or forward, the location of
// the background's iframe changes to the previous or next value in
// its history.
// Transitions: s1
// s4: IEUriMonitor has programmatically changed the location of the
// background iframe, but it's location hasn't yet changed. In this
// case we do nothing because we need to wait for the iframe's
// location to reflect its actual state.
// Transitions: s4, s5
// s5: IEUriMonitor has programmatically changed the location of the
// background iframe, and the iframe's location has caught up with
// reality. In this case we need to transition to s1.
// Transitions: s1
//
// The hashchange event is always dispatched on the transition back to s1.
//
// create and append iframe
var ifr = document.createElement("iframe"),
IFRAME_ID = "dojo-hash-iframe",
ifrSrc = dojo.config.dojoBlankHtmlUrl || dojo.moduleUrl("dojo", "resources/blank.html");
ifr.id = IFRAME_ID;
ifr.src = ifrSrc + "?" + _getHash();
ifr.style.display = "none";
document.body.appendChild(ifr);
this.iframe = dojo.global[IFRAME_ID];
var recentIframeQuery, transitioning, expectedIFrameQuery, docTitle, ifrOffline,
iframeLoc = this.iframe.location;
function resetState(){
_recentHash = _getHash();
recentIframeQuery = ifrOffline ? _recentHash : _getSegment(iframeLoc.href, "?");
transitioning = false;
expectedIFrameQuery = null;
}
this.isTransitioning = function(){
return transitioning;
}
this.pollLocation = function(){
if(!ifrOffline) {
try{
//see if we can access the iframe's location without a permission denied error
var iframeSearch = _getSegment(iframeLoc.href, "?");
//good, the iframe is same origin (no thrown exception)
if(document.title != docTitle){ //sync title of main window with title of iframe.
docTitle = this.iframe.document.title = document.title;
}
}catch(e){
//permission denied - server cannot be reached.
ifrOffline = true;
console.error("dojo.hash: Error adding history entry. Server unreachable.");
}
}
var hash = _getHash();
if(transitioning && _recentHash === hash){
// we're in an iframe transition (s4 or s5)
if(ifrOffline || iframeSearch === expectedIFrameQuery){
// s5 (iframe caught up to main window or iframe offline), transition back to s1
resetState();
_dispatchEvent();
}else{
// s4 (waiting for iframe to catch up to main window)
setTimeout(dojo.hitch(this,this.pollLocation),0);
return;
}
}else if(_recentHash === hash && (ifrOffline || recentIframeQuery === iframeSearch)){
// we're in stable state (s1, iframe query == main window hash), do nothing
}else{
// the user has initiated a URL change somehow.
// sync iframe query <-> main window hash
if(_recentHash !== hash){
// s2 (main window location changed), set iframe url and transition to s4
_recentHash = hash;
transitioning = true;
expectedIFrameQuery = hash;
ifr.src = ifrSrc + "?" + expectedIFrameQuery;
ifrOffline = false; //we're updating the iframe src - set offline to false so we can check again on next poll.
setTimeout(dojo.hitch(this,this.pollLocation),0); //yielded transition to s4 while iframe reloads.
return;
}else if(!ifrOffline){
// s3 (iframe location changed via back/forward button), set main window url and transition to s1.
location.href = "#" + iframeLoc.search.substring(1);
resetState();
_dispatchEvent();
}
}
setTimeout(dojo.hitch(this,this.pollLocation), _pollFrequency);
}
resetState(); // initialize state (transition to s1)
setTimeout(dojo.hitch(this,this.pollLocation), _pollFrequency);
}
dojo.addOnLoad(function(){
if("onhashchange" in dojo.global && (!dojo.isIE || (dojo.isIE >= 8 && document.compatMode != "BackCompat"))){ //need this IE browser test because "onhashchange" exists in IE8 in IE7 mode
dojo.connect(dojo.global,"onhashchange",_dispatchEvent);
}else{
if(document.addEventListener){ // Non-IE
_recentHash = _getHash();
setInterval(_pollLocation, _pollFrequency); //Poll the window location for changes
}else if(document.attachEvent){ // IE7-
//Use hidden iframe in versions of IE that don't have onhashchange event
_ieUriMonitor = new IEUriMonitor();
}
// else non-supported browser, do nothing.
}
});
})();
}