2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
8
* OOP utils. If included, the OOP methods are added to the YUI instance
11
YUI.add("oop", function(Y) {
15
OP = Object.prototype,
19
* The following methods are added to the YUI instance
24
* Applies prototype properties from the supplier to the receiver.
25
* The receiver can be a constructor or an instance.
27
* @param {Function} r the object to receive the augmentation
28
* @param {Function} s the object that supplies the properties to augment
29
* @param ov {boolean} if true, properties already on the receiver
30
* will be overwritten if found on the supplier.
31
* @param wl {string[]} a whitelist. If supplied, only properties in
32
* this list will be applied to the receiver.
33
* @param args {Array | Any} arg or arguments to apply to the supplier
34
* constructor when initializing.
35
* @return {object} the augmented object
37
* @todo constructor optional?
38
* @todo understanding what an instance is augmented with
39
* @TODO evaluate if we can do this in a way that doesn't interfere
40
* with normal inheritance
42
Y.augment = function(r, s, ov, wl, args) {
44
var sProto = s.prototype, newProto = null, construct = s,
45
a = (args) ? Y.Array(args) : [], rProto = r.prototype,
46
target = rProto || r, applyConstructor = false;
48
// working on a class, so apply constructor infrastructure
49
if (rProto && construct) {
52
// Y.Do.before(r, construct);
54
var sequestered = {}, replacements = {};
57
// sequester all of the functions in the supplier and replace with
58
// one that will restore all of them.
59
Y.each(sProto, function(v, k) {
62
// var initialized = false;
64
replacements[k] = function() {
69
// overwrite the prototype with all of the sequestered functions,
70
// but only if it hasn't been overridden
71
for (var i in sequestered) {
72
if (Y.Object.owns(sequestered, i) && (me[i] === replacements[i])) {
73
me[i] = sequestered[i];
77
// apply the constructor
78
construct.apply(me, a);
80
// apply the original sequestered function
81
return sequestered[k].apply(me, arguments);
85
if ((!wl || (k in wl)) && (ov || !(k in this))) {
88
if (L.isFunction(v)) {
90
// sequester the function
93
// replace the sequestered function with a function that will
94
// restore all sequestered functions and exectue the constructor.
95
this[k] = replacements[k];
107
// augmenting an instance, so apply the constructor immediately
109
applyConstructor = true;
112
Y.mix(target, newProto || sProto, ov, wl);
114
if (applyConstructor) {
122
* Applies object properties from the supplier to the receiver. If
123
* the target has the property, and the property is an object, the target
124
* object will be augmented with the supplier's value. If the property
125
* is an array, the suppliers value will be appended to the target.
127
* @param {Function} r the object to receive the augmentation
128
* @param {Function} s the object that supplies the properties to augment
129
* @param ov {boolean} if true, properties already on the receiver
130
* will be overwritten if found on the supplier.
131
* @param wl {string[]} a whitelist. If supplied, only properties in
132
* this list will be applied to the receiver.
133
* @return {object} the extended object
135
Y.aggregate = function(r, s, ov, wl) {
136
return Y.mix(r, s, ov, wl, 0, true);
140
* Utility to set up the prototype, constructor and superclass properties to
141
* support an inheritance strategy that can chain constructors and methods.
142
* Static members will not be inherited.
145
* @param {Function} r the object to modify
146
* @param {Function} s the object to inherit
147
* @param {Object} px prototype properties to add/override
148
* @param {Object} sx static properties to add/override
149
* @return {YUI} the YUI instance
151
Y.extend = function(r, s, px, sx) {
153
Y.fail("extend failed, verify dependencies");
156
var sp = s.prototype, rp=Y.Object(sp), i;
162
// If the superclass doesn't have a standard constructor,
163
// define one so that Super() works
164
if (s != Object && sp.constructor == OP.constructor) {
168
// Add object properties too
169
// @TODO removed for now because it isn't that useful and
170
// has caused a few issues overwriting things that should
171
// not be. You can do this manually if needed. Revisit
172
// if this is something that really is needed for some
176
// Add superclass convienience functions
177
// @TODO revisit when we have something that works
178
// Y.augment(r, Ext);
180
// Add prototype overrides
185
// Add object overrides
194
* Executes the supplied function for each item in
195
* a collection. Supports arrays, objects, and
198
* @param o the object to iterate
199
* @param f the function to execute. This function
200
* receives the value, key, and object as parameters
201
* @param proto if true, prototype properties are
202
* iterated on objects
203
* @return {YUI} the YUI instance
205
Y.each = function(o, f, c, proto) {
207
if (o.each && o.item) {
208
return o.each.call(o, f, c);
212
return A.each(o, f, c);
214
return A.each(Y.Array(o, 0, true), f, c);
216
return Y.Object.each(o, f, c, proto);
220
// return Y.Object.each(o, f, c);
224
* Deep obj/array copy. Functions will are cloned with Y.bind.
225
* Array-like objects are treated as arrays.
226
* primitives are returned untouched. Optionally a
227
* function can be provided to handle other data types,
228
* filter keys, validate values, etc.
231
* @param o what to clone
232
* @param safe {boolean} if true, objects will not have prototype
233
* items from the source. If false, it does. In this case, the
234
* original is initally protected, but the clone is not completely immune
235
* from changes to the source object prototype. Also, cloned prototype
236
* items that are deleted from the clone will result in the value
237
* of the source prototype to be exposed. If operating on a non-safe
238
* clone, items should be nulled out rather than deleted.
240
* @param f optional function to apply to each item in a collection
241
* it will be executed prior to applying the value to
242
* the new object. Return false to prevent the copy.
243
* @param c optional execution context for f
244
* @param owner Owner object passed when clone is iterating an
245
* object. Used to set up context for cloned functions.
246
* @return {Array|Object} the cloned object
248
Y.clone = function(o, safe, f, c, owner) {
250
if (!L.isObject(o)) {
258
var func = L.isFunction(o), o2;
261
if (o instanceof RegExp) {
262
return new RegExp(o.source);
264
o2 = Y.bind(o, owner);
266
o2 = (safe) ? {} : Y.Object(o);
269
Y.each(o, function(v, k) {
270
if (!f || (f.call(c || this, v, k, this, o) !== false)) {
271
this[k] = Y.clone(v, safe, f, c, this);
279
* Returns a function that will execute the supplied function in the
280
* supplied object's context, optionally adding any additional
281
* supplied parameters to the end of the arguments the function
284
* In some cases it is preferable to have the additional arguments
285
* applied to the beginning of the function signature. For instance,
286
* FireFox setTimeout/setInterval supplies a parameter that other
288
* Note: YUI provides a later() function which wraps setTimeout/setInterval,
289
* providing context adjustment and parameter addition. This can be
290
* used instead of setTimeout/setInterval, avoiding the arguments
291
* collection issue when using bind() in FireFox.
293
* @TODO review param order for PR2
295
* @param f {Function} the function to bind
296
* @param c the execution context
297
* @param args* 0..n arguments to append to the end of arguments collection
298
* supplied to the function
299
* @return {function} the wrapped function
301
Y.bind = function(f, c) {
302
var a = Y.Array(arguments, 2, true);
304
return f.apply(c || f, Y.Array(arguments, 0, true).concat(a));
309
* Returns a function that will execute the supplied function in the
310
* supplied object's context, optionally adding any additional
311
* supplied parameters to the beginning of the arguments collection the
312
* supplied to the function.
314
* In some cases it is preferable to have the additional arguments
315
* applied to the end of the function signature. @see bind for a version
318
* @TODO consider adding this in PR2
321
* @param f {Function} the function to bind
322
* @param c the execution context
323
* @param args* 0..n arguments to append to the arguments collection for the function
324
* @return {function} the wrapped function
326
// Y.rbind = function(f, c) {
327
// var a = Y.Array(arguments, 2, true);
328
// return function () {
329
// return f.apply(c || f, a.concat(Y.Array(arguments, 0, true)));