Skip to content

Instantly share code, notes, and snippets.

@bmeck
Created March 28, 2011 18:05
Show Gist options
  • Save bmeck/890940 to your computer and use it in GitHub Desktop.
Save bmeck/890940 to your computer and use it in GitHub Desktop.
An extensible preloader
//
// Create our type
//
function PreLoader() {
this._queue = [];
this._mime = {};
this._handlers = {};
this._loaded = [];
};
PreLoader.prototype.addFileType = function addFileType(extension,mime) {
var ext = "." + extension.toLowerCase().replace(/^[.]/,"");
this._mime[ ext ] = mime;
return this;
};
//cb(next(err,?))
PreLoader.prototype.addMimeHandler = function addMimeHandler(mime,cb) {
;(this._handlers[ mime ] || (this._handlers[ mime ] = [])).push(cb);
return this;
};
//mime will be inferred if missing
//callback and mime are optional
PreLoader.prototype.queue = function queue(src,mime,callback) {
var self = this;
if(src instanceof Array || (typeof src === "object" && src.length)) {
if(typeof mime === "function") {
callback = mime;
}
var done = 0;
var l = src.length;
function finish() {
done++;
if(done === l) {
if(callback) callback(src,self);
}
};
for(var i = 0; i < l; i++) {
queue.call(this,src[i],finish);
}
return;
}
if(arguments.length === 2 && typeof mime === "function") {
callback = mime;
mime = this._mime[ src.match(/[.]\w+(?=[?]|$)/)[0].toLowerCase() ];;
}
else {
mime = mime || this._mime[ src.match(/[.]\w+(?=[?]|$)/)[0].toLowerCase() ];
}
var handlers = this._handlers[ mime ];
if(!handlers) {
var parts = mime.split("/");
while(!handlers) {
parts.pop();
handlers = this._handlers[ parts.join("/") + "/*" ]
}
}
var l = handlers.length;
var finished = 0;
function next() {
finished++;
if(finished === l) {
finished++;
var queue = self.queue;
for(var i = 0; i < queue.length; i++) {
if(queue[i] === src) {
queue.splice(i,1);
}
}
self._loaded.push(src);
if(callback) callback(src,self);
}
}
for(var i = 0; i < l; i++) {
handlers[ i ](src,next);
}
return this;
};
//
// Set up a default preloader for websites
//
var preload = new PreLoader();
preload.addFileType("js","text/javascript");
preload.addFileType("jpg","image/jpeg");
preload.addFileType("jpeg","image/jpeg");
preload.addFileType("gif","image/gif");
preload.addFileType("png","image/png");
preload.addFileType("css","text/css");
preload.addMimeHandler("text/javascript",function(src,next){
var elem = document.createElement("script");
elem.type = "text/javascript";
elem.src = src;
var done = false;
function finish(err) {
if(done) return;
done = true;
elem.parentNode.removeChild(elem);
next(err,elem);
}
elem.onload = function onLoad(){finish();};
elem.onreadystatechange = function onReadyState() {
var state = String(elem.readyState).toLowerCase();
if(state === "completed") finish();
};
elem.onerror = function onError(){finish(arguments);};
document.body.appendChild(elem);
});
preload.addMimeHandler("image/*",function(src,next){
var elem = document.createElement("img");
elem.src = src;
var done = false;
function finish(err) {
if(done) return;
done = true;
elem.parentNode.removeChild(elem);
next(err,elem);
}
elem.onload = finish;
elem.onreadystatechange = function onReadyState() {
var state = String(elem.readyState).toLowerCase();
if(state === "completed") finish(false);
};
elem.onerror = function onError(){finish(arguments);};
document.body.appendChild(elem);
});
preload.addMimeHandler("text/css",function(src,next){
var elem = document.createElement("link");
elem.type = "text/css";
elem.rel = "stylesheet";
elem.src = src;
var done = false;
function finish(err) {
if(done) return;
done = true;
elem.parentNode.removeChild(elem);
next(err,elem);
}
elem.onload = finish;
elem.onreadystatechange = function onReadyState() {
var state = String(elem.readyState).toLowerCase();
if(state === "completed") finish();
};
elem.onerror = function onError(){finish(arguments);};
document.body.appendChild(elem);
});
// spew out some info
function load(src,preloader) {
console.log("loaded:",preloader._loaded.length ,"still queued:",preloader._queue.length);
}
var arr = []
for(var i = 0; i < 100; i++) {
arr.push("localhost?v="+i);
}
preload.queue(arr,load);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment