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