components/utils/scripts/elation.js
function(name, container, args, events) {
      /* handling for any default values if args are not specified */
      var mergeDefaults = function(args, defaults) {
        var args = args || {};

        if (typeof defaults == 'object') {
          for (var key in defaults) {
            if (elation.utils.isNull(args[key])) {
              args[key] = defaults[key];
            }
          }
        }
        
        return args;
      };

      var realname = name;
      if (elation.utils.isObject(name)) {
        // Simple syntax just takes an object with all arguments
        args = name;
        realname = elation.utils.any(args.id, args.name, null);
        container = (!elation.utils.isNull(args.container) ? args.container : null);
        events = (!elation.utils.isNull(args.events) ? args.events : null);
      }

      // If no args were passed in, we're probably being used as the base for another 
      // component's prototype, so there's no need to go through full init
      if (elation.utils.isNull(realname) && !container && !args) {
        var obj = new component.base(type);
        
        // apply default args
        obj.args = mergeDefaults(obj.args, elation.utils.clone(obj.defaults));
        
        return obj;
      }

      // If no name was passed, use the current object count as a name instead ("anonymous" components)
      if (elation.utils.isNull(realname) || realname === "") {
        realname = component.objcount;
      }

      if (!component.obj[realname] && !elation.utils.isEmpty(args)) {
        component.obj[realname] = obj = new component.base(type);
        component.objcount++;
      //}
      // TODO - I think combining this logic would let us use components without needing HTML elements for the container
      //if (component.obj[realname] && container !== undefined) {
        component.obj[realname].componentinit(type, realname, container, args, events);

/*
        if (component.extendclass) {
          component.obj[realname].initSuperClass(component.extendclass);
        }
*/
        // fix handling for append component infinite recursion issue
        if (args.append instanceof elation.component.base) 
          args.append = args.append.container;

        if (args.before instanceof elation.component.base) 
          args.before = args.before.container;

        // apply default args
        try {
          if (typeof obj.defaults == 'object')
            args = mergeDefaults(args, elation.utils.clone(obj.defaults));

          var parentclass = component.extendclass;

          // recursively apply inherited defaults
          while (parentclass) {
            if (typeof parentclass.defaults == 'object')
              elation.utils.merge(mergeDefaults(args, elation.utils.clone(parentclass.defaults)),args);

            parentclass = parentclass.extendclass;
          }
        } catch (e) {
          console.log('-!- Error merging component args', e.msg);
        }

        if (typeof obj.init == 'function') {
          obj.init(realname, container, args, events);
        }
      }
      return component.obj[realname];
    }
function(name, container, args, events) {
      /* handling for any default values if args are not specified */
      var mergeDefaults = function(args, defaults) {
        var args = args || {};

        if (typeof defaults == 'object') {
          for (var key in defaults) {
            if (elation.utils.isNull(args[key])) {
              args[key] = defaults[key];
            }
          }
        }
        
        return args;
      };

      var realname = name;
      if (elation.utils.isObject(name)) {
        // Simple syntax just takes an object with all arguments
        args = name;
        realname = elation.utils.any(args.id, args.name, null);
        container = (!elation.utils.isNull(args.container) ? args.container : null);
        events = (!elation.utils.isNull(args.events) ? args.events : null);
      }

      // If no args were passed in, we're probably being used as the base for another 
      // component's prototype, so there's no need to go through full init
      if (elation.utils.isNull(realname) && !container && !args) {
        var obj = new component.base(type);
        
        // apply default args
        obj.args = mergeDefaults(obj.args, elation.utils.clone(obj.defaults));
        
        return obj;
      }

      // If no name was passed, use the current object count as a name instead ("anonymous" components)
      if (elation.utils.isNull(realname) || realname === "") {
        realname = component.objcount;
      }

      if (!component.obj[realname] && !elation.utils.isEmpty(args)) {
        component.obj[realname] = obj = new component.base(type);
        component.objcount++;
      //}
      // TODO - I think combining this logic would let us use components without needing HTML elements for the container
      //if (component.obj[realname] && container !== undefined) {
        component.obj[realname].componentinit(type, realname, container, args, events);

/*
        if (component.extendclass) {
          component.obj[realname].initSuperClass(component.extendclass);
        }
*/
        // fix handling for append component infinite recursion issue
        if (args.append instanceof elation.component.base) 
          args.append = args.append.container;

        if (args.before instanceof elation.component.base) 
          args.before = args.before.container;

        // apply default args
        try {
          if (typeof obj.defaults == 'object')
            args = mergeDefaults(args, elation.utils.clone(obj.defaults));

          var parentclass = component.extendclass;

          // recursively apply inherited defaults
          while (parentclass) {
            if (typeof parentclass.defaults == 'object')
              elation.utils.merge(mergeDefaults(args, elation.utils.clone(parentclass.defaults)),args);

            parentclass = parentclass.extendclass;
          }
        } catch (e) {
          console.log('-!- Error merging component args', e.msg);
        }

        if (typeof obj.init == 'function') {
          obj.init(realname, container, args, events);
        }
      }
      return component.obj[realname];
    }
