extender – Object  [ 876 views ]

Goal: give some additional function to the Object type

available extends:

  • objectId: global unique identifier for every DOM and non DOM object
  • _bind, _unbind, _trigger: bind logic for every DOM and non DOM object
  • _trace, _watch: easy setable trace and watch functionality
  • _catch (SET catching): bind a function to the variable setter
  • _chain: to investigate the call chains with arguments

The code itself:

(function() {  // unique ID

/* usage
 read from plain javascript: var id = obj.objectId;
           read from jquery: var id = $(this)[0].objectId;
*/

  __Object_oIdcnt = 1;
  Object.defineProperty(Object.prototype, "__oId", { writable: true });
  Object.defineProperty(Object.prototype, "objectId", {
    get: function() {
      !this.__oId && (this.__oId = __Object_oIdcnt++);
      return this.__oId;
    }
  });
}());

(function() { // _bind, _trigger capability

/* usage
  var f = {}; // new Object();
  f._bind('evt1.nspc', function(){console.log('first one');});
  f._bind('evt2.nspc', function(){console.log('second one');});
  f._bind('evt1.nspc2', function(){console.log('third one');});
  f._trigger('evt1');
  f._trigger('evt2');
  f._unbind('.nspc');
  f._trigger('evt1');
  f._trigger('evt2');
*/

  Object.defineProperty(Object.prototype, "__bound", { writable: true });
  Object.defineProperty(Object.prototype, "bound", {
    get: function() {
      this.__bound = this.__bound || [];
      return this.__bound;
    }
  });  

  TypeExtend(Object, '_bind', function(evt, func) { 
    var evts = evt.split('.'),
        obj = {namespace: (evts[1] && evts[1]), event: evts[0], f:func};
    this.bound.push(obj);
    return this;
  });

  TypeExtend(Object, '_unbind', function(evt) { 
    if(!this.__bound){return false;}
    if(!evt){
      this.__bound = [];
      delete this.__bound;
    }
    else{
      var evts = evt.split('.');
      for(var i in this.__bound){
        if((evts[1] && this.__bound[i].namespace == evts[1])
            || this.__bound[i].event == evts[0]){
          delete this.__bound[i];
        }
      }
    }
    this.__bound.shrink(); // drop all undefined  items    
    return this;
  });

  TypeExtend(Object, '_trigger', function(evt) { 
    if(!this.__bound){return false;}
    for(var i in this.__bound){
      if(this.__bound[i].event == evt){
        var a = arguments;
        this.__bound[i].f && (this.__bound[i].f)(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[8],a[10]);
      }
    }
    return this;
  });

}());
  
(function() {  // _trace, _watch, _catch capability

/* usage
  1. simple trace and watch
    this._trace('myFunctionName'); ... or ... _trace.call(this, 'myFunctionName');
    this._watch('myVariableName'); ... or ... _watch.call(this, 'myVariableName');
  2. function bind on variable set
    this._catch('myVariableName', function(){...}); ... or ... _catch.call(this, 'myVariableName', function(){...});
*/

var _trace_level = 1;

  TypeExtend(Object, '_trace', function(funcName, useChain) { 
  
    if(typeof(this[funcName]) != 'function'){_watch.call(this, funcName); return false;}
  
    if(this['__' + funcName]){return false;}
    this['__' + funcName] = this[funcName];
    
    this[funcName] = function(){
      var a = arguments, _tl = _trace_level;
    
      arguments.callee.caller.toString() && _trace_level++;
    
      var aa = '', aar = [];
      for(var ar in a){ a[ar] && aar.push(a[ar].toString()); }
      aa = aar.join(',');
    
      if(useChain){
        if(_tl < _trace_level){ console.group(funcName + ' (' + aa + ')'); }
        else{ console.log(funcName + ' (' + aa + ')'); }
      }
      else{
        console.traceEx('_trace: ' + ' '.repeat(_trace_level) + funcName, 'background: rgba(207, 181, 42, 0.6); color: #000;', arguments);
      }
      var ret = this['__' + funcName](a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[8],a[10]);
      
      if(_tl < _trace_level){ console.groupEnd(); }
      _trace_level = _tl;
      
      return ret;
    };
    !useChain && console.info('_trace applied to ' + funcName);
    return true;
  });
  
  _trace = function(fn){ this._trace(fn); }; 
  
  TypeExtend(Object, '_watch', function(varName, binder) { 
  
    if(this['__' + varName]){console.error('unable to apply _watch for ' + varName); return false;}
    this['__' + varName] = this[varName];

    Object.defineProperty(this, varName, {
      get: function() {
        !binder && console.traceEx('_watch GET: ' + varName, 'background: rgba(97, 243, 126, 0.6); color: #000;');
        return this['__' + varName];
      },
      set: function(val) {
        !binder && console.traceEx('_watch SET: ' + varName + '--> value:' + val, 'background: rgba(243, 151, 151, 0.6); color: #000;');
        this['__' + varName] != val && (this._trigger('__set_' + varName, this['__' + varName], val), this['__' + varName] = val);
        return this;
      }      
    });
    
    if(binder){ // ezt meg rákötöm figyelésnek
      this._bind('__set_' + varName, binder);
      console.info('_catch applied to ' + varName);
    }
    else{
      console.info('_watch applied to ' + varName);
    }
    return true;
  });
  
  TypeExtend(Object, '_catch', function(varName, binder) { 
    return this._watch(varName, binder);
  });  
  
  _watch = function(vn, binder){ this._watch(vn, binder); };  
  _catch = function(vn, binder){ this._watch(vn, binder); };  
  
}());

(function() {  // _chain

/* usage
  1. I have only a simple way to do this
    this._chain();
*/

  TypeExtend(Object, '_chain', function() { 

    for(var i in this){
      if(typeof this[i] === "function") {
        this._trace(i, true);
      }
    }
    console.obj('_chain applied to', this);

  });

}());

see also: extend the console, javascript extender (TypeExtend), extender – Array

#sidebar a { color:#fff; } #sidebar ul ul li { color: #DEF585; } #sidebar h2 { color: #fff; } #sidebar ul p, #sidebar ul select { color: #BEDDBE; } #backfly { background: url(images/golfBallWallPaper.jpg) left bottom fixed repeat-x #65a51d; }