Skip to content

Instantly share code, notes, and snippets.

@Saneyan
Created November 16, 2012 09:06
Show Gist options
  • Select an option

  • Save Saneyan/4085688 to your computer and use it in GitHub Desktop.

Select an option

Save Saneyan/4085688 to your computer and use it in GitHub Desktop.
Module Manager (Prototype)
var wic = wic || {};
wic.Module = function(){
var _id
, _detail
, _children = {};
/*
* @param object destination
* @param object source
* @return object
*/
var _extend = function( destination, source ){
for( var key in source )
destination[ key ] = source[ key ];
return destination;
};
/*
* @param string key
* @param object obj (Must be wic.Module instance)
*/
var _addChild = function( key, obj ){
var child = {
object: obj
, configuration: {
modifiable: true
, deletable: true
, overwritable: true
, attachable: true
, detachable: true
, freezable: true
, setter: null
, getter: null
}
, listeners: {
set: []
, get: []
, del: []
, has: []
, modify: []
, trigger: []
, number: 0
}
, statuses: {
modified: false
, overwritten: false
, attached: false
, detached: false
, frozen: false
}
};
_children[ key ] = child;
};
var _getChild = function( target, preventException ){
var child = _children[ target ];
if( child ){
if( child.statuses.frozen === false )
return child;
else if( preventException !== true )
throw "'" + target + "' is frozen";
}
else{
throw "'" + target + "' does not exist in this module";
}
};
/*
* @param string target
* @param object obj
*/
var _overwriteChild = function( target, obj ){
var child = _getChild( target )
, conf = child.configuration;
if( conf.overwritable === true ){
if( conf.setter )
conf.setter.apply( child.object, [ obj ] );
else
child.object = obj;
child.statuses.overwritten = true;
}
else
throw "'" + target + "' cannot be overwritten because of permission";
};
/*
* @param string target
* @return true || false (If specific child exists,
* it'll return true; otherwise return false)
*/
var _hasChild = function( target ){
return !!_children[ target ];
};
var _callListeners = function( type, target ){
var child = _children[ target ]
, listeners = child.listeners[ type ];
for( var i = 0; listeners[ i ]; i++ )
listeners[ i ]();
};
_extend( this, {
set: function(){
if( arguments.length > 0 ){
var obj;
if( arguments.length === 1 ){
obj = arguments[ 0 ];
}
else if( arguments.length === 2 ){
obj = {};
obj[ arguments[ 0 ] ] = arguments[ 1 ];
}
for( var key in obj ){
if( _hasChild( key ) === true ){
_overwriteChild( key, obj[ key ] );
_callListeners( 'set', key );
}
else{
_addChild( key, obj[ key ] );
}
}
}
else{
throw "No arguments assigned";
}
}
, get: function( target ){
var res, child, conf;
if( target == '*' ){
res = {}
for( var key in _children ){
child = _getChild( key, true );
if( !child )
continue;
conf = child.configuration;
if( conf.getter )
res[ key ] = conf.getter.apply( child.object, [] );
else
res[ key ] = child.object;
}
}
else{
child = _getChild( target );
conf = child.configuration;
if( conf.getter )
res = conf.getter.apply( child.object, [] );
else
res = child.object;
_callListeners( 'get', target );
}
return res;
}
, isModifiable: function( target ){
return _getChild( target ).configuration.modifiable;
}
, isDeletable: function( target ){
return _getChild( target ).configuration.deletable;
}
, isOverwritable: function( target ){
return _getChild( target ).configuration.overwritable;
}
, isAttachable: function( target ){
return _getChild( target ).configuration.attachable;
}
, isDetachable: function( target ){
return _getChild( target ).configuration.detachable;
}
, isFreezable: function( target ){
return _getChild( target ).configuration.freezable;
}
, isModified: function( target ){
return _getChild( target ).statuses.modified;
}
, isOverwritten: function( target ){
return _getChild( target ).statuses.overwritten;
}
, isAttached: function( target ){
return _getChild( target ).statuses.attached;
}
, isDetached: function( target ){
return _getChild( target ).statuses.detached;
}
, isFrozen: function( target ){
return _getChild( target ).statuses.frozen;
}
, isset: function( target ){
var res = _hasChild( target );
if( res === true )
_callListeners( 'has', target );
return res;
}
, hasSetter: function( target ){
return !!_getChild( target ).setter;
}
, hasGetter: function( target ){
return !!_getChild( target ).getter;
}
, del: function(){
var child, target;
for( var i = 0; arguments[ i ]; i++ ){
target = arguments[ i ];
child = _getChild( target );
if( child.configuration.deletable === true ){
_callListeners( 'del', target );
delete _children[ target ];
}
else{
throw "'" + target + "' cannot be deleted because of permission";
}
}
}
, modify: function( target, configuration ){
var child = _getChild( target )
, conf = child.configuration;
if( conf.modifiable === true ){
for( var key in configuration ){
if((
key.match( /modifiable|deletable|overwritable|attachable|detachable|freezable/ )
&& typeof configuration[ key ] == 'boolean'
) || (
key.match( /setter|getter/ )
&& typeof configuration[ key ] == 'function' || configuration[ key ] === null
))
conf[ key ] = configuration[ key ];
}
child.statuses.modified = true;
_callListeners( 'modify', target );
}
else{
throw "'" + target + "' cannot be modified because of permission";
}
}
, lock: function(){
var target, conf;
for( var i = 0; arguments[ i ]; i++ ){
target = arguments[ i ];
conf = _getChild( target ).configuration;
if( conf.modifiable === true ){
for( var key in conf ){
if( !key.match( /setter|getter/ ) )
conf[ key ] = false;
}
}
else{
throw "'" + target + "' cannot be modified because of permission";
}
}
}
, trigger: function( target, arg ){
var obj = _getChild( target ).object;
if( typeof obj == 'function' ){
obj.apply( null, arg );
_callListeners( 'trigger', target );
}
else{
throw "'" + target + "' is not function";
}
}
, attach: function( type, target, listener ){
var child = _getChild( target );
if( child.listeners[ type ] ){
if( child.configuration.attachable === true ){
child.listeners[ type ].push( listener );
child.listeners.number++;
child.statuses.attached = true;
}
else{
throw "'" + target + "' cannot be attached a listener because of permission";
}
}
}
, detach: function( type, target, targetListener ){
var listener
, listeners
, child = getChild( target );
if( child.listeners[ type ] ){
if( child.detachable === true ){
listeners = child.listeners[ type ];
for( var i = 0; listeners[ i ]; i++ ){
listener = listeners[ i ];
if( listener === targetListener ){
listeners.splice( i, 1 );
child.listeners.number--;
if( child.listeners.number <= 0 )
child.statuses.detached = true;
}
}
}
else{
throw "'" + target + "' cannot be detached a listener because of permission";
}
}
}
, freeze: function(){
var child, target;
for( var i = 0; arguments[ i ]; i++ ){
target = arguments[ i ];
child = _getChild( target );
if( child.configuration.freezable === true )
child.statuses.frozen = true;
else
throw "'" + target + "' cannot be frozen because of permission";
}
}
});
_extend( this.set, {
detail: function( detail ){
if( _detail === undefined )
_detail = detail;
}
, id: function( id ){
if( _id === undefined )
_id = id;
}
});
_extend( this.get, {
detail: function(){
return _detail;
}
, id: function(){
return _id;
}
});
};
wic.modules = function( Module ){
var _modules = {}
, _paths = {};
var _addModule = function( id, module ){
_modules[ id ] = module;
};
var _require = function( src, success, error ){
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = src;
script.onload = success;
script.onerror = error;
document.getElementsByTagName( 'head' ).item( 0 ).appendChild( script );
};
return {
require: function( target, success, error ){
if( _modules[ target ] ){
return _modules[ target ];
}
else{
var i = 0;
var srcs = typeof target == 'string' ? [ target ] : target;
for( var src, j = 0; srcs[ j ]; j++ ){
src = srcs[ j ];
if( _paths[ src ] )
srcs[ j ] = _paths[ src ];
}
var repeat = function(){
i++;
if( srcs.length > i ){
_require( srcs[ i ], repeat, error );
}
else{
success( wic.modules.require, wic.modules.demand );
}
};
_require( srcs[ i ], repeat, error );
}
}
, demand: function( target ){
if( _modules[ target ] )
return _modules[ target ].get( '*' );
}
, add: function(){
if( arguments[ 0 ] instanceof Module ){
var module = arguments[ 0 ];
_addModule( module.get.id(), module );
}
else{
var id = arguments[ 0 ]
, define = arguments[ 1 ]
, module = new Module();
module.set.id( id );
define.apply( module, [ this.require, this.demand ] );
_addModule( id, module );
}
}
, has: function( target ){
return _modules.hasOwnProperty( target );
}
, configure: function( configuration ){
if( configuration.paths ){
for( var key in configuration.paths )
_paths[ key ] = configuration.paths[ key ];
}
}
};
}( wic.Module );
if( Object.seal ){
Object.seal( wic.modules );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment