# Yahoo! UI Library

### yui 3.3.0

Yahoo! UI Library > yui > yui-core.js (source view)
Search:
Filters Show Private Show Protected Show Deprecated

    /**
     * The YUI module contains the components required for building the YUI
     * seed file.  This includes the script loading mechanism, a simple queue,
     * and the core utilities for the library.
     * @module yui
     * @submodule yui-base
     */

    var CACHED_DELIMITER = '__',

    /*
     * IE will not enumerate native functions in a derived object even if the
     * function was overridden.  This is a workaround for specific functions
     * we care about on the Object prototype.
     * @property _iefix
     * @for YUI
     * @param {Function} r  the object to receive the augmentation
     * @param {Function} s  the object that supplies the properties to augment
     * @private
     */
    _iefix = function(r, s) {
        var fn = s.toString;
        if (Y.Lang.isFunction(fn) && fn != Object.prototype.toString) {
            r.toString = fn;
        }
    };

    /**
     * Returns a new object containing all of the properties of
     * all the supplied objects.  The properties from later objects
     * will overwrite those in earlier objects.  Passing in a
     * single object will create a shallow copy of it.  For a deep
     * copy, use clone.
     * @method merge
     * @for YUI
     * @param arguments {Object*} the objects to merge.
     * @return {object} the new merged object.
     */
    Y.merge = function() {
        var a = arguments, o = {}, i, l = a.length;
        for (i = 0; i < l; i = i + 1) {
            Y.mix(o, a[i], true);
        }
        return o;
    };

    /**
     * Applies the supplier's properties to the receiver.  By default
     * all prototype and static propertes on the supplier are applied
     * to the corresponding spot on the receiver.  By default all
     * properties are applied, and a property that is already on the
     * reciever will not be overwritten.  The default behavior can
     * be modified by supplying the appropriate parameters.
     *
     * @todo add constants for the modes
     *
     * @method mix
     * @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 {int} mode what should be copies, and to where
     *        default(0): object to object
     *        1: prototype to prototype (old augment)
     *        2: prototype to prototype and object props (new augment)
     *        3: prototype to object
     *        4: object to prototype.
     * @param merge {boolean/int} merge objects instead of overwriting/ignoring.
     * A value of 2 will skip array merge
     * Used by Y.aggregate.
     * @return {object} the augmented object.
     */
    Y.mix = function(r, s, ov, wl, mode, merge) {

        if (!s || !r) {
            return r || Y;
        }

        if (mode) {
            switch (mode) {
                case 1: // proto to proto
                    return Y.mix(r.prototype, s.prototype, ov, wl, 0, merge);
                case 2: // object to object and proto to proto
                    Y.mix(r.prototype, s.prototype, ov, wl, 0, merge);
                    break; // pass through
                case 3: // proto to static
                    return Y.mix(r, s.prototype, ov, wl, 0, merge);
                case 4: // static to proto
                    return Y.mix(r.prototype, s, ov, wl, 0, merge);
                default:  // object to object is what happens below
            }
        }

        // Maybe don't even need this wl && wl.length check anymore??
        var i, l, p, type;

        if (wl && wl.length) {
            for (i = 0, l = wl.length; i < l; ++i) {
                p = wl[i];
                type = Y.Lang.type(r[p]);
                if (s.hasOwnProperty(p)) {
                    if (merge && type == 'object') {
                        Y.mix(r[p], s[p]);
                    } else if (ov || !(p in r)) {
                        r[p] = s[p];
                    }
                }
            }
        } else {
            for (i in s) {
                // if (s.hasOwnProperty(i) && !(i in FROZEN)) {
                if (s.hasOwnProperty(i)) {
                    // check white list if it was supplied
                    // if the receiver has this property, it is an object,
                    // and merge is specified, merge the two objects.
                    if (merge && Y.Lang.isObject(r[i], true)) {
                        Y.mix(r[i], s[i], ov, wl, 0, true); // recursive
                    // otherwise apply the property only if overwrite
                    // is specified or the receiver doesn't have one.
                    } else if (ov || !(i in r)) {
                        r[i] = s[i];
                    }
                    // if merge is specified and the receiver is an array,
                    // append the array item
                    // } else if (arr) {
                        // r.push(s[i]);
                    // }
                }
            }

            if (Y.UA.ie) {
                _iefix(r, s);
            }
        }

        return r;
    };

    /**
     * Returns a wrapper for a function which caches the
     * return value of that function, keyed off of the combined
     * argument values.
     * @method cached
     * @param source {function} the function to memoize.
     * @param cache an optional cache seed.
     * @param refetch if supplied, this value is tested against the cached
     * value.  If the values are equal, the wrapped function is executed again.
     * @return {Function} the wrapped function.
     */
    Y.cached = function(source, cache, refetch) {
        cache = cache || {};

        return function(arg1) {

            var k = (arguments.length > 1) ?
                Array.prototype.join.call(arguments, CACHED_DELIMITER) : arg1;

            if (!(k in cache) || (refetch && cache[k] == refetch)) {
                cache[k] = source.apply(source, arguments);
            }

            return cache[k];
        };

    };

Copyright © 2011 Yahoo! Inc. All rights reserved.