Created
December 1, 2010 22:25
-
-
Save mindplay-dk/724347 to your computer and use it in GitHub Desktop.
Dynamic loader for JS and CSS resources
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
/* | |
Version: 1.1 | |
Developer: Rasmus Schultz <http://mindplay.dk> | |
License: GPL v3 <http://www.gnu.org/licenses/gpl-3.0-standalone.html> | |
Gist: <https://gist.github.com/724347> | |
Removing this notice from the source code would be bad karma. | |
*/ | |
var Loader = { | |
q: [], // the Queue for pending items to be loaded | |
reg: {}, // a registry to ensure items are loaded only once | |
load: function(url, cb, context, driver, once) { | |
var dd = url.split('.').pop(); | |
if (!Loader.drivers[dd]) dd = driver || 'js'; | |
var p = new Loader.Proxy( | |
{ url: url, cb: cb || function(){}, reg: once, driver: dd, context: context } | |
); | |
Loader.q.push(p); | |
Loader.next(); | |
return p; | |
}, | |
once: function(url, cb, context, driver) { | |
this.load(url, cb, context, driver, 1); | |
}, | |
next: function() { | |
for (i=0; i<Loader.q.length; i++) { | |
var l = Loader.q[i]; | |
if (l.state == 1) return; // already loading | |
if (l.state == 0) return l.load(); // not loading (and not yet loaded) | |
} | |
} | |
} | |
Loader.Proxy = function(opt) { | |
this.driver = opt.driver; | |
this.context = opt.context || this; | |
this.url = opt.url; | |
this.reg = opt.reg; | |
this.state = 0; // inactive | |
this.cb = opt.cb; | |
this.load = function() { | |
if (this.reg && Loader.reg[this.url]) return this.loaded(); // already loaded once | |
this.state = 1; // loading | |
var hd = document.getElementsByTagName("head")[0]; | |
var el = Loader.drivers[this.driver](this, this.url + (this.url.indexOf('?') == -1 ? '?' : '&') + new Date().getTime()); | |
hd.appendChild(el); | |
} | |
this.loaded = function() { | |
this.state = 2; // loaded | |
if (this.reg) Loader.reg[this.url] = 1; | |
this.cb.call(this.context); | |
Loader.next(); | |
} | |
} | |
Loader.drivers = { | |
js: function(proxy, url) { | |
var el = document.createElement('script'); | |
el.type = 'text/javascript'; | |
el.src = url; | |
var me = proxy; | |
if (el.attachEvent) { // IE | |
el.attachEvent('onreadystatechange', function() { | |
if (el.readyState == 'loaded' || el.readyState == 'complete') me.loaded(); | |
}); | |
} else { // DOM | |
el.onload = function() { me.loaded(); } | |
} | |
return el; | |
}, | |
css: function(proxy, url) { | |
var el = document.createElement('link'); | |
el.rel = 'stylesheet'; | |
el.type = 'text/css'; | |
el.href = url; | |
el.media = 'all'; | |
new (function(link, proxy){ | |
this.index = document.styleSheets.length; | |
this.link = link; | |
this.proxy = proxy; | |
var me = this; | |
this.check = function() { | |
try { | |
var s = document.styleSheets[me.index]; | |
if ((s.rules || s.cssRules).length) { // DOM || FF | |
window.clearInterval(me.int); | |
me.proxy.loaded(); | |
} | |
} catch (e) {}; | |
} | |
this.int = window.setInterval(this.check, 100); | |
})(el, proxy); | |
return el; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Loader.js
Dynamically loads JavaScript and CSS files on demand.
Features
Some requirements that this class fulfills:
Limitations
There is currently no error-handling - missing files and empty stylesheets will throw this script off.
Previous version of my loader used a method of injection that allowed scripts from foreign domains to load and execute within the page, without security restrictions. This version uses a different technique, where scripts are actually embedded from their original source, which means that cross-domain security restrictions may apply.
Usage
There are two methods for loading resources:
Loader.load( url, [callback-function], [context-object], [driver-name] );
Loader.once( url, [callback-function], [context-object], [driver-name] );
The load() method will allow you to load the same resource repeatedly, while the once() method will ensure that the same URL is only loaded once. (Note that the callback-function will be called on time - that is, when the source would have loaded; callbacks are guaranteed to fire in the order the resources were requested.)
Arguments for the two functions are identical: