Created
December 22, 2014 08:54
-
-
Save weger/e01d0bcf3fe3c059f891 to your computer and use it in GitHub Desktop.
动态加载css,监听onload事件
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
WebKit: | |
- linkNode.sheet 在 css 文件下载完成并解析好后才有值,之前为 undefined | |
- linkNode.sheet.cssRules 同域时返回 CSSRuleList, 跨域时返回 null | |
- WebKit >= 535.23 后支持 onload / onerror | |
Firefox: | |
- linkNode.sheet 在 css 插入 DOM 中后立刻有值,插入前为 undefined | |
- linkNode.sheet.cssRules 在文件还未下好时,抛出 NS_ERROR_DOM_INVALID_ACCESS_ERR | |
在文件下载并解析好后, | |
同域时返回 cssRuleList | |
跨域时抛出 NS_ERROR_DOM_SECURITY_ERR | |
- Firefox >= 9.0 后支持 onload / onerror | |
IE / Opera: | |
- linkNode.sheet 和 cssRules 在 css 插入 DOM 后都立刻可访问,cssRules 为 [] | |
- 当文件下载完成时,cssRules 为 cssRuleList | |
- Opera 只在成功时触发 onload,失败时不会触发 onerror | |
- IE 下,无论成功失败,都会触发 onload,不会触发 onerror,中间会触发 onreadystatechange | |
- 期待 IE 和 Opera 的后续版本能正确支持 onerror | |
https://bugs.dojotoolkit.org/attachment/ticket/5402/requireCss.js | |
*/ | |
dojo.provide("dojo.requireCss"); | |
(function(){ | |
var cssCounter = 0; | |
var cssInFlight = {}; | |
var cssInFlightIntvl = null; | |
var cssStartTime = 0; | |
var idPrefix = dojo._scopeName + "RequireCss"; | |
var _watchCssInFlight = function(){ | |
//summary: watches to make sure all css files have loaded. | |
var stillWaiting = false; | |
for(var param in cssInFlight){ | |
//Protect against bad JS modifying Object.prototype | |
if(typeof param == "string" && param.indexOf(idPrefix) == 0){ | |
console.debug(cssInFlight[param].sheet); | |
if((dojo.isMoz || dojo.isSafari) && cssInFlight[param].sheet.cssRules){ | |
//Since moz and safari do not work with onload callbacks on the link | |
//tag, see if the sheet and sheet.cssRules exist. If so, then assume | |
//the css file has be loaded. | |
delete cssInFlight[param]; | |
}else{ | |
stillWaiting = true; | |
} | |
} | |
} | |
if(stillWaiting){ | |
//Make sure we have not reached the timeout stage. | |
var waitInterval = (dojo.config.cssWaitSeconds || 15) * 1000; | |
if((cssStartTime + waitInterval) < (new Date()).getTime()){ | |
var err = "Timed out waiting for css files: "; | |
for(param in cssInFlight){ | |
err += cssInFlight[param].href + " "; | |
} | |
throw err; | |
} | |
}else{ | |
//All loaded. Clean up. | |
console.debug("all done"); | |
clearInterval(cssInFlightIntvl); | |
cssInFlightIntvl = null; | |
} | |
} | |
dojo.requireCss = function(/*String*/resourceName){ | |
//summary: Converts the resource name ("some.thing") to a CSS URL | |
//(http://some.domain.com/path/to/some/thing.css), then adds the CSS file | |
//to the page. Full urls can be passed in (instead of a "some.thing" resourceName. | |
//It also registers this CSS file with the dojo loader. This | |
//means that if you do a dojo.addOnLoad() callback after calling this function, | |
//the addOnLoad callback will not be fired until the CSS file has loaded. | |
//Note that style sheets may be evaluated in a different order than the order | |
//they appear in the DOM. If you want precise ordering of style rules, make | |
//one call to this function, then in a dojo.addOnLoad() callback, load the other, | |
//and repeat this call structure until you load all the stylesheets. | |
//Example: | |
// dojo.requireCss("some.thing"); | |
// dojo.requireCss("http://some.domain.com/path/to/some/thing.css"); | |
//Translate resource name to a file path | |
var path = resourceName; | |
if(path.indexOf("/") == -1){ | |
path = dojo._getModuleSymbols(resourceName).join("/") + '.css'; | |
path = ((path.charAt(0) == '/' || path.match(/^\w+:/)) ? "" : dojo.baseUrl) + path; | |
} | |
if(dojo.config.cacheBust){ | |
path += (path.indexOf("?") == -1 ? "?" : "&") + String(dojo.config.cacheBust).replace(/\W+/g,""); | |
} | |
//Create the link node | |
var link = dojo.doc.createElement("link"); | |
link.id = idPrefix + (cssCounter++); | |
link.type = "text/css"; | |
link.rel = "stylesheet"; | |
link.href = path; | |
cssInFlight[link.id] = link; | |
console.debug(link.id + " created"); | |
//Set up loader hooks. | |
//TODO | |
//Register the onload trigger, if supported. | |
if(!(dojo.isMoz || dojo.isSafari)){ | |
//IE and Opera, which support onload. A not test is used in the above if | |
//since for moz and safari, those are the only ones that are tested to have | |
//the sheet property that we will test in the inflight | |
//watch, so want to match that test with the one used here. | |
link.onload = function(){ | |
console.debug(link.id + " loaded"); | |
delete cssInFlight[link.id]; | |
//Try to help break circular memory leaks. | |
link.onload = null; | |
} | |
} | |
//Attach the node to document. | |
if(!this.headElement){ | |
this._headElement = document.getElementsByTagName("head")[0]; | |
//Head element may not exist, particularly in html | |
//html 4 or tag soup cases where the page does not | |
//have a head tag in it. Use html element, since that will exist. | |
//Seems to be an issue mostly with Opera 9 and to lesser extent Safari 2 | |
if(!this._headElement){ | |
this._headElement = document.getElementsByTagName("html")[0]; | |
} | |
} | |
console.debug(link.id + " adding to head"); | |
this._headElement.appendChild(link); | |
//Start the inflight watch. | |
cssStartTime = (new Date()).getTime(); | |
if(!cssInFlightIntvl){ | |
cssInFlightIntvl = setInterval(_watchCssInFlight, 100); | |
} | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment