src/cm/media/js/lib/yui/yui_3.10.3/build/oop/oop-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('oop', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11 Adds object inheritance and manipulation utilities to the YUI instance. This
       
    12 module is required by most YUI components.
       
    13 
       
    14 @module oop
       
    15 **/
       
    16 
       
    17 var L            = Y.Lang,
       
    18     A            = Y.Array,
       
    19     OP           = Object.prototype,
       
    20     CLONE_MARKER = '_~yuim~_',
       
    21 
       
    22     hasOwn   = OP.hasOwnProperty,
       
    23     toString = OP.toString;
       
    24 
       
    25 function dispatch(o, f, c, proto, action) {
       
    26     if (o && o[action] && o !== Y) {
       
    27         return o[action].call(o, f, c);
       
    28     } else {
       
    29         switch (A.test(o)) {
       
    30             case 1:
       
    31                 return A[action](o, f, c);
       
    32             case 2:
       
    33                 return A[action](Y.Array(o, 0, true), f, c);
       
    34             default:
       
    35                 return Y.Object[action](o, f, c, proto);
       
    36         }
       
    37     }
       
    38 }
       
    39 
       
    40 /**
       
    41 Augments the _receiver_ with prototype properties from the _supplier_. The
       
    42 receiver may be a constructor function or an object. The supplier must be a
       
    43 constructor function.
       
    44 
       
    45 If the _receiver_ is an object, then the _supplier_ constructor will be called
       
    46 immediately after _receiver_ is augmented, with _receiver_ as the `this` object.
       
    47 
       
    48 If the _receiver_ is a constructor function, then all prototype methods of
       
    49 _supplier_ that are copied to _receiver_ will be sequestered, and the
       
    50 _supplier_ constructor will not be called immediately. The first time any
       
    51 sequestered method is called on the _receiver_'s prototype, all sequestered
       
    52 methods will be immediately copied to the _receiver_'s prototype, the
       
    53 _supplier_'s constructor will be executed, and finally the newly unsequestered
       
    54 method that was called will be executed.
       
    55 
       
    56 This sequestering logic sounds like a bunch of complicated voodoo, but it makes
       
    57 it cheap to perform frequent augmentation by ensuring that suppliers'
       
    58 constructors are only called if a supplied method is actually used. If none of
       
    59 the supplied methods is ever used, then there's no need to take the performance
       
    60 hit of calling the _supplier_'s constructor.
       
    61 
       
    62 @method augment
       
    63 @param {Function|Object} receiver Object or function to be augmented.
       
    64 @param {Function} supplier Function that supplies the prototype properties with
       
    65   which to augment the _receiver_.
       
    66 @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
       
    67   will be overwritten if found on the supplier's prototype.
       
    68 @param {String[]} [whitelist] An array of property names. If specified,
       
    69   only the whitelisted prototype properties will be applied to the receiver, and
       
    70   all others will be ignored.
       
    71 @param {Array|any} [args] Argument or array of arguments to pass to the
       
    72   supplier's constructor when initializing.
       
    73 @return {Function} Augmented object.
       
    74 @for YUI
       
    75 **/
       
    76 Y.augment = function (receiver, supplier, overwrite, whitelist, args) {
       
    77     var rProto    = receiver.prototype,
       
    78         sequester = rProto && supplier,
       
    79         sProto    = supplier.prototype,
       
    80         to        = rProto || receiver,
       
    81 
       
    82         copy,
       
    83         newPrototype,
       
    84         replacements,
       
    85         sequestered,
       
    86         unsequester;
       
    87 
       
    88     args = args ? Y.Array(args) : [];
       
    89 
       
    90     if (sequester) {
       
    91         newPrototype = {};
       
    92         replacements = {};
       
    93         sequestered  = {};
       
    94 
       
    95         copy = function (value, key) {
       
    96             if (overwrite || !(key in rProto)) {
       
    97                 if (toString.call(value) === '[object Function]') {
       
    98                     sequestered[key] = value;
       
    99 
       
   100                     newPrototype[key] = replacements[key] = function () {
       
   101                         return unsequester(this, value, arguments);
       
   102                     };
       
   103                 } else {
       
   104                     newPrototype[key] = value;
       
   105                 }
       
   106             }
       
   107         };
       
   108 
       
   109         unsequester = function (instance, fn, fnArgs) {
       
   110             // Unsequester all sequestered functions.
       
   111             for (var key in sequestered) {
       
   112                 if (hasOwn.call(sequestered, key)
       
   113                         && instance[key] === replacements[key]) {
       
   114 
       
   115                     instance[key] = sequestered[key];
       
   116                 }
       
   117             }
       
   118 
       
   119             // Execute the supplier constructor.
       
   120             supplier.apply(instance, args);
       
   121 
       
   122             // Finally, execute the original sequestered function.
       
   123             return fn.apply(instance, fnArgs);
       
   124         };
       
   125 
       
   126         if (whitelist) {
       
   127             Y.Array.each(whitelist, function (name) {
       
   128                 if (name in sProto) {
       
   129                     copy(sProto[name], name);
       
   130                 }
       
   131             });
       
   132         } else {
       
   133             Y.Object.each(sProto, copy, null, true);
       
   134         }
       
   135     }
       
   136 
       
   137     Y.mix(to, newPrototype || sProto, overwrite, whitelist);
       
   138 
       
   139     if (!sequester) {
       
   140         supplier.apply(to, args);
       
   141     }
       
   142 
       
   143     return receiver;
       
   144 };
       
   145 
       
   146 /**
       
   147  * Copies object properties from the supplier to the receiver. If the target has
       
   148  * the property, and the property is an object, the target object will be
       
   149  * augmented with the supplier's value.
       
   150  *
       
   151  * @method aggregate
       
   152  * @param {Object} receiver Object to receive the augmentation.
       
   153  * @param {Object} supplier Object that supplies the properties with which to
       
   154  *     augment the receiver.
       
   155  * @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
       
   156  *     will be overwritten if found on the supplier.
       
   157  * @param {String[]} [whitelist] Whitelist. If supplied, only properties in this
       
   158  *     list will be applied to the receiver.
       
   159  * @return {Object} Augmented object.
       
   160  */
       
   161 Y.aggregate = function(r, s, ov, wl) {
       
   162     return Y.mix(r, s, ov, wl, 0, true);
       
   163 };
       
   164 
       
   165 /**
       
   166  * Utility to set up the prototype, constructor and superclass properties to
       
   167  * support an inheritance strategy that can chain constructors and methods.
       
   168  * Static members will not be inherited.
       
   169  *
       
   170  * @method extend
       
   171  * @param {function} r   the object to modify.
       
   172  * @param {function} s the object to inherit.
       
   173  * @param {object} px prototype properties to add/override.
       
   174  * @param {object} sx static properties to add/override.
       
   175  * @return {object} the extended object.
       
   176  */
       
   177 Y.extend = function(r, s, px, sx) {
       
   178     if (!s || !r) {
       
   179         Y.error('extend failed, verify dependencies');
       
   180     }
       
   181 
       
   182     var sp = s.prototype, rp = Y.Object(sp);
       
   183     r.prototype = rp;
       
   184 
       
   185     rp.constructor = r;
       
   186     r.superclass = sp;
       
   187 
       
   188     // assign constructor property
       
   189     if (s != Object && sp.constructor == OP.constructor) {
       
   190         sp.constructor = s;
       
   191     }
       
   192 
       
   193     // add prototype overrides
       
   194     if (px) {
       
   195         Y.mix(rp, px, true);
       
   196     }
       
   197 
       
   198     // add object overrides
       
   199     if (sx) {
       
   200         Y.mix(r, sx, true);
       
   201     }
       
   202 
       
   203     return r;
       
   204 };
       
   205 
       
   206 /**
       
   207  * Executes the supplied function for each item in
       
   208  * a collection.  Supports arrays, objects, and
       
   209  * NodeLists
       
   210  * @method each
       
   211  * @param {object} o the object to iterate.
       
   212  * @param {function} f the function to execute.  This function
       
   213  * receives the value, key, and object as parameters.
       
   214  * @param {object} c the execution context for the function.
       
   215  * @param {boolean} proto if true, prototype properties are
       
   216  * iterated on objects.
       
   217  * @return {YUI} the YUI instance.
       
   218  */
       
   219 Y.each = function(o, f, c, proto) {
       
   220     return dispatch(o, f, c, proto, 'each');
       
   221 };
       
   222 
       
   223 /**
       
   224  * Executes the supplied function for each item in
       
   225  * a collection.  The operation stops if the function
       
   226  * returns true. Supports arrays, objects, and
       
   227  * NodeLists.
       
   228  * @method some
       
   229  * @param {object} o the object to iterate.
       
   230  * @param {function} f the function to execute.  This function
       
   231  * receives the value, key, and object as parameters.
       
   232  * @param {object} c the execution context for the function.
       
   233  * @param {boolean} proto if true, prototype properties are
       
   234  * iterated on objects.
       
   235  * @return {boolean} true if the function ever returns true,
       
   236  * false otherwise.
       
   237  */
       
   238 Y.some = function(o, f, c, proto) {
       
   239     return dispatch(o, f, c, proto, 'some');
       
   240 };
       
   241 
       
   242 /**
       
   243 Deep object/array copy. Function clones are actually wrappers around the
       
   244 original function. Array-like objects are treated as arrays. Primitives are
       
   245 returned untouched. Optionally, a function can be provided to handle other data
       
   246 types, filter keys, validate values, etc.
       
   247 
       
   248 **Note:** Cloning a non-trivial object is a reasonably heavy operation, due to
       
   249 the need to recursively iterate down non-primitive properties. Clone should be
       
   250 used only when a deep clone down to leaf level properties is explicitly
       
   251 required. This method will also
       
   252 
       
   253 In many cases (for example, when trying to isolate objects used as hashes for
       
   254 configuration properties), a shallow copy, using `Y.merge()` is normally
       
   255 sufficient. If more than one level of isolation is required, `Y.merge()` can be
       
   256 used selectively at each level which needs to be isolated from the original
       
   257 without going all the way to leaf properties.
       
   258 
       
   259 @method clone
       
   260 @param {object} o what to clone.
       
   261 @param {boolean} safe if true, objects will not have prototype items from the
       
   262     source. If false, they will. In this case, the original is initially
       
   263     protected, but the clone is not completely immune from changes to the source
       
   264     object prototype. Also, cloned prototype items that are deleted from the
       
   265     clone will result in the value of the source prototype being exposed. If
       
   266     operating on a non-safe clone, items should be nulled out rather than
       
   267     deleted.
       
   268 @param {function} f optional function to apply to each item in a collection; it
       
   269     will be executed prior to applying the value to the new object.
       
   270     Return false to prevent the copy.
       
   271 @param {object} c optional execution context for f.
       
   272 @param {object} owner Owner object passed when clone is iterating an object.
       
   273     Used to set up context for cloned functions.
       
   274 @param {object} cloned hash of previously cloned objects to avoid multiple
       
   275     clones.
       
   276 @return {Array|Object} the cloned object.
       
   277 **/
       
   278 Y.clone = function(o, safe, f, c, owner, cloned) {
       
   279     var o2, marked, stamp;
       
   280 
       
   281     // Does not attempt to clone:
       
   282     //
       
   283     // * Non-typeof-object values, "primitive" values don't need cloning.
       
   284     //
       
   285     // * YUI instances, cloning complex object like YUI instances is not
       
   286     //   advised, this is like cloning the world.
       
   287     //
       
   288     // * DOM nodes (#2528250), common host objects like DOM nodes cannot be
       
   289     //   "subclassed" in Firefox and old versions of IE. Trying to use
       
   290     //   `Object.create()` or `Y.extend()` on a DOM node will throw an error in
       
   291     //   these browsers.
       
   292     //
       
   293     // Instad, the passed-in `o` will be return as-is when it matches one of the
       
   294     // above criteria.
       
   295     if (!L.isObject(o) ||
       
   296             Y.instanceOf(o, YUI) ||
       
   297             (o.addEventListener || o.attachEvent)) {
       
   298 
       
   299         return o;
       
   300     }
       
   301 
       
   302     marked = cloned || {};
       
   303 
       
   304     switch (L.type(o)) {
       
   305         case 'date':
       
   306             return new Date(o);
       
   307         case 'regexp':
       
   308             // if we do this we need to set the flags too
       
   309             // return new RegExp(o.source);
       
   310             return o;
       
   311         case 'function':
       
   312             // o2 = Y.bind(o, owner);
       
   313             // break;
       
   314             return o;
       
   315         case 'array':
       
   316             o2 = [];
       
   317             break;
       
   318         default:
       
   319 
       
   320             // #2528250 only one clone of a given object should be created.
       
   321             if (o[CLONE_MARKER]) {
       
   322                 return marked[o[CLONE_MARKER]];
       
   323             }
       
   324 
       
   325             stamp = Y.guid();
       
   326 
       
   327             o2 = (safe) ? {} : Y.Object(o);
       
   328 
       
   329             o[CLONE_MARKER] = stamp;
       
   330             marked[stamp] = o;
       
   331     }
       
   332 
       
   333     Y.each(o, function(v, k) {
       
   334         if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
       
   335             if (k !== CLONE_MARKER) {
       
   336                 if (k == 'prototype') {
       
   337                     // skip the prototype
       
   338                 // } else if (o[k] === o) {
       
   339                 //     this[k] = this;
       
   340                 } else {
       
   341                     this[k] =
       
   342                         Y.clone(v, safe, f, c, owner || o, marked);
       
   343                 }
       
   344             }
       
   345         }
       
   346     }, o2);
       
   347 
       
   348     if (!cloned) {
       
   349         Y.Object.each(marked, function(v, k) {
       
   350             if (v[CLONE_MARKER]) {
       
   351                 try {
       
   352                     delete v[CLONE_MARKER];
       
   353                 } catch (e) {
       
   354                     v[CLONE_MARKER] = null;
       
   355                 }
       
   356             }
       
   357         }, this);
       
   358         marked = null;
       
   359     }
       
   360 
       
   361     return o2;
       
   362 };
       
   363 
       
   364 /**
       
   365  * Returns a function that will execute the supplied function in the
       
   366  * supplied object's context, optionally adding any additional
       
   367  * supplied parameters to the beginning of the arguments collection the
       
   368  * supplied to the function.
       
   369  *
       
   370  * @method bind
       
   371  * @param {Function|String} f the function to bind, or a function name
       
   372  * to execute on the context object.
       
   373  * @param {object} c the execution context.
       
   374  * @param {any} args* 0..n arguments to include before the arguments the
       
   375  * function is executed with.
       
   376  * @return {function} the wrapped function.
       
   377  */
       
   378 Y.bind = function(f, c) {
       
   379     var xargs = arguments.length > 2 ?
       
   380             Y.Array(arguments, 2, true) : null;
       
   381     return function() {
       
   382         var fn = L.isString(f) ? c[f] : f,
       
   383             args = (xargs) ?
       
   384                 xargs.concat(Y.Array(arguments, 0, true)) : arguments;
       
   385         return fn.apply(c || fn, args);
       
   386     };
       
   387 };
       
   388 
       
   389 /**
       
   390  * Returns a function that will execute the supplied function in the
       
   391  * supplied object's context, optionally adding any additional
       
   392  * supplied parameters to the end of the arguments the function
       
   393  * is executed with.
       
   394  *
       
   395  * @method rbind
       
   396  * @param {Function|String} f the function to bind, or a function name
       
   397  * to execute on the context object.
       
   398  * @param {object} c the execution context.
       
   399  * @param {any} args* 0..n arguments to append to the end of
       
   400  * arguments collection supplied to the function.
       
   401  * @return {function} the wrapped function.
       
   402  */
       
   403 Y.rbind = function(f, c) {
       
   404     var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
       
   405     return function() {
       
   406         var fn = L.isString(f) ? c[f] : f,
       
   407             args = (xargs) ?
       
   408                 Y.Array(arguments, 0, true).concat(xargs) : arguments;
       
   409         return fn.apply(c || fn, args);
       
   410     };
       
   411 };
       
   412 
       
   413 
       
   414 }, '3.10.3', {"requires": ["yui-base"]});