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