src/cm/media/js/lib/yui/yui_3.0.0b1/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.0b1
       
     6 build: 1163
       
     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 
       
    22     /**
       
    23      * The following methods are added to the YUI instance
       
    24      * @class YUI~oop
       
    25      */
       
    26 
       
    27     /**
       
    28      * Applies prototype properties from the supplier to the receiver.
       
    29      * The receiver can be a constructor or an instance.
       
    30      * @method augment
       
    31      * @param {Function} r  the object to receive the augmentation
       
    32      * @param {Function} s  the object that supplies the properties to augment
       
    33      * @param ov {boolean} if true, properties already on the receiver
       
    34      * will be overwritten if found on the supplier.
       
    35      * @param wl {string[]} a whitelist.  If supplied, only properties in 
       
    36      * this list will be applied to the receiver.
       
    37      * @param args {Array | Any} arg or arguments to apply to the supplier
       
    38      * constructor when initializing.
       
    39      * @return {object} the augmented object
       
    40      *
       
    41      * @todo constructor optional?
       
    42      * @todo understanding what an instance is augmented with
       
    43      * @TODO best practices for overriding sequestered methods.
       
    44      */
       
    45     Y.augment = function(r, s, ov, wl, args) {
       
    46         var sProto           = s.prototype, 
       
    47             newProto         = null, 
       
    48             construct        = s, 
       
    49             a                = (args) ? Y.Array(args) : [], 
       
    50             rProto           = r.prototype, 
       
    51             target           = rProto || r, 
       
    52             applyConstructor = false,
       
    53             sequestered, replacements, i;
       
    54 
       
    55         // working on a class, so apply constructor infrastructure
       
    56         if (rProto && construct) {
       
    57             sequestered  = {};
       
    58             replacements = {};
       
    59             newProto     = {};
       
    60 
       
    61             // sequester all of the functions in the supplier and replace with
       
    62             // one that will restore all of them.
       
    63             Y.each(sProto, function(v, k) {
       
    64                 replacements[k] = function() {
       
    65 
       
    66 // overwrite the prototype with all of the sequestered functions,
       
    67 // but only if it hasn't been overridden
       
    68                     for (i in sequestered) {
       
    69                         if (sequestered.hasOwnProperty(i) && (this[i] === replacements[i])) {
       
    70                             this[i] = sequestered[i];
       
    71                         }
       
    72                     }
       
    73 
       
    74                     // apply the constructor
       
    75                     construct.apply(this, a);
       
    76 
       
    77                     // apply the original sequestered function
       
    78                     return sequestered[k].apply(this, arguments);
       
    79                 };
       
    80 
       
    81                 if ((!wl || (k in wl)) && (ov || !(k in this))) {
       
    82                     if (L.isFunction(v)) {
       
    83                         // sequester the function
       
    84                         sequestered[k] = v;
       
    85 
       
    86 // replace the sequestered function with a function that will
       
    87 // restore all sequestered functions and exectue the constructor.
       
    88                         this[k] = replacements[k];
       
    89                     } else {
       
    90                         this[k] = v;
       
    91                     }
       
    92 
       
    93                 }
       
    94 
       
    95             }, newProto, true);
       
    96 
       
    97         // augmenting an instance, so apply the constructor immediately
       
    98         } else {
       
    99             applyConstructor = true;
       
   100         }
       
   101 
       
   102         Y.mix(target, newProto || sProto, ov, wl);
       
   103 
       
   104         if (applyConstructor) {
       
   105             s.apply(target, a);
       
   106         }
       
   107 
       
   108         return r;
       
   109     };
       
   110 
       
   111     /**
       
   112      * Applies object properties from the supplier to the receiver.  If
       
   113      * the target has the property, and the property is an object, the target
       
   114      * object will be augmented with the supplier's value.  If the property
       
   115      * is an array, the suppliers value will be appended to the target.
       
   116      * @method aggregate
       
   117      * @param {Function} r  the object to receive the augmentation
       
   118      * @param {Function} s  the object that supplies the properties to augment
       
   119      * @param ov {boolean} if true, properties already on the receiver
       
   120      * will be overwritten if found on the supplier.
       
   121      * @param wl {string[]} a whitelist.  If supplied, only properties in 
       
   122      * this list will be applied to the receiver.
       
   123      * @return {object} the extended object
       
   124      */
       
   125     Y.aggregate = function(r, s, ov, wl) {
       
   126         return Y.mix(r, s, ov, wl, 0, true);
       
   127     };
       
   128 
       
   129     /**
       
   130      * Utility to set up the prototype, constructor and superclass properties to
       
   131      * support an inheritance strategy that can chain constructors and methods.
       
   132      * Static members will not be inherited.
       
   133      *
       
   134      * @method extend
       
   135      * @param {Function} r   the object to modify
       
   136      * @param {Function} s the object to inherit
       
   137      * @param {Object} px prototype properties to add/override
       
   138      * @param {Object} sx static properties to add/override
       
   139      * @return {YUI} the YUI instance
       
   140      */
       
   141     Y.extend = function(r, s, px, sx) {
       
   142         if (!s||!r) {
       
   143             // @TODO error symbols
       
   144             Y.error("extend failed, verify dependencies");
       
   145         }
       
   146 
       
   147         var sp = s.prototype, rp=Y.Object(sp);
       
   148         r.prototype=rp;
       
   149 
       
   150         rp.constructor=r;
       
   151         r.superclass=sp;
       
   152 
       
   153         // assign constructor property
       
   154         if (s != Object && sp.constructor == OP.constructor) {
       
   155             sp.constructor=s;
       
   156         }
       
   157     
       
   158         // add prototype overrides
       
   159         if (px) {
       
   160             Y.mix(rp, px, true);
       
   161         }
       
   162 
       
   163         // add object overrides
       
   164         if (sx) {
       
   165             Y.mix(r, sx, true);
       
   166         }
       
   167 
       
   168         return r;
       
   169     };
       
   170 
       
   171     /**
       
   172      * Executes the supplied function for each item in
       
   173      * a collection.  Supports arrays, objects, and
       
   174      * Y.NodeLists
       
   175      * @method each
       
   176      * @param o the object to iterate
       
   177      * @param f the function to execute.  This function
       
   178      * receives the value, key, and object as parameters
       
   179      * @param proto if true, prototype properties are
       
   180      * iterated on objects
       
   181      * @return {YUI} the YUI instance
       
   182      */
       
   183     Y.each = function(o, f, c, proto) {
       
   184 
       
   185         if (o.each && o.item) {
       
   186             return o.each.call(o, f, c);
       
   187         } else {
       
   188             switch (A.test(o)) {
       
   189                 case 1:
       
   190                     return A.each(o, f, c);
       
   191                 case 2:
       
   192                     return A.each(Y.Array(o, 0, true), f, c);
       
   193                 default:
       
   194                     return Y.Object.each(o, f, c, proto);
       
   195             }
       
   196         }
       
   197 
       
   198         // return Y.Object.each(o, f, c);
       
   199     };
       
   200 
       
   201     /**
       
   202      * Deep obj/array copy.  Functions will are cloned with Y.bind.
       
   203      * Array-like objects are treated as arrays.
       
   204      * primitives are returned untouched.  Optionally a
       
   205      * function can be provided to handle other data types,
       
   206      * filter keys, validate values, etc.
       
   207      *
       
   208      * @method clone
       
   209      * @param o what to clone
       
   210      * @param safe {boolean} if true, objects will not have prototype
       
   211      * items from the source.  If false, it does.  In this case, the
       
   212      * original is initally protected, but the clone is not completely immune
       
   213      * from changes to the source object prototype.  Also, cloned prototype
       
   214      * items that are deleted from the clone will result in the value
       
   215      * of the source prototype to be exposed.  If operating on a non-safe
       
   216      * clone, items should be nulled out rather than deleted.
       
   217      * @TODO review
       
   218      * @param f optional function to apply to each item in a collection
       
   219      *          it will be executed prior to applying the value to
       
   220      *          the new object.  Return false to prevent the copy.
       
   221      * @param c optional execution context for f
       
   222      * @param owner Owner object passed when clone is iterating an
       
   223      * object.  Used to set up context for cloned functions.
       
   224      * @return {Array|Object} the cloned object
       
   225      */
       
   226     Y.clone = function(o, safe, f, c, owner) {
       
   227 
       
   228         if (!L.isObject(o)) {
       
   229             return o;
       
   230         }
       
   231 
       
   232         var o2;
       
   233 
       
   234         switch (L.type(o)) {
       
   235             case 'date':
       
   236                 return new Date(o);
       
   237             case 'regexp':
       
   238                 return new RegExp(o.source);
       
   239             case 'function':
       
   240                 o2 = Y.bind(o, owner);
       
   241                 break;
       
   242             case 'array':
       
   243                 o2 = [];
       
   244                 break;
       
   245             default:
       
   246                 o2 = (safe) ? {} : Y.Object(o);
       
   247         }
       
   248 
       
   249         Y.each(o, function(v, k) {
       
   250             if (!f || (f.call(c || this, v, k, this, o) !== false)) {
       
   251                 this[k] =  Y.clone(v, safe, f, c, this);
       
   252             }
       
   253         }, o2);
       
   254 
       
   255         return o2;
       
   256     };
       
   257 
       
   258 
       
   259     /**
       
   260      * Returns a function that will execute the supplied function in the
       
   261      * supplied object's context, optionally adding any additional
       
   262      * supplied parameters to the beginning of the arguments collection the 
       
   263      * supplied to the function.
       
   264      *
       
   265      * @method bind
       
   266      * @param f {Function|String} the function to bind, or a function name
       
   267      * to execute on the context object
       
   268      * @param c the execution context
       
   269      * @param args* 0..n arguments to include before the arguments the 
       
   270      * function is executed with.
       
   271      * @return {function} the wrapped function
       
   272      */
       
   273     Y.bind = function(f, c) {
       
   274         var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
       
   275         return function () {
       
   276             var fn = L.isString(f) ? c[f] : f, 
       
   277                 args = (xargs) ? xargs.concat(Y.Array(arguments, 0, true)) : arguments;
       
   278             return fn.apply(c || fn, args);
       
   279         };
       
   280     };
       
   281     
       
   282     /**
       
   283      * Returns a function that will execute the supplied function in the
       
   284      * supplied object's context, optionally adding any additional
       
   285      * supplied parameters to the end of the arguments the function
       
   286      * is executed with.
       
   287      *
       
   288      * @method rbind
       
   289      * @param f {Function|String} the function to bind, or a function name
       
   290      * to execute on the context object
       
   291      * @param c the execution context
       
   292      * @param args* 0..n arguments to append to the end of arguments collection
       
   293      * supplied to the function
       
   294      * @return {function} the wrapped function
       
   295      */
       
   296     Y.rbind = function(f, c) {
       
   297         var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
       
   298         return function () {
       
   299             var fn = L.isString(f) ? c[f] : f, 
       
   300                 args = (xargs) ? Y.Array(arguments, 0, true).concat(xargs) : arguments;
       
   301             return fn.apply(c || fn, args);
       
   302         };
       
   303     };
       
   304 
       
   305 
       
   306 
       
   307 }, '3.0.0b1' );