I've built a small library that I use to boot or start a web application. The library code has been posted below, as well an example of application code. I'm looking for ways to make the code more concise or "tighter".
If there's anything I can do to make the comments better, let me know.
Library Code
/*******************************************************************************
**BOOTER
** manageGlobal - manages the single global variable that BOOT uses
** validateBrowser - validates the browser and version type
** configureFrame - passes a user defined function to config_boot which will
** configure the booter
** setResources - appends a user defined object to config_boot*
** bootResources - boots or starts the application, checks validation and
** calls the user defined function, then calls checkStorageAndBoot
** checkStorageAndBoot - checks storage and loops through the tokens loading
** as needed.
** parseResourceToken - parses the resource object, calls ajax, and adds
** elements as needed
** addElement - adds a resource element based on type ( htm, css, js, txt,
** etc. )
** addElementText - adds a txt file which may contain any kind of
** static text
*******************************************************************************/
(function () {
"use strict";
var $A,
$P = {},
$R = {};
// holds boot configuration info -> encapsulate this some where else.
$R.config_boot = {};
// requires utility, comms, and dom
// resources are loaded to the dom and their status is
// communicated to other packages
(function manageGlobal() {
if (window.$A && window.$A.pack && window.$A.pack.utility &&
window.$A.pack.comms && window.$A.pack.dom) {
$A = window.$A;
$A.pack.booter = true;
} else {
throw "booter requires utility, dom, and comms module";
}
}());
// only working with modern browsers
$P.validateBrowser = function (obj) {
var name = 'unknown',
browser_version = 'unknown',
element,
temp;
$A.Reg.set('browser_type', null);
$A.Reg.set('browser_validated', null);
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
$A.Reg.set('browser_type', 'ie');
name = 'Internet Explorer';
browser_version = parseFloat(RegExp.1ドル);
if (browser_version >= obj.In) {
$A.Reg.set('browser_validated', true);
return;
}
} else if (/Chrome[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {
$A.Reg.set('browser_type', 'ch');
name = 'Chrome';
browser_version = parseFloat(RegExp.1ドル);
if (browser_version >= obj.Ch) {
$A.Reg.set('browser_validated', true);
return;
}
} else if (/Safari/.test(navigator.userAgent)) {
$A.Reg.set('browser_type', 'sa');
/Version[\/\s](\d+\.\d+)/.test(navigator.userAgent);
name = 'Safari';
browser_version = parseFloat(RegExp.1ドル);
if (browser_version >= obj.Sa) {
$A.Reg.set('browser_validated', true);
return;
}
} else if (navigator.userAgent.match(/Firefox[\/\s](\d+\.\d+)/)) {
$A.Reg.set('browser_type', 'ff');
temp = navigator.userAgent.match(/Firefox[\/\s](\d+\.\d+)/);
name = 'Firefox';
browser_version = parseFloat(temp[1]);
if (browser_version >= obj.Fi) {
$A.Reg.set('browser_validated', true);
return;
}
}
if (!name) {
name = 'X';
}
if (!browser_version) {
browser_version = 'y';
}
element = document.getElementById('browser_validation');
element.innerHTML += " You are running " + name +
" " + browser_version + ".";
element.style.display = 'block';
$A.Reg.set('browser_validated', false);
$A.Reg.set('browser_element', element);
};
// things the framework needs to get ( server paths, server variables, etc. )
// and to set ( events, client variables, etc )
$P.configureFrame = function (func) {
$R.config_boot.func = func;
};
// sets version and resoures to load
$P.setResources = function (obj) {
$R.config_boot = $A.extend($R.config_boot, obj);
};
$P.bootResources = function (skip_validation) {
var validated = $A.Reg.get('browser_validated'),
element;
if (!skip_validation && !validated) {
return;
}
if (!validated) {
// we are skipping validation, remove the validation message
element = $A.Reg.get('browser_element');
element.style.display = 'none';
}
// run the configuration function
if ($R.config_boot.func) {
$R.config_boot.func();
}
// checkStorage for previous resources saved in storage and then boot
$R.checkStorageAndBoot();
};
$R.checkStorageAndBoot = function () {
var kindex,
length;
if (localStorage.file_version && localStorage.file_version >=
$R.config_boot.file_version) {
$R.config_boot.cached = true;
} else {
localStorage.file_version = $R.config_boot.file_version;
$R.config_boot.cached = false;
}
for (kindex = 0, length = $R.config_boot.resources.length;
kindex < length; kindex += 1) {
$R.parseResourceToken($R.config_boot.resources[kindex], null);
}
};
$R.parseResourceToken = function (source, callback) {
var matches,
prefix,
file_token;
// START (/ or //) () / () (.) () END
matches = source.match(/^(\/\/|\/)?([\w\/\.]*)\/([\w\.]+)(\.)([\w]+)$/);
if (matches) {
prefix = matches[1];
file_token = 'file_' + matches[3] + '_' + matches[5];
source = source + '?_time=' + new Date().getTime();
}
if ($R.config_boot.cached) {
$R.addElement(file_token, callback, localStorage[file_token]);
return;
}
// relative to directory || relative to root
if (prefix === undefined || prefix === '/') {
$A.serialAjax(source, function (response_text) {
$R.addElement(file_token, callback, response_text);
localStorage[file_token] = response_text;
});
return;
}
// not implemented yet
if (prefix === '//') {
return;
}
};
$R.addElement = function (file_token, callback, response_text, source) {
var file_type = file_token.match(/file_[\x20-\x7E]+_([\x20-x7E]+)$/)[1],
element;
if (file_type === 'txt') {
$R.addElementText(callback, response_text);
return;
}
if (file_type === 'htm') {
element = document.createElement("div");
element.id = file_token;
if (!source) {
element.innerHTML = response_text;
document.body.appendChild(element);
if (callback) {
callback();
}
$A.Event.trigger(file_token);
}
return;
}
if (file_type === 'js') {
element = document.createElement('script');
element.id = file_token;
if (!source) {
element.innerHTML = response_text;
document.head.appendChild(element);
if (callback) {
callback();
}
} else {
element.onload = callback;
element.async = true;
element.src = source;
document.head.appendChild(element);
}
$A.Event.trigger(file_token);
return;
}
if (file_type === 'css') {
if (!source) {
element = document.createElement('style');
element.id = file_token;
element.innerHTML = response_text;
document.head.appendChild(element);
if (callback) {
callback();
}
} else {
element = document.createElement("link");
element.onload = callback;
element.id = file_token;
element.rel = "stylesheet";
element.type = "text/css";
element.href = source;
document.head.appendChild(element);
}
$A.Event.trigger(file_token);
return;
}
if (file_type === 'ico') {
element = document.createElement("link");
element.onload = callback;
element.id = file_token;
element.rel = "icon";
if (!source) {
element.href = response_text;
} else {
element.href = source;
}
document.head.appendChild(element);
$A.Event.trigger(file_token);
return;
}
if (file_type === 'png') {
element = document.getElementById(file_token);
element.onload = callback;
element.id = file_token;
element.src = response_text;
$A.Event.trigger(file_token);
return;
}
};
$R.addElementText = function (callback, response_text) {
var regex,
token_content,
subtoken,
subtoken_text,
name,
name_is_variable,
index,
length;
regex = /\/\*<\|([\x20-\x7E]+)(_[\x20-\x7E]+)\|>\*\//g;
token_content = response_text.split(regex);
length = token_content.length;
for (index = 1; index < length; index += 3) {
subtoken = 'file_' + token_content[index] +
token_content[index + 1];
subtoken_text = token_content[index + 2];
name = token_content[index];
// handles variable based statics
name_is_variable = name.match(/\{([\x20-\x7E]*)\}/);
if (name_is_variable) {
if (name_is_variable[1] === $A.Reg.get('browser_type')) {
$R.addElement(subtoken, callback, subtoken_text);
}
// straight statics
} else {
$R.addElement(subtoken, callback, subtoken_text);
}
}
};
window.$A = $A.extendSafe($A, $P);
}());
Application Code
/*******************************************************************************
**BOOT
*******************************************************************************/
/*jslint
browser: true,
forin: true,
plusplus: true,
eqeq: true,
*/
/*global
$A,
$
*/
(function () {
"use strict";
var debug = true;
function libHasLoaded() {
// ( 1 ) Validate browser by type and version number ( filter out older browsers )
$A.validateBrowser({
In: 10,
Fi: 14,
Sa: 5,
Ch: 18
});
// ( 2 ) Configure the framework
$A.configureFrame(function () {
// add FRAME events
$A.Event.add('file_arcmarks_js', function () {
$A.getDomElements('E');
$A.initByProperty('init');
});
$A.Event.add('file_jqueryui_js', function () {
$A.getLibElements('J', $);
$A.initByProperty('initJ');
});
// add FRAME variables
$A.Reg.setMany($A.getData('universals'));
$A.Reg.setMany({
path_ajax: 'arcmarks/source/class.CMachine.php',
path_pictures: 'arcmarks/pictures/',
path_images: 'arcmarks/images/'
});
});
if (debug) {
$A.setResources({
file_version: Date.now(),
resources:
[
'arcmarks/source/arcmarks.txt',
'arcmarks/source/arcmarks.htm',
'arcmarks/source/arcmarks.js',
'arcmarks/source/arc_large.txt'
]
});
} else {
$A.setResources({
file_version: 5,
resources:
[
'arcmarks/source/arcmarks.txt',
'arcmarks/source/arcmarks.htm',
'arcmarks/source/arcmarks.js',
'arcmarks/source/arc_large.txt'
]
});
}
// ( 3 ) Boot or start the application
$A.bootResources();
}
var script_el = document.createElement('script');
script_el.src = 'arcmarks/source/arc.js';
document.head.appendChild(script_el);
script_el.onload = function () {
libHasLoaded();
};
}());
1 Answer 1
From a once over:
This
if (!name) {
name = 'X';
}
can be changed by using a fairly common logic trick:
name = name || 'X';
This could be simplified, mostly using some sugar:
$R.checkStorageAndBoot = function () {
var kindex,
length;
if (localStorage.file_version && localStorage.file_version >=
$R.config_boot.file_version) {
$R.config_boot.cached = true;
} else {
localStorage.file_version = $R.config_boot.file_version;
$R.config_boot.cached = false;
}
for (kindex = 0, length = $R.config_boot.resources.length;
kindex < length; kindex += 1) {
$R.parseResourceToken($R.config_boot.resources[kindex], null);
}
};
could be
$R.checkStorageAndBoot = function () {
var i, //Going Spartan for a simple for loop is more readable
length,
fs = localStorage, //localStorage is so wordy
config = $R.config_boot; //So is $R.config_boot
//No need to first check for fs.file_version
config.cached = (fs.file_version >= config.file_version);
fs.file_version = config.file_version;
for (i = 0, length = config.resources.length; i < length; i++) {
$R.parseResourceToken($R.config_boot.resources[kindex], null);
}
};
$R.addElement
should be split into smaller functions, this would probably prevent the multiple$A.Event.trigger(file_token);
statements.The use of underscores is still not right, I understand this is your naming standard, that does not make it less wrong.
Still, the code looks solid and should be a good base to build apps with.