src/cm/media/js/lib/yui/yui3.0.0/build/oop/oop.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     1 /*
       
     2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
       
     3 Code licensed under the BSD License:
       
     4 http://developer.yahoo.net/yui/license.txt
       
     5 version: 3.0.0
       
     6 build: 1549
       
     7 */
       
     8 YUI.add('oop', function(Y) {
       
     9 
       
    10 /**
       
    11  * Supplies object inheritance and manipulation utilities.  This adds
       
    12  * additional functionaity to what is provided in yui-base, and the
       
    13  * methods are applied directly to the YUI instance.  This module
       
    14  * is required for most YUI components.
       
    15  * @module oop
       
    16  */
       
    17 
       
    18     var L  = Y.Lang, 
       
    19         A  = Y.Array,
       
    20         OP = Object.prototype,
       
    21         CLONE_MARKER = "_~yuim~_";
       
    22 
       
    23         // dispatch = function(o, f, c, proto, action) {
       
    24         //     if (o[action] && o.item) {
       
    25         //         return o[action].call(o, f, c);
       
    26         //     } else {
       
    27         //         switch (A.test(o)) {
       
    28         //             case 1:
       
    29         //                 return A[action](o, f, c);
       
    30         //             case 2:
       
    31         //                 return A[action](Y.Array(o, 0, true), f, c);
       
    32         //             default:
       
    33         //                 return Y.Object[action](o, f, c, proto);
       
    34         //         }
       
    35         //     }
       
    36         // };
       
    37 
       
    38     /**
       
    39      * The following methods are added to the YUI instance
       
    40      * @class YUI~oop
       
    41      */
       
    42 
       
    43     /**
       
    44      * Applies prototype properties from the supplier to the receiver.
       
    45      * The receiver can be a constructor or an instance.
       
    46      * @method augment
       
    47      * @param {Function} r  the object to receive the augmentation
       
    48      * @param {Function} s  the object that supplies the properties to augment
       
    49      * @param ov {boolean} if true, properties already on the receiver
       
    50      * will be overwritten if found on the supplier.
       
    51      * @param wl {string[]} a whitelist.  If supplied, only properties in 
       
    52      * this list will be applied to the receiver.
       
    53      * @param args {Array | Any} arg or arguments to apply to the supplier
       
    54      * constructor when initializing.
       
    55      * @return {object} the augmented object
       
    56      *
       
    57      * @todo constructor optional?
       
    58      * @todo understanding what an instance is augmented with
       
    59      * @TODO best practices for overriding sequestered methods.
       
    60      */
       
    61     Y.augment = function(r, s, ov, wl, args) {
       
    62         var sProto           = s.prototype, 
       
    63             newProto         = null, 
       
    64             construct        = s, 
       
    65             a                = (args) ? Y.Array(args) : [], 
       
    66             rProto           = r.prototype, 
       
    67             target           = rProto || r, 
       
    68             applyConstructor = false,
       
    69             sequestered, replacements, i;
       
    70 
       
    71         // working on a class, so apply constructor infrastructure
       
    72         if (rProto && construct) {
       
    73             sequestered  = {};
       
    74             replacements = {};
       
    75             newProto     = {};
       
    76 
       
    77             // sequester all of the functions in the supplier and replace with
       
    78             // one that will restore all of them.
       
    79             Y.each(sProto, function(v, k) {
       
    80                 replacements[k] = function() {
       
    81 
       
    82 // overwrite the prototype with all of the sequestered functions,
       
    83 // but only if it hasn't been overridden
       
    84                     for (i in sequestered) {
       
    85                         if (sequestered.hasOwnProperty(i) && (this[i] === replacements[i])) {
       
    86                             this[i] = sequestered[i];
       
    87                         }
       
    88                     }
       
    89 
       
    90                     // apply the constructor
       
    91                     construct.apply(this, a);
       
    92 
       
    93                     // apply the original sequestered function
       
    94                     return sequestered[k].apply(this, arguments);
       
    95                 };
       
    96 
       
    97                 if ((!wl || (k in wl)) && (ov || !(k in this))) {
       
    98                     if (L.isFunction(v)) {
       
    99                         // sequester the function
       
   100                         sequestered[k] = v;
       
   101 
       
   102 // replace the sequestered function with a function that will
       
   103 // restore all sequestered functions and exectue the constructor.
       
   104                         this[k] = replacements[k];
       
   105                     } else {
       
   106                         this[k] = v;
       
   107                     }
       
   108 
       
   109                 }
       
   110 
       
   111             }, newProto, true);
       
   112 
       
   113         // augmenting an instance, so apply the constructor immediately
       
   114         } else {
       
   115             applyConstructor = true;
       
   116         }
       
   117 
       
   118         Y.mix(target, newProto || sProto, ov, wl);
       
   119 
       
   120         if (applyConstructor) {
       
   121             s.apply(target, a);
       
   122         }
       
   123 
       
   124         return r;
       
   125     };
       
   126 
       
   127     /**
       
   128      * Applies object properties from the supplier to the receiver.  If
       
   129      * the target has the property, and the property is an object, the target
       
   130      * object will be augmented with the supplier's value.  If the property
       
   131      * is an array, the suppliers value will be appended to the target.
       
   132      * @method aggregate
       
   133      * @param {Function} r  the object to receive the augmentation
       
   134      * @param {Function} s  the object that supplies the properties to augment
       
   135      * @param ov {boolean} if true, properties already on the receiver
       
   136      * will be overwritten if found on the supplier.
       
   137      * @param wl {string[]} a whitelist.  If supplied, only properties in 
       
   138      * this list will be applied to the receiver.
       
   139      * @return {object} the extended object
       
   140      */
       
   141     Y.aggregate = function(r, s, ov, wl) {
       
   142         return Y.mix(r, s, ov, wl, 0, true);
       
   143     };
       
   144 
       
   145     /**
       
   146      * Utility to set up the prototype, constructor and superclass properties to
       
   147      * support an inheritance strategy that can chain constructors and methods.
       
   148      * Static members will not be inherited.
       
   149      *
       
   150      * @method extend
       
   151      * @param {Function} r   the object to modify
       
   152      * @param {Function} s the object to inherit
       
   153      * @param {Object} px prototype properties to add/override
       
   154      * @param {Object} sx static properties to add/override
       
   155      * @return {YUI} the YUI instance
       
   156      */
       
   157     Y.extend = function(r, s, px, sx) {
       
   158         if (!s||!r) {
       
   159             // @TODO error symbols
       
   160             Y.error("extend failed, verify dependencies");
       
   161         }
       
   162 
       
   163         var sp = s.prototype, rp=Y.Object(sp);
       
   164         r.prototype=rp;
       
   165 
       
   166         rp.constructor=r;
       
   167         r.superclass=sp;
       
   168 
       
   169         // assign constructor property
       
   170         if (s != Object && sp.constructor == OP.constructor) {
       
   171             sp.constructor=s;
       
   172         }
       
   173     
       
   174         // add prototype overrides
       
   175         if (px) {
       
   176             Y.mix(rp, px, true);
       
   177         }
       
   178 
       
   179         // add object overrides
       
   180         if (sx) {
       
   181             Y.mix(r, sx, true);
       
   182         }
       
   183 
       
   184         return r;
       
   185     };
       
   186 
       
   187     /**
       
   188      * Executes the supplied function for each item in
       
   189      * a collection.  Supports arrays, objects, and
       
   190      * Y.NodeLists
       
   191      * @method each
       
   192      * @param o the object to iterate
       
   193      * @param f the function to execute.  This function
       
   194      * receives the value, key, and object as parameters
       
   195      * @param proto if true, prototype properties are
       
   196      * iterated on objects
       
   197      * @return {YUI} the YUI instance
       
   198      */
       
   199     Y.each = function(o, f, c, proto) {
       
   200 
       
   201         if (o.each && o.item) {
       
   202             return o.each.call(o, f, c);
       
   203         } else {
       
   204             switch (A.test(o)) {
       
   205                 case 1:
       
   206                     return A.each(o, f, c);
       
   207                 case 2:
       
   208                     return A.each(Y.Array(o, 0, true), f, c);
       
   209                 default:
       
   210                     return Y.Object.each(o, f, c, proto);
       
   211             }
       
   212         }
       
   213 
       
   214         // return Y.Object.each(o, f, c);
       
   215     };
       
   216 
       
   217     // Y.each = function(o, f, c, proto) {
       
   218     //     return dispatch(o, f, c, proto, 'each');
       
   219     // };
       
   220 
       
   221     /*
       
   222      * Executes the supplied function for each item in
       
   223      * a collection.  The operation stops if the function
       
   224      * returns true. Supports arrays, objects, and
       
   225      * Y.NodeLists.
       
   226      * @method some
       
   227      * @param o the object to iterate
       
   228      * @param f the function to execute.  This function
       
   229      * receives the value, key, and object as parameters
       
   230      * @param proto if true, prototype properties are
       
   231      * iterated on objects
       
   232      * @return {boolean} true if the function ever returns true, false otherwise
       
   233      */
       
   234     // Y.some = function(o, f, c, proto) {
       
   235     //     return dispatch(o, f, c, proto, 'some');
       
   236     // };
       
   237 
       
   238     /**
       
   239      * Deep obj/array copy.  Functions are cloned with Y.bind.
       
   240      * Array-like objects are treated as arrays.
       
   241      * Primitives are returned untouched.  Optionally, a
       
   242      * function can be provided to handle other data types,
       
   243      * filter keys, validate values, etc.
       
   244      *
       
   245      * @method clone
       
   246      * @param o what to clone
       
   247      * @param safe {boolean} if true, objects will not have prototype
       
   248      * items from the source.  If false, they will.  In this case, the
       
   249      * original is initially protected, but the clone is not completely immune
       
   250      * from changes to the source object prototype.  Also, cloned prototype
       
   251      * items that are deleted from the clone will result in the value
       
   252      * of the source prototype being exposed.  If operating on a non-safe
       
   253      * clone, items should be nulled out rather than deleted.
       
   254      * @TODO review
       
   255      * @param f optional function to apply to each item in a collection;
       
   256      *          it will be executed prior to applying the value to
       
   257      *          the new object.  Return false to prevent the copy.
       
   258      * @param c optional execution context for f
       
   259      * @param owner Owner object passed when clone is iterating an
       
   260      * object.  Used to set up context for cloned functions.
       
   261      * @return {Array|Object} the cloned object
       
   262      */
       
   263     Y.clone = function(o, safe, f, c, owner, cloned) {
       
   264 
       
   265         if (!L.isObject(o)) {
       
   266             return o;
       
   267         }
       
   268 
       
   269         var o2, marked = cloned || {}, stamp;
       
   270 
       
   271         switch (L.type(o)) {
       
   272             case 'date':
       
   273                 return new Date(o);
       
   274             case 'regexp':
       
   275                 return new RegExp(o.source);
       
   276             case 'function':
       
   277                 o2 = Y.bind(o, owner);
       
   278                 break;
       
   279             case 'array':
       
   280                 o2 = [];
       
   281                 break;
       
   282             default:
       
   283 
       
   284                 // #2528250 only one clone of a given object should be created.
       
   285                 if (o[CLONE_MARKER]) {
       
   286                     return marked[o[CLONE_MARKER]];
       
   287                 }
       
   288 
       
   289                 stamp = Y.guid();
       
   290 
       
   291                 o2 = (safe) ? {} : Y.Object(o);
       
   292 
       
   293                 o[CLONE_MARKER] = stamp;
       
   294                 marked[stamp] = o;
       
   295         }
       
   296 
       
   297         // #2528250 don't try to clone element properties
       
   298         if (!o.addEventListener && !o.attachEvent) {
       
   299             Y.each(o, function(v, k) {
       
   300                 if (!f || (f.call(c || this, v, k, this, o) !== false)) {
       
   301                     if (k !== CLONE_MARKER) {
       
   302                         this[k] = Y.clone(v, safe, f, c, owner || o, marked);
       
   303                     }
       
   304                 }
       
   305             }, o2);
       
   306         }
       
   307 
       
   308         if (!cloned) {
       
   309             Y.each(marked, function(v, k) {
       
   310                 delete v[CLONE_MARKER];
       
   311             });
       
   312             marked = null;
       
   313         }
       
   314 
       
   315         return o2;
       
   316     };
       
   317 
       
   318 
       
   319     /**
       
   320      * Returns a function that will execute the supplied function in the
       
   321      * supplied object's context, optionally adding any additional
       
   322      * supplied parameters to the beginning of the arguments collection the 
       
   323      * supplied to the function.
       
   324      *
       
   325      * @method bind
       
   326      * @param f {Function|String} the function to bind, or a function name
       
   327      * to execute on the context object
       
   328      * @param c the execution context
       
   329      * @param args* 0..n arguments to include before the arguments the 
       
   330      * function is executed with.
       
   331      * @return {function} the wrapped function
       
   332      */
       
   333     Y.bind = function(f, c) {
       
   334         var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
       
   335         return function () {
       
   336             var fn = L.isString(f) ? c[f] : f, 
       
   337                 args = (xargs) ? xargs.concat(Y.Array(arguments, 0, true)) : arguments;
       
   338             return fn.apply(c || fn, args);
       
   339         };
       
   340     };
       
   341     
       
   342     /**
       
   343      * Returns a function that will execute the supplied function in the
       
   344      * supplied object's context, optionally adding any additional
       
   345      * supplied parameters to the end of the arguments the function
       
   346      * is executed with.
       
   347      *
       
   348      * @method rbind
       
   349      * @param f {Function|String} the function to bind, or a function name
       
   350      * to execute on the context object
       
   351      * @param c the execution context
       
   352      * @param args* 0..n arguments to append to the end of arguments collection
       
   353      * supplied to the function
       
   354      * @return {function} the wrapped function
       
   355      */
       
   356     Y.rbind = function(f, c) {
       
   357         var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
       
   358         return function () {
       
   359             var fn = L.isString(f) ? c[f] : f, 
       
   360                 args = (xargs) ? Y.Array(arguments, 0, true).concat(xargs) : arguments;
       
   361             return fn.apply(c || fn, args);
       
   362         };
       
   363     };
       
   364 
       
   365 
       
   366 
       
   367 }, '3.0.0' );