1494N/A/**
1494N/AThe YUI module contains the components required for building the YUI seed file.
1494N/AThis includes the script loading mechanism, a simple queue, and the core
1494N/Autilities for the library.
1494N/A
1494N/A@module yui
1494N/A@submodule yui-base
1494N/A**/
1494N/A
1494N/Avar CACHED_DELIMITER = '__',
1494N/A
1494N/A hasOwn = Object.prototype.hasOwnProperty,
1494N/A isObject = Y.Lang.isObject;
1494N/A
1494N/A/**
1494N/AReturns a wrapper for a function which caches the return value of that function,
1494N/Akeyed off of the combined string representation of the argument values provided
1494N/Awhen the wrapper is called.
1494N/A
1494N/ACalling this function again with the same arguments will return the cached value
1494N/Arather than executing the wrapped function.
1494N/A
1494N/ANote that since the cache is keyed off of the string representation of arguments
1494N/Apassed to the wrapper function, arguments that aren't strings and don't provide
1494N/Aa meaningful `toString()` method may result in unexpected caching behavior. For
1494N/Aexample, the objects `{}` and `{foo: 'bar'}` would both be converted to the
1494N/Astring `[object Object]` when used as a cache key.
1494N/A
1494N/A@method cached
1494N/A@param {Function} source The function to memoize.
1494N/A@param {Object} [cache={}] Object in which to store cached values. You may seed
1494N/A this object with pre-existing cached values if desired.
1494N/A@param {any} [refetch] If supplied, this value is compared with the cached value
1494N/A using a `==` comparison. If the values are equal, the wrapped function is
1494N/A executed again even though a cached value exists.
1494N/A@return {Function} Wrapped function.
1494N/A@for YUI
1494N/A**/
1494N/AY.cached = function (source, cache, refetch) {
1494N/A cache || (cache = {});
1494N/A
1494N/A return function (arg) {
1494N/A var key = arguments.length > 1 ?
1494N/A Array.prototype.join.call(arguments, CACHED_DELIMITER) :
1494N/A String(arg);
1494N/A
1494N/A if (!(key in cache) || (refetch && cache[key] == refetch)) {
1494N/A cache[key] = source.apply(source, arguments);
1494N/A }
1494N/A
1494N/A return cache[key];
1494N/A };
1494N/A};
1494N/A
1494N/A/**
1494N/AReturns the `location` object from the window/frame in which this YUI instance
1494N/Aoperates, or `undefined` when executing in a non-browser environment
1494N/A(e.g. Node.js).
1494N/A
1494N/AIt is _not_ recommended to hold references to the `window.location` object
1494N/Aoutside of the scope of a function in which its properties are being accessed or
1494N/Aits methods are being called. This is because of a nasty bug/issue that exists
1494N/Ain both Safari and MobileSafari browsers:
1494N/A[WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
1494N/A
1494N/A@method getLocation
1494N/A@return {location} The `location` object from the window/frame in which this YUI
1494N/A instance operates.
1494N/A@since 3.5.0
1494N/A**/
1494N/AY.getLocation = function () {
1577N/A // It is safer to look this up every time because yui-base is attached to a
1577N/A // YUI instance before a user's config is applied; i.e. `Y.config.win` does
1494N/A // not point the correct window object when this file is loaded.
1494N/A var win = Y.config.win;
1494N/A
1494N/A // It is not safe to hold a reference to the `location` object outside the
1494N/A // scope in which it is being used. The WebKit engine used in Safari and
1494N/A // MobileSafari will "disconnect" the `location` object from the `window`
1494N/A // when a page is restored from back/forward history cache.
1494N/A return win && win.location;
1494N/A};
1494N/A
1494N/A/**
1494N/AReturns a new object containing all of the properties of all the supplied
1494N/Aobjects. The properties from later objects will overwrite those in earlier
1494N/Aobjects.
1494N/A
1494N/APassing in a single object will create a shallow copy of it. For a deep copy,
1494N/Ause `clone()`.
1494N/A
1494N/A@method merge
1494N/A@param {Object} objects* One or more objects to merge.
1494N/A@return {Object} A new merged object.
1494N/A**/
1494N/AY.merge = function () {
1494N/A var args = arguments,
1494N/A i = 0,
1494N/A len = args.length,
1494N/A result = {};
1494N/A
1494N/A for (; i < len; ++i) {
1494N/A Y.mix(result, args[i], true);
1494N/A }
1494N/A
1494N/A return result;
1494N/A};
1494N/A
1494N/A/**
1494N/AMixes _supplier_'s properties into _receiver_.
1494N/A
1494N/AProperties on _receiver_ or _receiver_'s prototype will not be overwritten or
1494N/Ashadowed unless the _overwrite_ parameter is `true`, and will not be merged
1494N/Aunless the _merge_ parameter is `true`.
1494N/A
1494N/AIn the default mode (0), only properties the supplier owns are copied (prototype
1494N/Aproperties are not copied). The following copying modes are available:
1494N/A
1494N/A * `0`: _Default_. Object to object.
1494N/A * `1`: Prototype to prototype.
1494N/A * `2`: Prototype to prototype and object to object.
1494N/A * `3`: Prototype to object.
1494N/A * `4`: Object to prototype.
1494N/A
1494N/A@method mix
1494N/A@param {Function|Object} receiver The object or function to receive the mixed
1494N/A properties.
1494N/A@param {Function|Object} supplier The object or function supplying the
1494N/A properties to be mixed.
1494N/A@param {Boolean} [overwrite=false] If `true`, properties that already exist
1494N/A on the receiver will be overwritten with properties from the supplier.
1494N/A@param {String[]} [whitelist] An array of property names to copy. If
1494N/A specified, only the whitelisted properties will be copied, and all others
1494N/A will be ignored.
1494N/A@param {Number} [mode=0] Mix mode to use. See above for available modes.
1494N/A@param {Boolean} [merge=false] If `true`, objects and arrays that already
1494N/A exist on the receiver will have the corresponding object/array from the
1494N/A supplier merged into them, rather than being skipped or overwritten. When
1494N/A both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
1494N/A@return {Function|Object|YUI} The receiver, or the YUI instance if the
1496N/A specified receiver is falsy.
1494N/A**/
1494N/AY.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
1494N/A var alwaysOverwrite, exists, from, i, key, len, to;
// If no supplier is given, we return the receiver. If no receiver is given,
// we return Y. Returning Y doesn't make much sense to me, but it's
// grandfathered in for backcompat reasons.
if (!receiver || !supplier) {
return receiver || Y;
}
if (mode) {
// In mode 2 (prototype to prototype and object to object), we recurse
// once to do the proto to proto mix. The object to object mix will be
// handled later on.
if (mode === 2) {
Y.mix(receiver.prototype, supplier.prototype, overwrite,
whitelist, 0, merge);
}
// Depending on which mode is specified, we may be copying from or to
// the prototypes of the supplier and receiver.
from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
// If either the supplier or receiver doesn't actually have a
// prototype property, then we could end up with an undefined `from`
// or `to`. If that happens, we abort and return the receiver.
if (!from || !to) {
return receiver;
}
} else {
from = supplier;
to = receiver;
}
// If `overwrite` is truthy and `merge` is falsy, then we can skip a
// property existence check on each iteration and save some time.
alwaysOverwrite = overwrite && !merge;
if (whitelist) {
for (i = 0, len = whitelist.length; i < len; ++i) {
key = whitelist[i];
// We call `Object.prototype.hasOwnProperty` instead of calling
// `hasOwnProperty` on the object itself, since the object's
// `hasOwnProperty` method may have been overridden or removed.
// Also, some native objects don't implement a `hasOwnProperty`
// method.
if (!hasOwn.call(from, key)) {
continue;
}
// The `key in to` check here is (sadly) intentional for backwards
// compatibility reasons. It prevents undesired shadowing of
// prototype members on `to`.
exists = alwaysOverwrite ? false : key in to;
if (merge && exists && isObject(to[key], true)
&& isObject(from[key], true)) {
// If we're in merge mode, and the key is present on both
// objects, and the value on both objects is either an object or
// an array (but not a function), then we recurse to merge the
// `from` value into the `to` value instead of overwriting it.
//
// Note: It's intentional that the whitelist isn't passed to the
// recursive call here. This is legacy behavior that lots of
// code still depends on.
Y.mix(to[key], from[key], overwrite, null, 0, merge);
} else if (overwrite || !exists) {
// We're not in merge mode, so we'll only copy the `from` value
// to the `to` value if we're in overwrite mode or if the
// current key doesn't exist on the `to` object.
to[key] = from[key];
}
}
} else {
for (key in from) {
// The code duplication here is for runtime performance reasons.
// Combining whitelist and non-whitelist operations into a single
// loop or breaking the shared logic out into a function both result
// in worse performance, and Y.mix is critical enough that the byte
// tradeoff is worth it.
if (!hasOwn.call(from, key)) {
continue;
}
// The `key in to` check here is (sadly) intentional for backwards
// compatibility reasons. It prevents undesired shadowing of
// prototype members on `to`.
exists = alwaysOverwrite ? false : key in to;
if (merge && exists && isObject(to[key], true)
&& isObject(from[key], true)) {
Y.mix(to[key], from[key], overwrite, null, 0, merge);
} else if (overwrite || !exists) {
to[key] = from[key];
}
}
// If this is an IE browser with the JScript enumeration bug, force
// enumeration of the buggy properties by making a recursive call with
// the buggy properties as the whitelist.
if (Y.Object._hasEnumBug) {
Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
}
}
return receiver;
};