[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/oop/ -> oop.js (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1