{"id":209,"date":"2014-05-31T22:52:03","date_gmt":"2014-05-31T22:52:03","guid":{"rendered":"http:\/\/localhost\/__sites\/3d_blog\/?p=209"},"modified":"2022-05-24T19:43:05","modified_gmt":"2022-05-24T19:43:05","slug":"extender-object","status":"publish","type":"post","link":"https:\/\/blog.silverterra.net\/?p=209","title":{"rendered":"extender &#8211; Object"},"content":{"rendered":"<blockquote><p>Goal: give some additional function to the Object type<\/p><\/blockquote>\n<p>available extends:<\/p>\n<ul>\n<li><strong>objectId:<\/strong> global unique identifier for every DOM and non DOM object<\/li>\n<li><strong>_bind, _unbind, _trigger:<\/strong> bind logic for every DOM and non DOM object<\/li>\n<li><strong>_trace, _watch:<\/strong> easy setable trace and watch functionality<\/li>\n<li><strong>_catch (SET catching):<\/strong> bind a function to the variable setter<\/li>\n<li><strong>_chain:<\/strong> to investigate the call chains with arguments<\/li>\n<\/ul>\n<p>The code itself:<\/p>\n<pre data-enlighter-language=\"js\" class=\"EnlighterJSRAW\">\r\n(function() {  \/\/ unique ID\r\n\r\n\/* usage\r\n read from plain javascript: var id = obj.objectId;\r\n           read from jquery: var id = $(this)[0].objectId;\r\n*\/\r\n\r\n  __Object_oIdcnt = 1;\r\n  Object.defineProperty(Object.prototype, &quot;__oId&quot;, { writable: true });\r\n  Object.defineProperty(Object.prototype, &quot;objectId&quot;, {\r\n    get: function() {\r\n      !this.__oId &amp;&amp; (this.__oId = __Object_oIdcnt++);\r\n      return this.__oId;\r\n    }\r\n  });\r\n}());\r\n\r\n(function() { \/\/ _bind, _trigger capability\r\n\r\n\/* usage\r\n  var f = {}; \/\/ new Object();\r\n  f._bind('evt1.nspc', function(){console.log('first one');});\r\n  f._bind('evt2.nspc', function(){console.log('second one');});\r\n  f._bind('evt1.nspc2', function(){console.log('third one');});\r\n  f._trigger('evt1');\r\n  f._trigger('evt2');\r\n  f._unbind('.nspc');\r\n  f._trigger('evt1');\r\n  f._trigger('evt2');\r\n*\/\r\n\r\n  Object.defineProperty(Object.prototype, &quot;__bound&quot;, { writable: true });\r\n  Object.defineProperty(Object.prototype, &quot;bound&quot;, {\r\n    get: function() {\r\n      this.__bound = this.__bound || [];\r\n      return this.__bound;\r\n    }\r\n  });  \r\n\r\n  TypeExtend(Object, '_bind', function(evt, func) { \r\n    var evts = evt.split('.'),\r\n        obj = {namespace: (evts[1] &amp;&amp; evts[1]), event: evts[0], f:func};\r\n    this.bound.push(obj);\r\n    return this;\r\n  });\r\n\r\n  TypeExtend(Object, '_unbind', function(evt) { \r\n    if(!this.__bound){return false;}\r\n    if(!evt){\r\n      this.__bound = [];\r\n      delete this.__bound;\r\n    }\r\n    else{\r\n      var evts = evt.split('.');\r\n      for(var i in this.__bound){\r\n        if((evts[1] &amp;&amp; this.__bound[i].namespace == evts[1])\r\n            || this.__bound[i].event == evts[0]){\r\n          delete this.__bound[i];\r\n        }\r\n      }\r\n    }\r\n    this.__bound.shrink(); \/\/ drop all undefined  items    \r\n    return this;\r\n  });\r\n\r\n  TypeExtend(Object, '_trigger', function(evt) { \r\n    if(!this.__bound){return false;}\r\n    for(var i in this.__bound){\r\n      if(this.__bound[i].event == evt){\r\n        var a = arguments;\r\n        this.__bound[i].f &amp;&amp; (this.__bound[i].f)(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[8],a[10]);\r\n      }\r\n    }\r\n    return this;\r\n  });\r\n\r\n}());\r\n  \r\n(function() {  \/\/ _trace, _watch, _catch capability\r\n\r\n\/* usage\r\n  1. simple trace and watch\r\n    this._trace('myFunctionName'); ... or ... _trace.call(this, 'myFunctionName');\r\n    this._watch('myVariableName'); ... or ... _watch.call(this, 'myVariableName');\r\n  2. function bind on variable set\r\n    this._catch('myVariableName', function(){...}); ... or ... _catch.call(this, 'myVariableName', function(){...});\r\n*\/\r\n\r\nvar _trace_level = 1;\r\n\r\n  TypeExtend(Object, '_trace', function(funcName, useChain) { \r\n  \r\n    if(typeof(this[funcName]) != 'function'){_watch.call(this, funcName); return false;}\r\n  \r\n    if(this['__' + funcName]){return false;}\r\n    this['__' + funcName] = this[funcName];\r\n    \r\n    this[funcName] = function(){\r\n      var a = arguments, _tl = _trace_level;\r\n    \r\n      arguments.callee.caller.toString() &amp;&amp; _trace_level++;\r\n    \r\n      var aa = '', aar = [];\r\n      for(var ar in a){ a[ar] &amp;&amp; aar.push(a[ar].toString()); }\r\n      aa = aar.join(',');\r\n    \r\n      if(useChain){\r\n        if(_tl &lt; _trace_level){ console.group(funcName + ' (' + aa + ')'); }\r\n        else{ console.log(funcName + ' (' + aa + ')'); }\r\n      }\r\n      else{\r\n        console.traceEx('_trace: ' + ' '.repeat(_trace_level) + funcName, 'background: rgba(207, 181, 42, 0.6); color: #000;', arguments);\r\n      }\r\n      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]);\r\n      \r\n      if(_tl &lt; _trace_level){ console.groupEnd(); }\r\n      _trace_level = _tl;\r\n      \r\n      return ret;\r\n    };\r\n    !useChain &#038;&#038; console.info('_trace applied to ' + funcName);\r\n    return true;\r\n  });\r\n  \r\n  _trace = function(fn){ this._trace(fn); }; \r\n  \r\n  TypeExtend(Object, '_watch', function(varName, binder) { \r\n  \r\n    if(this['__' + varName]){console.error('unable to apply _watch for ' + varName); return false;}\r\n    this['__' + varName] = this[varName];\r\n\r\n    Object.defineProperty(this, varName, {\r\n      get: function() {\r\n        !binder &#038;&#038; console.traceEx('_watch GET: ' + varName, 'background: rgba(97, 243, 126, 0.6); color: #000;');\r\n        return this['__' + varName];\r\n      },\r\n      set: function(val) {\r\n        !binder &#038;&#038; console.traceEx('_watch SET: ' + varName + '--&gt; value:' + val, 'background: rgba(243, 151, 151, 0.6); color: #000;');\r\n        this['__' + varName] != val &amp;&amp; (this._trigger('__set_' + varName, this['__' + varName], val), this['__' + varName] = val);\r\n        return this;\r\n      }      \r\n    });\r\n    \r\n    if(binder){ \/\/ ezt meg r\u00e1k\u00f6t\u00f6m figyel\u00e9snek\r\n      this._bind('__set_' + varName, binder);\r\n      console.info('_catch applied to ' + varName);\r\n    }\r\n    else{\r\n      console.info('_watch applied to ' + varName);\r\n    }\r\n    return true;\r\n  });\r\n  \r\n  TypeExtend(Object, '_catch', function(varName, binder) { \r\n    return this._watch(varName, binder);\r\n  });  \r\n  \r\n  _watch = function(vn, binder){ this._watch(vn, binder); };  \r\n  _catch = function(vn, binder){ this._watch(vn, binder); };  \r\n  \r\n}());\r\n\r\n(function() {  \/\/ _chain\r\n\r\n\/* usage\r\n  1. I have only a simple way to do this\r\n    this._chain();\r\n*\/\r\n\r\n  TypeExtend(Object, '_chain', function() { \r\n\r\n    for(var i in this){\r\n      if(typeof this[i] === &quot;function&quot;) {\r\n        this._trace(i, true);\r\n      }\r\n    }\r\n    console.obj('_chain applied to', this);\r\n\r\n  });\r\n\r\n}());\r\n<\/pre>\n<blockquote><p>see also: <a href=\"?p=11\" title=\"extend the console\">extend the console<\/a>, <a href=\"?p=23\" title=\"javascript extender (TypeExtend)\">javascript extender (TypeExtend)<\/a>, <a href=\"?p=232\" title=\"extender \u2013 Array\">extender \u2013 Array<\/a><\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-209","post","type-post","status-publish","format-standard","hentry","category-javascript"],"_links":{"self":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts\/209","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=209"}],"version-history":[{"count":24,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts\/209\/revisions"}],"predecessor-version":[{"id":1162,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=\/wp\/v2\/posts\/209\/revisions\/1162"}],"wp:attachment":[{"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=209"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=209"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.silverterra.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=209"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}