I was doing some test about implementing my custom bootstrap and kernel in Javascript and I wanted to load them asynchronously because inside those files, there are other stuff being loaded in runtime. I tried looking for some answers to load the scripts files asynchronously but some of them are using jQuery and some were not useful. I really like like to get away with jQuery with my loader so I made my own using queueing technique just like what I used to do in C# using Queue<T>
Here's the sample loader I made
function loadFile(url, callback) {
var head;
var element;
if (url.indexOf('.css') != -1) {
head = document.getElementsByTagName('head')[0];
element = document.createElement('link');
element.setAttribute('type', 'text/css');
element.setAttribute('href', url);
element.setAttribute('rel', 'stylesheet');
}
else if (url.indexOf('.js') != -1) {
head = document.getElementsByTagName('body')[0];
element = document.createElement('script');
element.setAttribute('type', 'text/javascript');
element.setAttribute('src', url);
}
/*else I'll try to add more here soon*/
/*bind the event to the callback function*/
{
/*http://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/*/
if (script.readyState){ /*IE*/
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { /*Others*/
script.onload = function(){
callback();
};
}
}
/*fire the loading*/
{
head.appendChild(element);
}
}
{ // ENQUEUE / DEQUEUE files for asyncloading
var d = new Date();
// enqueue files
var files = new Array(
"css/jquery.metro.css",
"css/common2.css",
"scripts/appmanifest.js",
"scripts/kernel.js",
"scripts/bootstrap.js"
);
// dequeue
var ready = false;
var callback = function () {
// file is now loaded
// call LoadFiles() again for dequeueing
LoadFiles();
};
function LoadFiles() {
if (files.length != 0) {
// load file and add time so browser thinks
// we are loading a different file
// in other words, I hate caching them while debugging
var file = files[0] + '?t=' + d.getTime();
// load the file
loadFile(file, callback);
// dequeue the file
files.splice(0, 1);
}
else {
ready = true;
}
}
}
In my code above, if you notice, the function tries to insert CSS on HEAD and Javascript on BODY so why is that? It's been a practice that whenever we load a script file in our web pages, we have to put them inside the HEAD to make sure our script variables, functions, etc are defined first. I have no problem with that, if you want to use my loader script, and insert the script in head, then that's fine. Though I haven't answered the question why would I like to insert the script in the BODY? The reason is very simple, I want to make sure every element written manually or inserted dynamically exists first before doing any changes at the elements at runtime.
you can also use Push() and Shift() in in Javascript like this one
{ // ENQUEUE / DEQUEUE files for asyncloading
var d = new Date();
// enqueue files
var queue = [];
queue.push("css/jquery.metro.css");
queue.push("css/common2.css");
queue.push("scripts/appmanifest.js");
queue.push("scripts/kernel.js");
queue.push("scripts/bootstrap.js");
// dequeue
var ready = false;
var callback = function () {
// file is now loaded
// call LoadFiles() again for dequeueing
LoadFiles();
};
function LoadFiles() {
if (queue.length != 0) {
// load file and add time so browser thinks
// we are loading a different file
// in other words, I hate caching them while debugging
var f = queue.shift(); // dequeue
var file = f + '?t=' + d.getTime();
// load the file
loadFile(file, callback);
}
else {
ready = true;
}
}
}
So why would I create a new bootstrap instead of using the one the was already made? The reason of that is because I really don't need everything on those offered bootstrap and loading the unnecessary libraries will just cause another webpage slowdown. My bootstrap is pretty simple, and it loads just the necessary libraries that I need which is defined in my appmanifest.js. So what on earth is appmenifest.js? App Manifest was just a small implementation of what was originally used in Siverlight, Windows Phone, and in Windows 8. Here, you can add the deployment details or any other information you need in your application.
Here's what my appmanifest.js looks like
/*
CAPABILITIES
------------
CAP_METROPIVOT
CAP_KNOCKOUT
*/
var Capabilities = [];
/*Capabilities.push("CAP_KNOCKOUT");*/
Capabilities.push("CAP_METROPIVOT");
var LayoutFiles = [];
LayoutFiles.push("scripts/View/Layout.js");
var MVVMFiles = [];
MVVMFiles.push("scripts/ViewModel/CommonViewModel.js");
and finally my bootstrap.js
/*
bootstrap.js
written by: Jayson Ragasa
*/
var d = new Date();
{ // async load required libraries
var required_libs = [];
required_libs.push('scripts/Libraries/jquery-1.7.1.min.js');
// load capabilities
for (var i = 0; i < Capabilities.length; i++) {
var cap = Capabilities[i];
if (cap == "CAP_METROPIVOT") {
required_libs.push('scripts/Libraries/Capabilities/jquery.metro.js');
required_libs.push('scripts/Libraries/Capabilities/jquery.metro.extension.js');
}
else if (cap == "CAP_KNOCKOUT") {
required_libs.push('scripts/Libraries/Capabilities/knockout.min.js');
}
}
function callback_library_loaded(a) {
LoadLibrary();
}
function LoadLibrary() {
//alert(required_libs.length);
if (required_libs.length != 0) {
var lib = required_libs.shift();
var f = lib + '?t=' + d.getTime() + '&ref=bootstrap';
loadScript(f,
function () {
callback_library_loaded(lib);
}
);
}
else {
LibrariesLoaded();
}
}
// call once;
LoadLibrary();
}
function LibrariesLoaded() {
required_libs.length = 0;
{ // add script files for layout
// render layout
for (var i = 0; i < LayoutFiles.length; i++) {
var f = LayoutFiles[i];
//loadScript(f, function () { });
required_libs.push(f);
}
// load MVVM files
for (var i = 0; i < MVVMFiles.length; i++) {
var f = MVVMFiles[i];
required_libs.push(f);
}
RenderLayout();
}
}
// load layout files and mvvm files
function callback_renderfiles_loaded(a) {
RenderLayout();
}
function RenderLayout() {
if (required_libs.length != 0) {
var lib = required_libs.shift();
var f = lib + '?t=' + d.getTime() + '&ref=bootstrap.renderfiles';
loadScript(f,
function () {
callback_renderfiles_loaded(lib);
}
);
}
else {
}
}
so simple isn't it? But I am hoping my custom bootstrap.js can go further as well as my kernel.js? Why on earth do I need kernel.js? I believe here in kernel.js, I can put all the necessary functions needed for my web application development.
Here's where I implemented the whole thing C.app.loud development