PDA

View Full Version : Ext.ux.Loader: Load js/css Files Dynamically



mm_202
22 Aug 2010, 5:54 PM
I looked and couldn't find something that would fit my needs of dynamically loading .css files, so I hashed it together and wanted to share it in case someone else runs into the same need.

This allows you to load javascript and CSS files dynamically, and leaves room to add support for other file types.

This is basically a modified buildScriptTag in Loader.js:

buildScriptTag: function(filename, callback) {
var exten = filename.substr(filename.lastIndexOf('.')+1);
//console.log('buildScriptTag: filename=[%s], exten=[%s]', filename, exten);
if(exten=='js') {
var script = document.createElement('script');
script.type = "text/javascript";
script.src = filename;

//IE has a different way of handling <script> loads, so we need to check for it here
if(script.readyState) {
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
};
} else {
script.onload = callback;
}
return script;
}
if(exten=='css') {
var style = document.createElement('link');
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = filename;
callback();
return style;
}
}

Here is the full file (Ext.ux.Loader.js) for those not wanting to modify the extjs files:

// 100822: Taken from Extjs 3.2.1. Dynamically loads js/css files and allows room for expansion.

Ext.namespace('Ext.ux');

Ext.ux.Loader = Ext.apply({}, {
load: function(fileList, callback, scope, preserveOrder) {
var scope = scope || this,
head = document.getElementsByTagName("head")[0],
fragment = document.createDocumentFragment(),
numFiles = fileList.length,
loadedFiles = 0,
me = this;

// Loads a particular file from the fileList by index. This is used when preserving order
var loadFileIndex = function(index) {
head.appendChild(
me.buildScriptTag(fileList[index], onFileLoaded)
);
};

/**
* Callback function which is called after each file has been loaded. This calls the callback
* passed to load once the final file in the fileList has been loaded
*/
var onFileLoaded = function() {
loadedFiles ++;

//if this was the last file, call the callback, otherwise load the next file
if (numFiles == loadedFiles && typeof callback == 'function') {
callback.call(scope);
} else {
if (preserveOrder === true) {
loadFileIndex(loadedFiles);
}
}
};

if (preserveOrder === true) {
loadFileIndex.call(this, 0);
} else {
//load each file (most browsers will do this in parallel)
Ext.each(fileList, function(file, index) {
fragment.appendChild(
this.buildScriptTag(file, onFileLoaded)
);
}, this);

head.appendChild(fragment);
}
},

buildScriptTag: function(filename, callback) {
var exten = filename.substr(filename.lastIndexOf('.')+1);
//console.log('Loader.buildScriptTag: filename=[%s], exten=[%s]', filename, exten);
if(exten=='js') {
var script = document.createElement('script');
script.type = "text/javascript";
script.src = filename;

//IE has a different way of handling <script> loads, so we need to check for it here
if(script.readyState) {
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
};
} else {
script.onload = callback;
}
return script;
}
if(exten=='css') {
var style = document.createElement('link');
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = filename;
callback();
return style;
}
}
});


Simple example usage:

var td = new Date();
Ext.ux.Loader.load([
'js/extjs/examples/ux/Spinner.js',
'js/extjs/examples/ux/SpinnerField.js',
'js/extjs/examples/ux/css/Spinner.css',
'spinnerexample.js'],
function() { // callback when finished loading
console.log('Loaded files successfully. (loadtime: %dms)', td.getElapsed());
Example.Spinner();
},
this // scope
);

Tested in FF 3.6.8 and Chrome 5.0 without any problems. Feedback welcome.

greyknght1
24 Aug 2010, 6:20 AM
Looks good. I am going to give it a try. I will be using IE 7-8 so if I run into any problems I will let you know. Thanks for the hard work!