Last active
February 12, 2025 16:29
-
-
Save ptejada/2269151 to your computer and use it in GitHub Desktop.
JSmodule is a simple JavaScript object for stacking data and hookable functions as methods.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A JavaScript module constructor | |
* | |
* Methods | |
* - get( name ) get the value the named internal variable | |
* - set( name , value ) set named internal variable a value | |
* - extend( methodName , function ) add a method to the module | |
* | |
* @param ModuleID | |
* @returns {Function} | |
* @constructor | |
*/ | |
function JSmodule(ModuleID){ | |
//save scope | |
var scope = this; | |
//debug function | |
function log(data, extra){ | |
if(!options.debug) return {}; | |
if(!!extra){ | |
console.log("["+options.app+"] >> ",data, extra); | |
}else{ | |
console.log("["+options.app+"] >> ",data); | |
} | |
return this; | |
} | |
/* | |
* Object constructor | |
*/ | |
function constructor(methodOrOptions, /**Array=*/args){ | |
if(methods[methodOrOptions]){ | |
//execute function before method || Cancel execution if returned false | |
if(constructor.runBeforeCallbacks(methodOrOptions, args) === false) return false; | |
//Execute method | |
var returnVal = methods[ methodOrOptions ].apply( this, args); | |
//Smart return value | |
if(typeof returnVal != 'undefined') | |
return returnVal; | |
return this; | |
} else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) { | |
// Default to "init" | |
if(constructor.runBeforeCallbacks("init", methodOrOptions) === false); | |
return methods.init.apply( this, arguments ); | |
} else { | |
throw new Error('['+options.app+'] >> Method `' + methodOrOptions + '` does not exists' ); | |
} | |
}; | |
//Global hidden options | |
var options = {}; | |
//Global hidden callbacks | |
var callbacks = {}; | |
//Global hidden data | |
var data = {}; | |
//Default methods | |
var methods = { | |
init: function(newOptions, callback){ | |
if(newOptions && typeof(newOptions) == 'object'){ | |
options = MergeObject( options, newOptions ); | |
} | |
if(typeof callback == 'function'){ | |
callback.apply(this, [newOptions]); | |
} | |
//Call callbacks | |
constructor.runAfterCallbacks("init", newOptions); | |
} | |
} | |
//Private functions | |
function applyCallback(name, args){ | |
if(typeof args == 'undefined'){ | |
args = []; | |
} | |
//exit if no callback | |
if(!callbacks[name]){ | |
log("No [" + name + "] callbacks"); | |
}else{ | |
log("Running ["+name+"] callback stack with arguments: ", args); | |
var cont; | |
//Apply function | |
for(var i in callbacks[name]){ | |
cont = callbacks[name][i].apply(this,args); | |
log("Callback "+name+"["+i+"]() returned: ", cont); | |
if(cont === false) return false; //Return false to cancel further execution when running afterCallback | |
} | |
} | |
return true; | |
} | |
//Add debugging function to constructor | |
constructor.log = log; | |
/** | |
* Adds a callback function to the given stack | |
* @param name | |
* @param callback | |
*/ | |
constructor.addCallback = function(name, callback){ | |
if(!callbacks[name]) | |
callbacks[name] = []; | |
callbacks[name].push(callback); | |
} | |
/** | |
* Adds a after callback function to the given stack | |
* | |
* @param name The name of the stack | |
* @param callback The callback function | |
*/ | |
constructor.addAfterCallback = function( name, callback){ | |
constructor.addCallback( name + ".after", callback) | |
} | |
/** | |
* Adds a before callback function to the given stack | |
* | |
* @param name The name of the stack | |
* @param callback The callback function | |
*/ | |
constructor.addBeforeCallback = function( name, callback){ | |
constructor.addCallback( name + ".before", callback) | |
} | |
/** | |
* Deletes callback stack | |
* | |
* @param name The name of the stack | |
*/ | |
constructor.removeCallback = function( name ){ | |
log("Clearing ["+name+"] callbacks"); | |
if(name in callbacks){ | |
delete callbacks[name]; | |
} | |
} | |
/** | |
* Execute the before callback stack passing the given arguments | |
* | |
* @param name The name of the stack to run the callbacks | |
* @param args The arguments to pass to each function | |
* @returns {*} | |
*/ | |
constructor.runBeforeCallbacks = function( name, /**Array=*/args ){ | |
if(typeof args == 'undefined'){ | |
args = []; | |
} | |
name = name + ".before"; | |
return applyCallback.call(this, name, args); | |
} | |
/** | |
* Execute the after callback stack passing the given arguments | |
* | |
* @param name The name of the stack to run the callbacks | |
* @param args The arguments to pass to each function | |
* @returns {*} | |
*/ | |
constructor.runAfterCallbacks = function( name, /**Array=*/args ){ | |
if(typeof args == 'undefined'){ | |
args = []; | |
} | |
name = name + ".after"; | |
return applyCallback.call(this, name, args); | |
} | |
/** | |
* Execute a stack of functions passing the given arguments | |
* | |
* @param name The name of the callback stack | |
* @returns {*} | |
*/ | |
constructor.runCallbacks = function(){ | |
return applyCallback.apply(this, arguments); | |
} | |
/** | |
* Adds a method to the module | |
* @param name The method name | |
* @param func The method function | |
*/ | |
constructor.extend = function(name, func){ | |
if(typeof name == 'object'){ | |
methods = MergeObject( methods, name ); | |
}else{ | |
methods[name] = func; | |
} | |
} | |
/** | |
* Gets value of a stored variable | |
* | |
* @param name The name of the stored variable | |
* @returns {*} | |
*/ | |
constructor.get = function( name ){ | |
if(name in data){ | |
return data[name]; | |
}else{ | |
return null; | |
} | |
} | |
/** | |
* Stores a value in the module | |
* | |
* @param name The variable name to hold the value | |
* @param value The value to store in the variable | |
*/ | |
constructor.set = function(name, value){ | |
data[name] = value; | |
} | |
/** | |
* Get an internal option | |
* | |
* @param name The name of the internal option | |
* @returns {*} | |
*/ | |
constructor.getOption = function( name ){ | |
if(name in options){ | |
return options[name] | |
}else{ | |
return null | |
} | |
} | |
/** | |
* Set an internal option | |
* | |
* @param name The name of the option | |
* @param value The value to set the option | |
* @returns {*} | |
*/ | |
constructor.setOption = function( name, value ){ | |
return options[name] = value; | |
} | |
//Default options | |
options = { | |
app: ModuleID || "Obj", | |
debug: false | |
} | |
/* | |
* Required object merger function | |
*/ | |
function MergeObject(obj1, obj2, callback){ | |
var obj3 = {}; | |
for(var i in obj1){ | |
obj3[i] = obj1[i]; | |
} | |
for(var n in obj2){ | |
obj3[n] = obj2[n]; | |
} | |
if(typeof callback == 'function') | |
callback(); | |
return obj3; | |
} | |
return constructor; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment