Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 7th, 2012  |  syntax: None  |  size: 7.05 KB  |  hits: 19  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <!doctype html>
  2.  
  3. <script>(function(undefined){
  4.  
  5. var recentDelimiter,
  6.     nativeIndexOf = Array.prototype.indexOf,
  7.     hasOwn = Object.prototype.hasOwnProperty,
  8.     toString = Object.prototype.toString,
  9.     isPrototypeOf = Object.prototype.isPrototypeOf,
  10.     prototypeProperty = 'isPrototypeOf',
  11.     types = "Number String Function Array Date RegExp Object".split(" "),
  12.     class2type = [];
  13.  
  14. for(var i=0,l=types.length,name;i<l;i++){
  15.   name = types[i];
  16.   class2type[ "[object " + name + "]" ] = name;
  17. }
  18.  
  19. var indexOf = function(array, item) {
  20.   if (array == undefined) return -1;
  21.   var i, l;
  22.   if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
  23.   for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
  24.   return -1;
  25. }
  26.  
  27. var prototypeDelimiter = function(arg){
  28.   if((arg===undefined || arg===0 ) && recentDelimiter){
  29.     // Allow for shorthand [$](0) chaining
  30.     if(arg===0)arg=init(this,recentDelimiter).chain();
  31.     else arg=init(this,recentDelimiter);
  32.     recentDelimiter = false;
  33.     return arg;
  34.   }else{
  35.     return isPrototypeOf.call(this,arg);
  36.   }
  37. }
  38.  
  39. try{
  40.   /*
  41.    * Check for Object.defineProperty support
  42.    * before adding property to Object.prototype
  43.    * IE8 only supports Object.defineProperty on
  44.    * DOM Objects
  45.    */
  46.   var defineProperty = {
  47.     value: prototypeDelimiter,
  48.     writable: true,
  49.     enumerable: false,
  50.     configurable: true
  51.   };
  52.   if(Object.defineProperty){
  53.     var fn = function(){};
  54.     Object.defineProperty(fn.prototype,"__delimit__",defineProperty);
  55.     for(var i in (new fn)){
  56.       if(i==='__delimit__'){
  57.         throw '__delimt__ found on fn';
  58.       }
  59.     }
  60.     isPrototypeOf = Object.prototype.__delimiter__ || isPrototypeOf;
  61.     Object.defineProperty(Object.prototype,"__delimit__",defineProperty);
  62.     prototypeProperty = '__delimit__';
  63.   }else{
  64.     throw 'Object.defineProperty doesn\' exist';
  65.   }
  66. }catch(error){
  67.   /*
  68.    * Internet Explorer requires workaround to get
  69.    * onto Object.prototype chain.
  70.    * This page: http://jsbin.com/ehaziv/3 tests
  71.    * for `isPrototypeOf` overiding support.
  72.    * isPrototypeOf's fuctionality is 100% preserved
  73.    * isPrototypeOf is also the least used Object.prototype
  74.    * it isn't even ever used in jQuery, Prototype...
  75.    */
  76.   Object.prototype.isPrototypeOf = prototypeDelimiter;
  77. }
  78.  
  79. /*
  80.  * Make an Object into a 'delimitertoString'
  81.  */
  82. function delimit(newDelimiter,parentDelimiter){
  83.   /*
  84.    * Objects and functions are stored as a tree
  85.    * on the delimitertoString to allow proper garbage collection
  86.    * everything should inherit from fns[0]
  87.    *
  88.    *              ojbs ['Object',obj1,obj2..]
  89.    *             /
  90.    * obj.toString
  91.    *             \
  92.    *              fns  [ObjectFn,fn1,fn2...]
  93.    */
  94.   var delimitertoString = newDelimiter.toString = function(){
  95.     recentDelimiter = this;
  96.     return prototypeProperty;
  97.   };
  98.   // ObjectFn
  99.   var fn = addFn();
  100.   var parentDelimitertoString;
  101.   if(parentDelimiter){
  102.     parentDelimitertoString = parentDelimiter.toString;
  103.     fn.prototype = new parentDelimitertoString.fns[0];
  104.   }
  105.  
  106.   delimitertoString.objs =
  107.    ( parentDelimitertoString && parentDelimitertoString.objs.slice(0) )
  108.         ||  ['Object'];
  109.   delimitertoString.fns = [fn];
  110.  
  111.   var i = 1,obj;
  112.   while(obj=delimitertoString.objs[i++]){
  113.     var fn = addFn(delimitertoString);
  114.     if(parentDelimitertoString){
  115.       var parentFn = parentDelimitertoString.fns[i-1].prototype;
  116.       for(var i in parentFn){
  117.         fn.prototype[i]=parentFn[i];
  118.       }
  119.     }
  120.   }
  121.   return newDelimiter;
  122. }
  123.  
  124. /*
  125.  * Add new function to delimitertoString
  126.  */
  127. function addFn(delimitertoString,constructor){
  128.   // The current obj is stored on `__` so it will
  129.   // appear at the top of the list in console
  130.   var fn = function(a){this.__=a;};
  131.   /*
  132.    * delimitertoString and Obj are Optional
  133.    */
  134.   if(constructor){
  135.     if(constructor.name){
  136.       var i = indexOf(types,constructor.name);
  137.       if(-1!=i){
  138.         constructor = types[i];
  139.       }
  140.     }
  141.     delimitertoString.objs.push(constructor);
  142.   }
  143.   if(delimitertoString){
  144.     delimitertoString.fns.push(fn);
  145.     fn.prototype = new delimitertoString.fns[0];
  146.   }
  147.   fn.prototype.chain = function(){this.__chain__=true;return this;}
  148.   fn.prototype.end = function(){return this.__;}
  149.   return fn;
  150. }
  151. /*
  152.  * Find the correct function in delimitertoString.fns
  153.  * based on an a contsructor or obj
  154.  * constructor may also be "Array,String,RegExp,Object,Date,Function"
  155.  * findFn(delimitertoString,null,obj) is to allow for cross frame lookup
  156.  * of native host objects
  157.  */
  158. function findFn(delimitertoString,constructor,obj){
  159.   var i;
  160.   // When called from init
  161.   if(obj!=undefined){
  162.     if(indexOf(types,obj.constructor.name)!=-1){
  163.       constructor = class2type[toString.call(obj)]
  164.     }else{
  165.       constructor = obj.constructor;
  166.     }
  167.     i = indexOf(delimitertoString.objs,constructor);
  168.   }else{
  169.     i = indexOf(delimitertoString.objs,constructor.name);
  170.     if(i==-1){
  171.       indexOf(delimitertoString.objs,constructor);
  172.     }
  173.   }
  174.   return delimitertoString.fns[i];
  175. }
  176.  
  177. /*
  178.  * Each Object,Array,String,etc
  179.  * has one fn that stores the
  180.  * prototype for the Object
  181.  */
  182.  
  183. function ret(obj,fn){
  184.   return fn.__chain__ ? init(obj,fn.__delimitertoString__).chain() : obj;
  185. }
  186.  
  187. function addPrototype(delimiter,constructor,name,method){
  188.   /*
  189.    * To support live inheritance, all prototypes
  190.    * added to Object are copied over to each prototype
  191.    * and marked with object flag.  The flag tells the script
  192.    * it is safe to overide later(to simulate inheritance)
  193.    * any other protypes added to an Object must also copy
  194.    * over all `Object.prototype`s on creation
  195.    * This means adding 'Object' prototypes are slighly more
  196.    * expensive, but should be used sparingly to begin with
  197.    */
  198.   var fn = findFn(delimiter.toString,constructor) || addFn(delimiter.toString,constructor);
  199.   fn.prototype[name] = function(){
  200.     var apply = method.apply(this.__,arguments);
  201.     return apply===undefined?apply:ret(apply,this);
  202.   }
  203. }
  204.  
  205. /*
  206.  * runs when delimitertoString is called
  207.  * on object example: object[$]()
  208.  */
  209. function init(obj,delimiter){
  210.   // fn contains `Object`s proxied prototype
  211.   var fn = findFn(delimiter.toString,undefined,obj) || delimiter.toString.fns[0];
  212.   var ret = new fn(obj);
  213.   // Store reference to delimitertoString in case of chaining
  214.   ret.__delimitertoString__ = delimiter.toString;
  215.   if(class2type[toString.call(obj)=='Function'] || indexOf(types,obj.name)){
  216.     //console.log(delimiter);
  217.     ret.fn = function(o){
  218.       for(var i in o){
  219.         addPrototype(delimiter,obj,i,o[i]);
  220.       }
  221.     }
  222.   }
  223.   return ret;
  224. }
  225.  
  226. window.delimit = delimit;
  227. // Allow for jQuery, Mootools, Zepto, Prototype... to continue to use '$' variable
  228. delimit(window.$ || (window.$ = {}));
  229.  
  230. })();
  231.  
  232. Array[$]().fn({
  233.   indexOf:function(array){
  234.     console.log('indexOf');
  235.   }
  236. });
  237.  
  238. var fn = function(){};
  239. var f = new fn;
  240.  
  241. fn[$]().fn({
  242.   test:function(){
  243.     return 'test'
  244.   }
  245. });
  246.  
  247. Object[$]().fn({
  248.   log:function(){
  249.     console.log(this);
  250.   }
  251. });
  252.  
  253. f
  254.   [$]().test()
  255.   [$]().log();
  256.  
  257. var o = {};
  258. delimit(o,$);
  259.  
  260. Array[o]().fn({
  261.   indexOf:function(array){
  262.     console.log('indexOf override!');
  263.   },
  264.   yo:function(){alert('yo')}
  265. });
  266.  
  267. var array = [1,2,3];
  268. array[o]().indexOf(2);
  269.  
  270.  
  271. </script>