/*
######################################
apex.js
Universal properties and methods
Components
==========
.core Core services
.ajax AJAX methods
.event Event management
.json JSON "to_string" and "to_object"
.string LTrim, RTrim, Trim, Pad, Chop
######################################
*/
// If the "apex" namespace does not exist, create it
if (typeof apex === 'undefined') { var apex = {}; }
// Create true array from pseudo-array (like "arguments")
function to_array(imposter) {
var ra = [];
for(var i = 0; i < imposter.length; i++) {
ra.push(imposter[i]);
}
return ra;
}
// Create namespace within "apex"
apex.namespace = function() {
var a = to_array(arguments);
var o = null;
for (var i = 0; i < a.length; i++) {
var d = a[i].split(".");
o = apex;
for (var j = (d[0] === 'apex') ? 1 : 0; j < d.length; j++) {
o[d[j]] = o[d[j]] || {};
o = o[d[j]];
}
}
return o;
};
// Known namespaces
apex.namespace('core','ajax','event','json','string');
The function "to_array" returns a true Array object from a pseudo array such as the "arguments" collection that is available to every function. Declaring it at the top of the code makes it available to all of the functions in the library.
/*
######################################
OO Event Listening through Partial
Application in JavaScript, from
http://www.brockman.se/writing/method-references.html.utf8
######################################
*/
(function () {
var destructor = {};
Function.prototype.bind = function(object) {
var method = this;
var oldArguments = to_array(arguments).slice(1);
return function(argument) {
if (argument === destructor) {
method = null;
oldArguments = null;
}
else if (method === null) {
throw 'Attempt to invoke destructed method reference';
}
else {
var newArguments = to_array(arguments);
return method.apply(object, oldArguments.concat(newArguments));
}
};
};
Function.prototype.bindEventListener = function(object) {
var method = this;
var oldArguments = to_array(arguments).slice(1);
return function(event) {
return method.apply(object, [event || window.event].concat(oldArguments));
};
};
})();
This function is added to the prototype chain for Function. It allows us to bind a method to an object. It also lets us bind an event handler to an object. It provides a way to un-bind a method by passing in a new Object ("{}"). Finally, it lets us curry a function, that is, to pass a partial list of parameters to a function.
// ####################################
apex.core = function() {
var site = 'over-engineering';
var PURL = document.location.href;
var URL_BASE = 'http://' + (PURL.indexOf('www.') > 0 ? 'www.' + site + '.com/' : 'localhost/' + site) + '/';
var URL_BROKER = URL_BASE + 'apex/';
var URL_FULL = URL_BASE;
function enclude(file_name, loaded) {
// File prefix and suffix
var pfx = '<script type="text/javascript" src="' + URL_BROKER;
var sfx = '"><\/script>';
// Include the file(s)
for (var i = 0; i < file_name.length; i++) {
if (!loaded) {
document.write(pfx + file_name[i] + sfx);
}
else {
var elem = document.createElement('script');
elem.src = pfx + file_name[i] + sfx;
document.body.appendChild(elem);
}
}
}
function get_node_type(name) {
var node_name = {
'ELEMENT' :'1',
'ATTRIBUTE' :'2',
'TEXT' :'3',
'CDATA_SECTION' :'4',
'ENTITY_REFERENCE' :'5',
'ENTITY' :'6',
'PROCESSING_INSTRUCTION':'7',
'COMMENT' :'8',
'DOCUMENT' :'9',
'DOCUMENT_TYPE' :'10',
'DOCUMENT_FRAGMENT' :'11',
'NOTATION' :'12'
};
return node_name[name.toUpperCase()];
}
function get_node_name(type) {
var node_type = {
'1' :'ELEMENT',
'2' :'ATTRIBUTE',
'3' :'TEXT',
'4' :'CDATA_SECTION',
'5' :'ENTITY_REFERENCE',
'6' :'ENTITY',
'7' :'PROCESSING_INSTRUCTION',
'8' :'COMMENT',
'9' :'DOCUMENT',
'10':'DOCUMENT_TYPE',
'11':'DOCUMENT_FRAGMENT',
'12':'NOTATION'
};
return node_type[type];
}
function get_broker_control() {
return function(){
return {
'async' :false,
'broker_url' :URL_BROKER,
'broker_dir' :'apex/',
'broker_name' :'xs_sys.asp',
'callback_method' :null,
'callback_parms' :null,
'proc_name' :'',
'notify_window' :null,
'alert_interval' :1000,
'content_type' :'application/x-www-form-urlencoded',
'header' :[],
'mode' :'' /* Set to 'plain_text' for non-JSON requests */
};
}();
}
function get_elements_by_className(arg) {
// Expects
//
// arg.node Location of the elements (default is "document)
// arg.tag = Tagname (default is "*")
//
// Returns
// arg.result Array of objects
arg.node = arg.node || document;
arg.tag = arg.tag || '*';
arg.result = [];
//
var el = arg.node.getElementsByTagName(arg.tag);
var pattern = new RegExp('(^|\\s)' + arg.clas + '(\\s|$)');
//
for (var i = 0; i < el.length; i++) {
if (pattern.test(el[i].className)) {
arg.result.push({'type':el[i].tagName, 'id':el[i].id});
}
}
return arg;
}
function tcelfer(obj) {
// Expects
//
// obj JSON object
obj = obj || apex.core;
var ra = [];
if ((obj.length) || 0 > 0) {
for (var j = 0; j < obj.length; j++) {
ra.push(tcelfer(obj[j]));
}
}
else {
for (var n in obj) {
if (obj.hasOwnProperty(n)) {
ra.push([n, obj[n]]);
}
}
}
return ra;
}
By declaring "apex.core" as a function (or class, if you prefer), we can have private properties and methods and privileged (or public) methods and properties.
// Exposed properties and methods
return {
/*
* ############################
* Internal methods
* ----------------------------
*/
'broker_url' :URL_BROKER,
'region' :site + '.com',
'region_from_db':false, /* get region from db? */
'$' :function(arg) { return document.getElementById(arg); },
'$$' :function(arg) { return get_elements_by_className(arg); },
'$$$' :function(tag) { return document.getElementsByTagName(tag); },
'broker_control':function() { return get_broker_control(); },
'enclude' :function(file_name, mode) { return enclude([file_name], mode); }, /* INCLUDE external file */
'event_control' :function(cat, ele, eve, han) { return get_event_control(cat, ele, eve, han); },
'reflect' :function(arg) { return tcelfer(arg); },
'error_trap' :function(desc, url, line) { return trap_error(desc, url, line); },
'node_type' :function(arg) { return get_node_type(arg); },
'node_name' :function(arg) { return get_node_name(arg); },
//
'empty' :null // dummy object closer
};
}();
"empty" is an indicator that terminates the exposed methods. Since each exposed method is followed by a comma, "empty" is just a convenience, but it prevents me from forgetting to add a comma if I add a new method.
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (0)