oop-debug.js revision cce3fb1ef3935d8cea4963fcb7d4f05cee7f8e17
5f40f927dba3cf399373572f6ed6fe59a376376eTodd KlootsYUI.add('oop', function(Y) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots/**
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * Supplies object inheritance and manipulation utilities. This adds
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * additional functionaity to what is provided in yui-base, and the
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * methods are applied directly to the YUI instance. This module
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * is required for most YUI components.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @module oop
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots */
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots var L = Y.Lang,
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots A = Y.Array,
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots OP = Object.prototype,
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots CLONE_MARKER = "_~yuim~_",
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots EACH = 'each',
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots SOME = 'some',
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots dispatch = function(o, f, c, proto, action) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots if (o && o[action] && o !== Y) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return o[action].call(o, f, c);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots } else {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots switch (A.test(o)) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots case 1:
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return A[action](o, f, c);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots case 2:
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return A[action](Y.Array(o, 0, true), f, c);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots default:
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return Y.Object[action](o, f, c, proto);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots /**
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * The following methods are added to the YUI instance
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @class YUI~oop
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots */
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots /**
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * Applies prototype properties from the supplier to the receiver.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * The receiver can be a constructor or an instance.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @method augment
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param {Function} r the object to receive the augmentation
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param {Function} s the object that supplies the properties to augment
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param ov {boolean} if true, properties already on the receiver
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * will be overwritten if found on the supplier.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param wl {string[]} a whitelist. If supplied, only properties in
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * this list will be applied to the receiver.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param args {Array | Any} arg or arguments to apply to the supplier
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * constructor when initializing.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @return {object} the augmented object
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots *
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @todo constructor optional?
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @todo understanding what an instance is augmented with
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @TODO best practices for overriding sequestered methods.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots */
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.augment = function(r, s, ov, wl, args) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots var sProto = s.prototype,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots newProto = null,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots construct = s,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots a = (args) ? Y.Array(args) : [],
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots rProto = r.prototype,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots target = rProto || r,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots applyConstructor = false,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots sequestered, replacements, i;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // working on a class, so apply constructor infrastructure
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (rProto && construct) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots sequestered = {};
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots replacements = {};
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots newProto = {};
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // sequester all of the functions in the supplier and replace with
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // one that will restore all of them.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.Object.each(sProto, function(v, k) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots replacements[k] = function() {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots// Y.log('sequestered function "' + k + '" executed. Initializing EventTarget');
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots// overwrite the prototype with all of the sequestered functions,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots// but only if it hasn't been overridden
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots for (i in sequestered) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (sequestered.hasOwnProperty(i) && (this[i] === replacements[i])) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // Y.log('... restoring ' + k);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots this[i] = sequestered[i];
de413b3e25c9cba63ab4b3003f5a4524d49f9f05Todd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // apply the constructor
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots construct.apply(this, a);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // apply the original sequestered function
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return sequestered[k].apply(this, arguments);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots };
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots if ((!wl || (k in wl)) && (ov || !(k in this))) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // Y.log('augment: ' + k);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (L.isFunction(v)) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // sequester the function
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots sequestered[k] = v;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
de413b3e25c9cba63ab4b3003f5a4524d49f9f05Todd Kloots// replace the sequestered function with a function that will
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots// restore all sequestered functions and exectue the constructor.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots this[k] = replacements[k];
de413b3e25c9cba63ab4b3003f5a4524d49f9f05Todd Kloots } else {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // Y.log('augment() applying non-function: ' + k);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots this[k] = v;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }, newProto, true);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots // augmenting an instance, so apply the constructor immediately
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots } else {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots applyConstructor = true;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.mix(target, newProto || sProto, ov, wl);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (applyConstructor) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots s.apply(target, a);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots return r;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots /**
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * Applies object properties from the supplier to the receiver. If
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * the target has the property, and the property is an object, the target
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * object will be augmented with the supplier's value. If the property
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * is an array, the suppliers value will be appended to the target.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @method aggregate
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param {Function} r the object to receive the augmentation
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param {Function} s the object that supplies the properties to augment
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param ov {boolean} if true, properties already on the receiver
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * will be overwritten if found on the supplier.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param wl {string[]} a whitelist. If supplied, only properties in
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * this list will be applied to the receiver.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @return {object} the extended object
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots */
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.aggregate = function(r, s, ov, wl) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots return Y.mix(r, s, ov, wl, 0, true);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots };
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots /**
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * Utility to set up the prototype, constructor and superclass properties to
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * support an inheritance strategy that can chain constructors and methods.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * Static members will not be inherited.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots *
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @method extend
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param {Function} r the object to modify
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param {Function} s the object to inherit
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param {Object} px prototype properties to add/override
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param {Object} sx static properties to add/override
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @return {YUI} the YUI instance
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots */
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.extend = function(r, s, px, sx) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (!s||!r) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // @TODO error symbols
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.error("extend failed, verify dependencies");
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots var sp = s.prototype, rp=Y.Object(sp);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots r.prototype=rp;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots rp.constructor=r;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots r.superclass=sp;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // assign constructor property
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (s != Object && sp.constructor == OP.constructor) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots sp.constructor=s;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // add prototype overrides
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (px) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.mix(rp, px, true);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // add object overrides
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (sx) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.mix(r, sx, true);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots return r;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots };
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots /**
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * Executes the supplied function for each item in
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * a collection. Supports arrays, objects, and
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * Y.NodeLists
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @method each
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param o the object to iterate
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param f the function to execute. This function
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * receives the value, key, and object as parameters
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param proto if true, prototype properties are
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * iterated on objects
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @return {YUI} the YUI instance
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots */
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.each = function(o, f, c, proto) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return dispatch(o, f, c, proto, EACH);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots /*
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * Executes the supplied function for each item in
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * a collection. The operation stops if the function
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * returns true. Supports arrays, objects, and
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * Y.NodeLists.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @method some
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param o the object to iterate
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param f the function to execute. This function
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * receives the value, key, and object as parameters
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param proto if true, prototype properties are
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * iterated on objects
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @return {boolean} true if the function ever returns true, false otherwise
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots */
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots Y.some = function(o, f, c, proto) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return dispatch(o, f, c, proto, SOME);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots /**
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * Deep obj/array copy. Function clones are actually
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * wrappers around the original function.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * Array-like objects are treated as arrays.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * Primitives are returned untouched. Optionally, a
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * function can be provided to handle other data types,
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * filter keys, validate values, etc.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots *
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @method clone
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param o what to clone
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param safe {boolean} if true, objects will not have prototype
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * items from the source. If false, they will. In this case, the
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * original is initially protected, but the clone is not completely immune
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * from changes to the source object prototype. Also, cloned prototype
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * items that are deleted from the clone will result in the value
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * of the source prototype being exposed. If operating on a non-safe
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * clone, items should be nulled out rather than deleted.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @param f optional function to apply to each item in a collection;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * it will be executed prior to applying the value to
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * the new object. Return false to prevent the copy.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param c optional execution context for f
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param owner Owner object passed when clone is iterating an
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * object. Used to set up context for cloned functions.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @return {Array|Object} the cloned object
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots */
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots Y.clone = function(o, safe, f, c, owner, cloned) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (!L.isObject(o)) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots return o;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots var o2, marked = cloned || {}, stamp,
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots each = Y.each || Y.Object.each;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots switch (L.type(o)) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots case 'date':
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots return new Date(o);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots case 'regexp':
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots // return new RegExp(o.source); // if we do this we need to set the flags too
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots return o;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots case 'function':
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots o2 = Y.bind(o, owner);
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots break;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots case 'array':
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots o2 = [];
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots break;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots default:
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots // #2528250 only one clone of a given object should be created.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (o[CLONE_MARKER]) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return marked[o[CLONE_MARKER]];
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots stamp = Y.guid();
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots o2 = (safe) ? {} : Y.Object(o);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots o[CLONE_MARKER] = stamp;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots marked[stamp] = o;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots // #2528250 don't try to clone element properties
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots if (!o.addEventListener && !o.attachEvent) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots each(o, function(v, k) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots if (!f || (f.call(c || this, v, k, this, o) !== false)) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots if (k !== CLONE_MARKER) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots if (k == 'prototype') {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots // skip the prototype
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots } else if (o[k] === o) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots this[k] = this;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots } else {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots this[k] = Y.clone(v, safe, f, c, owner || o, marked);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }, o2);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots if (!cloned) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.Object.each(marked, function(v, k) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots delete v[CLONE_MARKER];
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots });
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots marked = null;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots }
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return o2;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots /**
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * Returns a function that will execute the supplied function in the
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * supplied object's context, optionally adding any additional
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * supplied parameters to the beginning of the arguments collection the
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * supplied to the function.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots *
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * @method bind
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param f {Function|String} the function to bind, or a function name
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * to execute on the context object
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param c the execution context
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param args* 0..n arguments to include before the arguments the
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * function is executed with.
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @return {function} the wrapped function
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots */
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots Y.bind = function(f, c) {
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return function () {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots var fn = L.isString(f) ? c[f] : f,
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots args = (xargs) ? xargs.concat(Y.Array(arguments, 0, true)) : arguments;
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots return fn.apply(c || fn, args);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots /**
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * Returns a function that will execute the supplied function in the
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * supplied object's context, optionally adding any additional
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots * supplied parameters to the end of the arguments the function
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * is executed with.
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots *
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @method rbind
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param f {Function|String} the function to bind, or a function name
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * to execute on the context object
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param c the execution context
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @param args* 0..n arguments to append to the end of arguments collection
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * supplied to the function
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots * @return {function} the wrapped function
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots */
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots Y.rbind = function(f, c) {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots return function () {
5f40f927dba3cf399373572f6ed6fe59a376376eTodd Kloots var fn = L.isString(f) ? c[f] : f,
de413b3e25c9cba63ab4b3003f5a4524d49f9f05Todd Kloots args = (xargs) ? Y.Array(arguments, 0, true).concat(xargs) : arguments;
de413b3e25c9cba63ab4b3003f5a4524d49f9f05Todd Kloots return fn.apply(c || fn, args);
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots };
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots}, '@VERSION@' );
9a2430d08e4d1b8b870cd3ba6c17ffc7881d16a6Todd Kloots