function ( name , container , args , events ) { /* handling for any default values if args are not specified */ var mergeDefaults = function ( args , defaults ) { var args = args || { } ; if ( typeof defaults == 'object' ) { for ( var key in defaults ) { if ( elation . utils . isNull ( args [ key ] ) ) { args [ key ] = defaults [ key ] ; } } } return args ; } ; var realname = name ; if ( elation . utils . isObject ( name ) ) { // Simple syntax just takes an object with all arguments args = name ; realname = elation . utils . any ( args . id , args . name , null ) ; container = ( ! elation . utils . isNull ( args . container ) ? args . container : null ) ; events = ( ! elation . utils . isNull ( args . events ) ? args . events : null ) ; } // If no args were passed in, we're probably being used as the base for another  // component's prototype, so there's no need to go through full init if ( elation . utils . isNull ( realname ) && ! container && ! args ) { var obj = new component . base ( type ) ; // apply default args obj . args = mergeDefaults ( obj . args , elation . utils . clone ( obj . defaults ) ) ; return obj ; } // If no name was passed, use the current object count as a name instead ("anonymous" components) if ( elation . utils . isNull ( realname ) || realname === "" ) { realname = component . objcount ; } if ( ! component . obj [ realname ] && ! elation . utils . isEmpty ( args ) ) { component . obj [ realname ] = obj = new component . base ( type ) ; component . objcount ++ ; //} // TODO - I think combining this logic would let us use components without needing HTML elements for the container //if (component.obj[realname] && container !== undefined) { component . obj [ realname ] . componentinit ( type , realname , container , args , events ) ; /*
        if (component.extendclass) {
          component.obj[realname].initSuperClass(component.extendclass);
        }
*/ // fix handling for append component infinite recursion issue if ( args . append instanceof elation . component . base ) args . append = args . append . container ; if ( args . before instanceof elation . component . base ) args . before = args . before . container ; // apply default args try { if ( typeof obj . defaults == 'object' ) args = mergeDefaults ( args , elation . utils . clone ( obj . defaults ) ) ; var parentclass = component . extendclass ; // recursively apply inherited defaults while ( parentclass ) { if ( typeof parentclass . defaults == 'object' ) elation . utils . merge ( mergeDefaults ( args , elation . utils . clone ( parentclass . defaults ) ) , args ) ; parentclass = parentclass . extendclass ; } } catch ( e ) { console . log ( '-!- Error merging component args' , e . msg ) ; } if ( typeof obj . init == 'function' ) { obj . init ( realname , container , args , events ) ; } } return component . obj [ realname ] ; }
At the top level, a component is just a function which checks to see if an instance with the given name exists already.  If it doesn't we create it, and then we return a reference to the specified instance.
At the top level a component is just a function which checks to see if an instance with the given name exists already . If it doesn t we create it and then we return a reference to the specified instance .