# Yahoo! UI Library

### yui 3.3.0

Yahoo! UI Library > yui > yui.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
     */

    if (typeof YUI != 'undefined') {
        YUI._YUI = YUI;
    }

    /**
     * The YUI global namespace object.  If YUI is already defined, the
     * existing YUI object will not be overwritten so that defined
     * namespaces are preserved.  It is the constructor for the object
     * the end user interacts with.  As indicated below, each instance
     * has full custom event support, but only if the event system
     * is available.  This is a self-instantiable factory function.  You
     * can invoke it directly like this:
     *
     * YUI().use('*', function(Y) {
     *   // ready
     * });
     *
     * But it also works like this:
     *
     * var Y = YUI();
     *
     * @class YUI
     * @constructor
     * @global
     * @uses EventTarget
     * @param o* {object} 0..n optional configuration objects.  these values
     * are store in Y.config.  See config for the list of supported
     * properties.
     */
        /*global YUI*/
        /*global YUI_config*/
        var YUI = function() {
            var i = 0,
                Y = this,
                args = arguments,
                l = args.length,
                instanceOf = function(o, type) {
                    return (o && o.hasOwnProperty && (o instanceof type));
                },
                gconf = (typeof YUI_config !== 'undefined') && YUI_config;

            if (!(instanceOf(Y, YUI))) {
                Y = new YUI();
            } else {
                // set up the core environment
                Y._init();

                // YUI.GlobalConfig is a master configuration that might span
                // multiple contexts in a non-browser environment.  It is applied
                // first to all instances in all contexts.
                if (YUI.GlobalConfig) {
                    Y.applyConfig(YUI.GlobalConfig);
                }

                // YUI_Config is a page-level config.  It is applied to all
                // instances created on the page.  This is applied after
                // YUI.GlobalConfig, and before the instance level configuration
                // objects.
                if (gconf) {
                    Y.applyConfig(gconf);
                }

                // bind the specified additional modules for this instance
                if (!l) {
                    Y._setup();
                }
            }

            if (l) {
                // Each instance can accept one or more configuration objects.
                // These are applied after YUI.GlobalConfig and YUI_Config,
                // overriding values set in those config files if there is a '
                // matching property.
                for (; i < l; i++) {
                    Y.applyConfig(args[i]);
                }

                Y._setup();
            }

            Y.instanceOf = instanceOf;

            return Y;
        };

    (function() {

        var proto, prop,
            VERSION = '@VERSION@',
            PERIOD = '.',
            BASE = 'http://yui.yahooapis.com/',
            DOC_LABEL = 'yui3-js-enabled',
            NOOP = function() {},
            SLICE = Array.prototype.slice,
            APPLY_TO_AUTH = { 'io.xdrReady': 1,   // the functions applyTo
                              'io.xdrResponse': 1,   // can call. this should
                              'SWF.eventHandler': 1 }, // be done at build time
            hasWin = (typeof window != 'undefined'),
            win = (hasWin) ? window : null,
            doc = (hasWin) ? win.document : null,
            docEl = doc && doc.documentElement,
            docClass = docEl && docEl.className,
            instances = {},
            time = new Date().getTime(),
            add = function(el, type, fn, capture) {
                if (el && el.addEventListener) {
                    el.addEventListener(type, fn, capture);
                } else if (el && el.attachEvent) {
                    el.attachEvent('on' + type, fn);
                }
            },
            remove = function(el, type, fn, capture) {
                if (el && el.removeEventListener) {
                    // this can throw an uncaught exception in FF
                    try {
                        el.removeEventListener(type, fn, capture);
                    } catch (ex) {}
                } else if (el && el.detachEvent) {
                    el.detachEvent('on' + type, fn);
                }
            },
            handleLoad = function() {
                YUI.Env.windowLoaded = true;
                YUI.Env.DOMReady = true;
                if (hasWin) {
                    remove(window, 'load', handleLoad);
                }
            },
            getLoader = function(Y, o) {
                var loader = Y.Env._loader;
                if (loader) {
                    loader.ignoreRegistered = false;
                    loader.onEnd = null;
                    loader.data = null;
                    loader.required = [];
                    loader.loadType = null;
                } else {
                    loader = new Y.Loader(Y.config);
                    Y.Env._loader = loader;
                }

                return loader;
            },

            clobber = function(r, s) {
                for (var i in s) {
                    if (s.hasOwnProperty(i)) {
                        r[i] = s[i];
                    }
                }
            },

            ALREADY_DONE = { success: true };

    //  Stamp the documentElement (HTML) with a class of "yui-loaded" to
    //  enable styles that need to key off of JS being enabled.
    if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
        if (docClass) {
            docClass += ' ';
        }
        docClass += DOC_LABEL;
        docEl.className = docClass;
    }

    if (VERSION.indexOf('@') > -1) {
        VERSION = '3.2.0'; // dev time hack for cdn test
    }

    proto = {
        /**
         * Applies a new configuration object to the YUI instance config.
         * This will merge new group/module definitions, and will also
         * update the loader cache if necessary.  Updating Y.config directly
         * will not update the cache.
         * @method applyConfig
         * @param {object} the configuration object.
         * @since 3.2.0
         */
        applyConfig: function(o) {

            o = o || NOOP;

            var attr,
                name,
                // detail,
                config = this.config,
                mods = config.modules,
                groups = config.groups,
                rls = config.rls,
                loader = this.Env._loader;

            for (name in o) {
                if (o.hasOwnProperty(name)) {
                    attr = o[name];
                    if (mods && name == 'modules') {
                        clobber(mods, attr);
                    } else if (groups && name == 'groups') {
                        clobber(groups, attr);
                    } else if (rls && name == 'rls') {
                        clobber(rls, attr);
                    } else if (name == 'win') {
                        config[name] = attr.contentWindow || attr;
                        config.doc = config[name].document;
                    } else if (name == '_yuid') {
                        // preserve the guid
                    } else {
                        config[name] = attr;
                    }
                }
            }

            if (loader) {
                loader._config(o);
            }
        },

        _config: function(o) {
            this.applyConfig(o);
        },

        /**
         * Initialize this YUI instance
         * @private
         */
        _init: function() {
            var filter,
                Y = this,
                G_ENV = YUI.Env,
                Env = Y.Env,
                prop;

            /**
             * The version number of the YUI instance.
             * @property version
             * @type string
             */
            Y.version = VERSION;

            if (!Env) {
                Y.Env = {
                    mods: {}, // flat module map
                    versions: {}, // version module map
                    base: BASE,
                    cdn: BASE + VERSION + '/build/',
                    // bootstrapped: false,
                    _idx: 0,
                    _used: {},
                    _attached: {},
                    _yidx: 0,
                    _uidx: 0,
                    _guidp: 'y',
                    _loaded: {},
                    serviced: {},
                    getBase: G_ENV && G_ENV.getBase ||

        function(srcPattern, comboPattern) {
            var b, nodes, i, src, match;
            // get from querystring
            nodes = (doc && doc.getElementsByTagName('script')) || [];
            for (i = 0; i < nodes.length; i = i + 1) {
                src = nodes[i].src;
                if (src) {

                    match = src.match(srcPattern);
                    b = match && match[1];
                    if (b) {
                        // this is to set up the path to the loader.  The file
                        // filter for loader should match the yui include.
                        filter = match[2];

                        if (filter) {
                            match = filter.indexOf('js');

                            if (match > -1) {
                                filter = filter.substr(0, match);
                            }
                        }

                        // extract correct path for mixed combo urls
                        // http://yuilibrary.com/projects/yui3/ticket/2528423
                        match = src.match(comboPattern);
                        if (match && match[3]) {
                            b = match[1] + match[3];
                        }

                        break;
                    }
                }
            }

            // use CDN default
            return b || Env.cdn;
        }
                };

                Env = Y.Env;

                Env._loaded[VERSION] = {};

                if (G_ENV && Y !== YUI) {
                    Env._yidx = ++G_ENV._yidx;
                    Env._guidp = ('yui_' + VERSION + '_' +
                                 Env._yidx + '_' + time).replace(/\./g, '_');
                } else if (YUI._YUI) {

                    G_ENV = YUI._YUI.Env;
                    Env._yidx += G_ENV._yidx;
                    Env._uidx += G_ENV._uidx;

                    for (prop in G_ENV) {
                        if (!(prop in Env)) {
                            Env[prop] = G_ENV[prop];
                        }
                    }

                    delete YUI._YUI;
                }

                Y.id = Y.stamp(Y);
                instances[Y.id] = Y;

            }

            Y.constructor = YUI;

            // configuration defaults
            Y.config = Y.config || {
                win: win,
                doc: doc,
                debug: true,
                useBrowserConsole: true,
                throwFail: true,
                bootstrap: true,
                cacheUse: true,
                fetchCSS: true
            };

            Y.config.base = YUI.config.base ||
                Y.Env.getBase(/^(.*)yui\/yui([\.\-].*)js(\?.*)?$/,
                              /^(.*\?)(.*\&)(.*)yui\/yui[\.\-].*js(\?.*)?$/);

            if (!filter || (!('-min.-debug.').indexOf(filter))) {
                filter = '-min.';
            }

            Y.config.loaderPath = YUI.config.loaderPath ||
                'loader/loader' + (filter || '-min.') + 'js';

        },

        /**
         * Finishes the instance setup. Attaches whatever modules were defined
         * when the yui modules was registered.
         * @method _setup
         * @private
         */
        _setup: function(o) {
            var i, Y = this,
                core = [],
                mods = YUI.Env.mods,
                extras = Y.config.core || ['get',
                                            'rls',
                                            'intl-base',
                                            'loader',
                                            'yui-log',
                                            'yui-later',
                                            'yui-throttle'];

            for (i = 0; i < extras.length; i++) {
                if (mods[extras[i]]) {
                    core.push(extras[i]);
                }
            }

            Y._attach(['yui-base']);
            Y._attach(core);

            // Y.log(Y.id + ' initialized', 'info', 'yui');
        },

        /**
         * Executes a method on a YUI instance with
         * the specified id if the specified method is whitelisted.
         * @method applyTo
         * @param id {string} the YUI instance id.
         * @param method {string} the name of the method to exectute.
         * Ex: 'Object.keys'.
         * @param args {Array} the arguments to apply to the method.
         * @return {object} the return value from the applied method or null.
         */
        applyTo: function(id, method, args) {
            if (!(method in APPLY_TO_AUTH)) {
                this.log(method + ': applyTo not allowed', 'warn', 'yui');
                return null;
            }

            var instance = instances[id], nest, m, i;
            if (instance) {
                nest = method.split('.');
                m = instance;
                for (i = 0; i < nest.length; i = i + 1) {
                    m = m[nest[i]];
                    if (!m) {
                        this.log('applyTo not found: ' + method, 'warn', 'yui');
                    }
                }
                return m.apply(instance, args);
            }

            return null;
        },

        /**
         * Registers a module with the YUI global.  The easiest way to create a
         * first-class YUI module is to use the YUI component build tool.
         *
         * http://yuilibrary.com/projects/builder
         *
         * The build system will produce the YUI.add wrapper for you module, along
         * with any configuration info required for the module.
         * @method add
         * @param name {string} module name.
         * @param fn {Function} entry point into the module that
         * is used to bind module to the YUI instance.
         * @param version {string} version string.
         * @param details {object} optional config data:
         * requires: features that must be present before this module can be
         * attached.
         * optional: optional features that should be present if loadOptional
         * is defined.  Note: modules are not often loaded this way in YUI 3,
         * but this field is still useful to inform the user that certain
         * features in the component will require additional dependencies.
         * use: features that are included within this module which need to
         * be attached automatically when this module is attached.  This
         * supports the YUI 3 rollup system -- a module with submodules
         * defined will need to have the submodules listed in the 'use'
         * config.  The YUI component build tool does this for you.
         * @return {YUI} the YUI instance.
         *
         */
        add: function(name, fn, version, details) {
            details = details || {};
            var env = YUI.Env,
                mod = {
                    name: name,
                    fn: fn,
                    version: version,
                    details: details
                },
                loader,
                i, versions = env.versions;

            env.mods[name] = mod;
            versions[version] = versions[version] || {};
            versions[version][name] = mod;

            for (i in instances) {
                if (instances.hasOwnProperty(i)) {
                    loader = instances[i].Env._loader;
                    if (loader) {
                        if (!loader.moduleInfo[name]) {
                            loader.addModule(details, name);
                        }
                    }
                }
            }

            return this;
        },

        /**
         * Executes the function associated with each required
         * module, binding the module to the YUI instance.
         * @method _attach
         * @private
         */
        _attach: function(r, fromLoader) {
            var i, name, mod, details, req, use, after,
                mods = YUI.Env.mods,
                Y = this, j,
                done = Y.Env._attached,
                len = r.length, loader;

            // Y.log('attaching: ' + r, 'info', 'yui');

            for (i = 0; i < len; i++) {
                if (!done[r[i]]) {
                    name = r[i];
                    mod = mods[name];
                    if (!mod) {
                        loader = Y.Env._loader;

                        // Y.log('no js def for: ' + name, 'info', 'yui');

                        if (!loader || !loader.moduleInfo[name]) {
                            Y.message('NOT loaded: ' + name, 'warn', 'yui');
                        }
                    } else {
                        done[name] = true;
                        details = mod.details;
                        req = details.requires;
                        use = details.use;
                        after = details.after;

                        if (req) {
                            for (j = 0; j < req.length; j++) {
                                if (!done[req[j]]) {
                                    if (!Y._attach(req)) {
                                        return false;
                                    }
                                    break;
                                }
                            }
                        }

                        if (after) {
                            for (j = 0; j < after.length; j++) {
                                if (!done[after[j]]) {
                                    if (!Y._attach(after)) {
                                        return false;
                                    }
                                    break;
                                }
                            }
                        }

                        if (use) {
                            for (j = 0; j < use.length; j++) {
                                if (!done[use[j]]) {
                                    if (!Y._attach(use)) {
                                        return false;
                                    }
                                    break;
                                }
                            }
                        }

                        if (mod.fn) {
                            try {
                                mod.fn(Y, name);
                            } catch (e) {
                                Y.error('Attach error: ' + name, e, name);
                                return false;
                            }
                        }

                    }
                }
            }

            return true;
        },

        /**
         * Attaches one or more modules to the YUI instance.  When this
         * is executed, the requirements are analyzed, and one of
         * several things can happen:
         *
         * - All requirements are available on the page --  The modules
         *   are attached to the instance.  If supplied, the use callback
         *   is executed synchronously.
         *
         * - Modules are missing, the Get utility is not available OR
         *   the 'bootstrap' config is false -- A warning is issued about
         *   the missing modules and all available modules are attached.
         *
         * - Modules are missing, the Loader is not available but the Get
         *   utility is and boostrap is not false -- The loader is bootstrapped
         *   before doing the following....
         *
         * - Modules are missing and the Loader is available -- The loader
         *   expands the dependency tree and fetches missing modules.  When
         *   the loader is finshed the callback supplied to use is executed
         *   asynchronously.
         *
         * @param modules* {string} 1-n modules to bind (uses arguments array).
         * @param *callback {function} callback function executed when
         * the instance has the required functionality.  If included, it
         * must be the last parameter.
         * <code>
         * // loads and attaches drag and drop and its dependencies
         * YUI().use('dd', function(Y) &#123;&#125);
         * // attaches all modules that are available on the page
         * YUI().use('*', function(Y) &#123;&#125);
         * // intrinsic YUI gallery support (since 3.1.0)
         * YUI().use('gallery-yql', function(Y) &#123;&#125);
         * // intrinsic YUI 2in3 support (since 3.1.0)
         * YUI().use('yui2-datatable', function(Y) &#123;&#125);.
         * </code>
         *
         * @return {YUI} the YUI instance.
         */
        use: function() {
            var args = SLICE.call(arguments, 0),
                callback = args[args.length - 1],
                Y = this,
                key;

            // The last argument supplied to use can be a load complete callback
            if (Y.Lang.isFunction(callback)) {
                args.pop();
            } else {
                callback = null;
            }

            if (Y._loading) {
                Y._useQueue = Y._useQueue || new Y.Queue();
                Y._useQueue.add([args, callback]);
            } else {
                key = args.join();

                if (Y.config.cacheUse && Y.Env.serviced[key]) {
                    Y.log('already provisioned: ' + key, 'info', 'yui');
                    Y._notify(callback, ALREADY_DONE, args);
                } else {
                    Y._use(args, function(Y, response) {
                        if (Y.config.cacheUse) {
                            Y.log('caching request: ' + key, 'info', 'yui');
                            Y.Env.serviced[key] = true;
                        }
                        Y._notify(callback, response, args);
                    });
                }
            }

            return Y;
        },

        _notify: function(callback, response, args) {
            if (!response.success && this.config.loadErrorFn) {
                this.config.loadErrorFn.call(this, this, callback, response, args);
            } else if (callback) {
                try {
                    callback(this, response);
                } catch (e) {
                    this.error('use callback error', e, args);
                }
            }
        },

        _use: function(args, callback) {

            if (!this.Array) {
                this._attach(['yui-base']);
            }

            var len, loader, handleBoot,
                Y = this,
                G_ENV = YUI.Env,
                mods = G_ENV.mods,
                Env = Y.Env,
                used = Env._used,
                queue = G_ENV._loaderQueue,
                firstArg = args[0],
                YArray = Y.Array,
                config = Y.config,
                boot = config.bootstrap,
                missing = [],
                r = [],
                ret = true,
                fetchCSS = config.fetchCSS,
                process = function(names, skip) {

                    if (!names.length) {
                        return;
                    }

                    YArray.each(names, function(name) {

                        // add this module to full list of things to attach
                        if (!skip) {
                            r.push(name);
                        }

                        // only attach a module once
                        if (used[name]) {
                            return;
                        }

                        var m = mods[name], req, use;

                        if (m) {
                            used[name] = true;
                            req = m.details.requires;
                            use = m.details.use;
                        } else {
                            // CSS files don't register themselves, see if it has
                            // been loaded
                            if (!G_ENV._loaded[VERSION][name]) {
                                missing.push(name);
                            } else {
                                used[name] = true; // probably css
                            }
                        }

                        // make sure requirements are attached
                        if (req && req.length) {
                            process(req);
                        }

                        // make sure we grab the submodule dependencies too
                        if (use && use.length) {
                            process(use, 1);
                        }
                    });
                },

                handleLoader = function(fromLoader) {
                    var response = fromLoader || {
                            success: true,
                            msg: 'not dynamic'
                        },
                        redo, origMissing,
                        ret = true,
                        data = response.data;

                    Y._loading = false;

                    if (data) {
                        origMissing = missing;
                        missing = [];
                        r = [];
                        process(data);
                        redo = missing.length;
                        if (redo) {
                            if (missing.sort().join() ==
                                    origMissing.sort().join()) {
                                redo = false;
                            }
                        }
                    }

                    if (redo && data) {
                        Y._loading = false;
                        Y._use(args, function() {
                            Y.log('Nested use callback: ' + data, 'info', 'yui');
                            if (Y._attach(data)) {
                                Y._notify(callback, response, data);
                            }
                        });
                    } else {
                        if (data) {
                            // Y.log('attaching from loader: ' + data, 'info', 'yui');
                            ret = Y._attach(data);
                        }
                        if (ret) {
                            Y._notify(callback, response, args);
                        }
                    }

                    if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
                        Y._use.apply(Y, Y._useQueue.next());
                    }

                };

    // Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');

            // YUI().use('*'); // bind everything available
            if (firstArg === '*') {
                ret = Y._attach(Y.Object.keys(mods));
                if (ret) {
                    handleLoader();
                }
                return Y;
            }

            // Y.log('before loader requirements: ' + args, 'info', 'yui');

            // use loader to expand dependencies and sort the
            // requirements if it is available.
            if (boot && Y.Loader && args.length) {
                loader = getLoader(Y);
                loader.require(args);
                loader.ignoreRegistered = true;
                loader.calculate(null, (fetchCSS) ? null : 'js');
                args = loader.sorted;
            }

            // process each requirement and any additional requirements
            // the module metadata specifies
            process(args);

            len = missing.length;

            if (len) {
                missing = Y.Object.keys(YArray.hash(missing));
                len = missing.length;
    Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
            }

            // dynamic load
            if (boot && len && Y.Loader) {
    // Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
                Y.log('Using Loader', 'info', 'yui');
                Y._loading = true;
                loader = getLoader(Y);
                loader.onEnd = handleLoader;
                loader.context = Y;
                loader.data = args;
                loader.ignoreRegistered = false;
                loader.require(args);
                loader.insert(null, (fetchCSS) ? null : 'js');
                // loader.partial(missing, (fetchCSS) ? null : 'js');

            } else if (len && Y.config.use_rls) {

                // server side loader service
                Y.Get.script(Y._rls(args), {
                    onEnd: function(o) {
                        handleLoader(o);
                    },
                    data: args
                });

            } else if (boot && len && Y.Get && !Env.bootstrapped) {

                Y._loading = true;

                handleBoot = function() {
                    Y._loading = false;
                    queue.running = false;
                    Env.bootstrapped = true;
                    if (Y._attach(['loader'])) {
                        Y._use(args, callback);
                    }
                };

                if (G_ENV._bootstrapping) {
    Y.log('Waiting for loader', 'info', 'yui');
                    queue.add(handleBoot);
                } else {
                    G_ENV._bootstrapping = true;
    Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
                    Y.Get.script(config.base + config.loaderPath, {
                        onEnd: handleBoot
                    });
                }

            } else {
                Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
                ret = Y._attach(args);
                if (ret) {
                    handleLoader();
                }
            }

            return Y;
        },

        /**
         * Returns the namespace specified and creates it if it doesn't exist
         * <pre>
         * YUI.namespace("property.package");
         * YUI.namespace("YAHOO.property.package");
         * </pre>
         * Either of the above would create YUI.property, then
         * YUI.property.package (YAHOO is scrubbed out, this is
         * to remain compatible with YUI2)
         *
         * Be careful when naming packages. Reserved words may work in some browsers
         * and not others. For instance, the following will fail in Safari:
         * <pre>
         * YUI.namespace("really.long.nested.namespace");
         * </pre>
         * This fails because "long" is a future reserved word in ECMAScript
         *
         * @method namespace
         * @param  {string*} arguments 1-n namespaces to create.
         * @return {object}  A reference to the last namespace object created.
         */
        namespace: function() {
            var a = arguments, o = this, i = 0, j, d, arg;
            for (; i < a.length; i++) {
                // d = ('' + a[i]).split('.');
                arg = a[i];
                if (arg.indexOf(PERIOD)) {
                    d = arg.split(PERIOD);
                    for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
                        o[d[j]] = o[d[j]] || {};
                        o = o[d[j]];
                    }
                } else {
                    o[arg] = o[arg] || {};
                }
            }
            return o;
        },

        // this is replaced if the log module is included
        log: NOOP,
        message: NOOP,

        /**
         * Report an error.  The reporting mechanism is controled by
         * the 'throwFail' configuration attribute.  If throwFail is
         * not specified, the message is written to the Logger, otherwise
         * a JS error is thrown
         * @method error
         * @param msg {string} the error message.
         * @param e {Error|string} Optional JS error that was caught, or an error string.
         * @param data Optional additional info
         * and throwFail is specified, this error will be re-thrown.
         * @return {YUI} this YUI instance.
         */
        error: function(msg, e, data) {

            var Y = this, ret;

            if (Y.config.errorFn) {
                ret = Y.config.errorFn.apply(Y, arguments);
            }

            if (Y.config.throwFail && !ret) {
                throw (e || new Error(msg));
            } else {
                Y.message(msg, 'error'); // don't scrub this one
            }

            return Y;
        },

        /**
         * Generate an id that is unique among all YUI instances
         * @method guid
         * @param pre {string} optional guid prefix.
         * @return {string} the guid.
         */
        guid: function(pre) {
            var id = this.Env._guidp + (++this.Env._uidx);
            return (pre) ? (pre + id) : id;
        },

        /**
         * Returns a guid associated with an object.  If the object
         * does not have one, a new one is created unless readOnly
         * is specified.
         * @method stamp
         * @param o The object to stamp.
         * @param readOnly {boolean} if true, a valid guid will only
         * be returned if the object has one assigned to it.
         * @return {string} The object's guid or null.
         */
        stamp: function(o, readOnly) {
            var uid;
            if (!o) {
                return o;
            }

            // IE generates its own unique ID for dom nodes
            // The uniqueID property of a document node returns a new ID
            if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
                uid = o.uniqueID;
            } else {
                uid = (typeof o === 'string') ? o : o._yuid;
            }

            if (!uid) {
                uid = this.guid();
                if (!readOnly) {
                    try {
                        o._yuid = uid;
                    } catch (e) {
                        uid = null;
                    }
                }
            }
            return uid;
        },

        /**
         * Destroys the YUI instance
         * @method destroy
         * @since 3.3.0
         */
        destroy: function() {
            var Y = this;
            if (Y.Event) {
                Y.Event._unload();
            }
            delete instances[Y.id];
            delete Y.Env;
            delete Y.config;
        }

        /**
         * instanceof check for objects that works around
         * memory leak in IE when the item tested is
         * window/document
         * @method instanceOf
         * @since 3.3.0
         */
    };

        YUI.prototype = proto;

        // inheritance utilities are not available yet
        for (prop in proto) {
            if (proto.hasOwnProperty(prop)) {
                YUI[prop] = proto[prop];
            }
        }

        // set up the environment
        YUI._init();

        if (hasWin) {
            // add a window load event at load time so we can capture
            // the case where it fires before dynamic loading is
            // complete.
            add(window, 'load', handleLoad);
        } else {
            handleLoad();
        }

        YUI.Env.add = add;
        YUI.Env.remove = remove;

        /*global exports*/
        // Support the CommonJS method for exporting our single global
        if (typeof exports == 'object') {
            exports.YUI = YUI;
        }

    }());

    /**
     * The config object contains all of the configuration options for
     * the YUI instance.  This object is supplied by the implementer
     * when instantiating a YUI instance.  Some properties have default
     * values if they are not supplied by the implementer.  This should
     * not be updated directly because some values are cached.  Use
     * applyConfig() to update the config object on a YUI instance that
     * has already been configured.
     *
     * @class config
     * @static
     */

    /**
     * Allows the YUI seed file to fetch the loader component and library
     * metadata to dynamically load additional dependencies.
     *
     * @property bootstrap
     * @type boolean
     * @default true
     */

    /**
     * Log to the browser console if debug is on and the browser has a
     * supported console.
     *
     * @property useBrowserConsole
     * @type boolean
     * @default true
     */

    /**
     * A hash of log sources that should be logged.  If specified, only
     * log messages from these sources will be logged.
     *
     * @property logInclude
     * @type object
     */

    /**
     * A hash of log sources that should be not be logged.  If specified,
     * all sources are logged if not on this list.
     *
     * @property logExclude
     * @type object
     */

    /**
     * Set to true if the yui seed file was dynamically loaded in
     * order to bootstrap components relying on the window load event
     * and the 'domready' custom event.
     *
     * @property injected
     * @type boolean
     * @default false
     */

    /**
     * If throwFail is set, Y.error will generate or re-throw a JS Error.
     * Otherwise the failure is logged.
     *
     * @property throwFail
     * @type boolean
     * @default true
     */

    /**
     * The window/frame that this instance should operate in.
     *
     * @property win
     * @type Window
     * @default the window hosting YUI
     */

    /**
     * The document associated with the 'win' configuration.
     *
     * @property doc
     * @type Document
     * @default the document hosting YUI
     */

    /**
     * A list of modules that defines the YUI core (overrides the default).
     *
     * @property core
     * @type string[]
     */

    /**
     * A list of languages in order of preference. This list is matched against
     * the list of available languages in modules that the YUI instance uses to
     * determine the best possible localization of language sensitive modules.
     * Languages are represented using BCP 47 language tags, such as "en-GB" for
     * English as used in the United Kingdom, or "zh-Hans-CN" for simplified
     * Chinese as used in China. The list can be provided as a comma-separated
     * list or as an array.
     *
     * @property lang
     * @type string|string[]
     */

    /**
     * The default date format
     * @property dateFormat
     * @type string
     * @deprecated use configuration in DataType.Date.format() instead.
     */

    /**
     * The default locale
     * @property locale
     * @type string
     * @deprecated use config.lang instead.
     */

    /**
     * The default interval when polling in milliseconds.
     * @property pollInterval
     * @type int
     * @default 20
     */

    /**
     * The number of dynamic nodes to insert by default before
     * automatically removing them.  This applies to script nodes
     * because remove the node will not make the evaluated script
     * unavailable.  Dynamic CSS is not auto purged, because removing
     * a linked style sheet will also remove the style definitions.
     * @property purgethreshold
     * @type int
     * @default 20
     */

    /**
     * The default interval when polling in milliseconds.
     * @property windowResizeDelay
     * @type int
     * @default 40
     */

    /**
     * Base directory for dynamic loading
     * @property base
     * @type string
     */

    /*
     * The secure base dir (not implemented)
     * For dynamic loading.
     * @property secureBase
     * @type string
     */

    /**
     * The YUI combo service base dir. Ex: http://yui.yahooapis.com/combo?
     * For dynamic loading.
     * @property comboBase
     * @type string
     */

    /**
     * The root path to prepend to module path for the combo service.
     * Ex: 3.0.0b1/build/
     * For dynamic loading.
     * @property root
     * @type string
     */

    /**
     * A filter to apply to result urls.  This filter will modify the default
     * path for all modules.  The default path for the YUI library is the
     * minified version of the files (e.g., event-min.js).  The filter property
     * can be a predefined filter or a custom filter.  The valid predefined
     * filters are:
     * <dl>
     *  <dt>DEBUG</dt>
     *  <dd>Selects the debug versions of the library (e.g., event-debug.js).
     *      This option will automatically include the Logger widget</dd>
     *  <dt>RAW</dt>
     *  <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
     * </dl>
     * You can also define a custom filter, which must be an object literal
     * containing a search expression and a replace string:
     * <pre>
     *  myFilter: &#123;
     *      'searchExp': "-min\\.js",
     *      'replaceStr': "-debug.js"
     *  &#125;
     * </pre>
     *
     * For dynamic loading.
     *
     * @property filter
     * @type string|object
     */

    /**
     * The 'skin' config let's you configure application level skin
     * customizations.  It contains the following attributes which
     * can be specified to override the defaults:
     *
     *      // The default skin, which is automatically applied if not
     *      // overriden by a component-specific skin definition.
     *      // Change this in to apply a different skin globally
     *      defaultSkin: 'sam',
     *
     *      // This is combined with the loader base property to get
     *      // the default root directory for a skin.
     *      base: 'assets/skins/',
     *
     *      // Any component-specific overrides can be specified here,
     *      // making it possible to load different skins for different
     *      // components.  It is possible to load more than one skin
     *      // for a given component as well.
     *      overrides: {
     *          slider: ['capsule', 'round']
     *      }
     *
     * For dynamic loading.
     *
     *  @property skin
     */

    /**
     * Hash of per-component filter specification.  If specified for a given
     * component, this overrides the filter config.
     *
     * For dynamic loading.
     *
     * @property filters
     */

    /**
     * Use the YUI combo service to reduce the number of http connections
     * required to load your dependencies.  Turning this off will
     * disable combo handling for YUI and all module groups configured
     * with a combo service.
     *
     * For dynamic loading.
     *
     * @property combine
     * @type boolean
     * @default true if 'base' is not supplied, false if it is.
     */

    /**
     * A list of modules that should never be dynamically loaded
     *
     * @property ignore
     * @type string[]
     */

    /**
     * A list of modules that should always be loaded when required, even if already
     * present on the page.
     *
     * @property force
     * @type string[]
     */

    /**
     * Node or id for a node that should be used as the insertion point for new
     * nodes.  For dynamic loading.
     *
     * @property insertBefore
     * @type string
     */

    /**
     * Object literal containing attributes to add to dynamically loaded script
     * nodes.
     * @property jsAttributes
     * @type string
     */

    /**
     * Object literal containing attributes to add to dynamically loaded link
     * nodes.
     * @property cssAttributes
     * @type string
     */

    /**
     * Number of milliseconds before a timeout occurs when dynamically
     * loading nodes. If not set, there is no timeout.
     * @property timeout
     * @type int
     */

    /**
     * Callback for the 'CSSComplete' event.  When dynamically loading YUI
     * components with CSS, this property fires when the CSS is finished
     * loading but script loading is still ongoing.  This provides an
     * opportunity to enhance the presentation of a loading page a little
     * bit before the entire loading process is done.
     *
     * @property onCSS
     * @type function
     */

    /**
     * A hash of module definitions to add to the list of YUI components.
     * These components can then be dynamically loaded side by side with
     * YUI via the use() method. This is a hash, the key is the module
     * name, and the value is an object literal specifying the metdata
     * for the module.  * See Loader.addModule for the supported module
     * metadata fields.  Also @see groups, which provides a way to
     * configure the base and combo spec for a set of modules.
     * <code>
     * modules: {
     * &nbsp; mymod1: {
     * &nbsp;   requires: ['node'],
     * &nbsp;   fullpath: 'http://myserver.mydomain.com/mymod1/mymod1.js'
     * &nbsp; },
     * &nbsp; mymod2: {
     * &nbsp;   requires: ['mymod1'],
     * &nbsp;   fullpath: 'http://myserver.mydomain.com/mymod2/mymod2.js'
     * &nbsp; }
     * }
     * </code>
     *
     * @property modules
     * @type object
     */

    /**
     * A hash of module group definitions.  It for each group you
     * can specify a list of modules and the base path and
     * combo spec to use when dynamically loading the modules.  @see
     * @see modules for the details about the modules part of the
     * group definition.
     * <code>
     * &nbsp; groups: {
     * &nbsp;     yui2: {
     * &nbsp;         // specify whether or not this group has a combo service
     * &nbsp;         combine: true,
     * &nbsp;
     * &nbsp;         // the base path for non-combo paths
     * &nbsp;         base: 'http://yui.yahooapis.com/2.8.0r4/build/',
     * &nbsp;
     * &nbsp;         // the path to the combo service
     * &nbsp;         comboBase: 'http://yui.yahooapis.com/combo?',
     * &nbsp;
     * &nbsp;         // a fragment to prepend to the path attribute when
     * &nbsp;         // when building combo urls
     * &nbsp;         root: '2.8.0r4/build/',
     * &nbsp;
     * &nbsp;         // the module definitions
     * &nbsp;         modules:  {
     * &nbsp;             yui2_yde: {
     * &nbsp;                 path: "yahoo-dom-event/yahoo-dom-event.js"
     * &nbsp;             },
     * &nbsp;             yui2_anim: {
     * &nbsp;                 path: "animation/animation.js",
     * &nbsp;                 requires: ['yui2_yde']
     * &nbsp;             }
     * &nbsp;         }
     * &nbsp;     }
     * &nbsp; }
     * </code>
     * @property modules
     * @type object
     */

    /**
     * The loader 'path' attribute to the loader itself.  This is combined
     * with the 'base' attribute to dynamically load the loader component
     * when boostrapping with the get utility alone.
     *
     * @property loaderPath
     * @type string
     * @default loader/loader-min.js
     */

    /**
     * Specifies whether or not YUI().use(...) will attempt to load CSS
     * resources at all.  Any truthy value will cause CSS dependencies
     * to load when fetching script.  The special value 'force' will
     * cause CSS dependencies to be loaded even if no script is needed.
     *
     * @property fetchCSS
     * @type boolean|string
     * @default true
     */

    /**
     * The default gallery version to build gallery module urls
     * @property gallery
     * @type string
     * @since 3.1.0
     */

    /**
     * The default YUI 2 version to build yui2 module urls.  This is for
     * intrinsic YUI 2 support via the 2in3 project.  Also @see the '2in3'
     * config for pulling different revisions of the wrapped YUI 2
     * modules.
     * @since 3.1.0
     * @property yui2
     * @type string
     * @default 2.8.1
     */

    /**
     * The 2in3 project is a deployment of the various versions of YUI 2
     * deployed as first-class YUI 3 modules.  Eventually, the wrapper
     * for the modules will change (but the underlying YUI 2 code will
     * be the same), and you can select a particular version of
     * the wrapper modules via this config.
     * @since 3.1.0
     * @property 2in3
     * @type string
     * @default 1
     */

    /**
     * Alternative console log function for use in environments without
     * a supported native console.  The function is executed in the
     * YUI instance context.
     * @since 3.1.0
     * @property logFn
     * @type Function
     */

    /**
     * A callback to execute when Y.error is called.  It receives the
     * error message and an javascript error object if Y.error was
     * executed because a javascript error was caught.  The function
     * is executed in the YUI instance context.
     *
     * @since 3.2.0
     * @property errorFn
     * @type Function
     */

    /**
     * A callback to execute when the loader fails to load one or
     * more resource.  This could be because of a script load
     * failure.  It can also fail if a javascript module fails
     * to register itself, but only when the 'requireRegistration'
     * is true.  If this function is defined, the use() callback will
     * only be called when the loader succeeds, otherwise it always
     * executes unless there was a javascript error when attaching
     * a module.
     *
     * @since 3.3.0
     * @property loadErrorFn
     * @type Function
     */

    /**
     * When set to true, the YUI loader will expect that all modules
     * it is responsible for loading will be first-class YUI modules
     * that register themselves with the YUI global.  If this is
     * set to true, loader will fail if the module registration fails
     * to happen after the script is loaded.
     *
     * @since 3.3.0
     * @property requireRegistration
     * @type boolean
     * @default false
     */

    /**
     * Cache serviced use() requests.
     * @since 3.3.0
     * @property cacheUse
     * @type boolean
     * @default true
     */

    /**
     * The parameter defaults for the remote loader service.
     * Requires the rls submodule.  The properties that are
     * supported:
     * <pre>
     * m: comma separated list of module requirements.  This
     *    must be the param name even for custom implemetations.
     * v: the version of YUI to load.  Defaults to the version
     *    of YUI that is being used.
     * gv: the version of the gallery to load (@see the gallery config)
     * env: comma separated list of modules already on the page.
     *      this must be the param name even for custom implemetations.
     * lang: the languages supported on the page (@see the lang config)
     * '2in3v':  the version of the 2in3 wrapper to use (@see the 2in3 config).
     * '2v': the version of yui2 to use in the yui 2in3 wrappers
     *       (@see the yui2 config)
     * filt: a filter def to apply to the urls (@see the filter config).
     * filts: a list of custom filters to apply per module
     *        (@see the filters config).
     * tests: this is a map of conditional module test function id keys
     * with the values of 1 if the test passes, 0 if not.  This must be
     * the name of the querystring param in custom templates.
     *</pre>
     *
     * @since 3.2.0
     * @property rls
     */

    /**
     * The base path to the remote loader service
     *
     * @since 3.2.0
     * @property rls_base
     */

    /**
     * The template to use for building the querystring portion
     * of the remote loader service url.  The default is determined
     * by the rls config -- each property that has a value will be
     * represented.
     *
     * ex: m={m}&v={v}&env={env}&lang={lang}&filt={filt}&tests={tests}
     *
     *
     * @since 3.2.0
     * @property rls_tmpl
     */

    /**
     * Configure the instance to use a remote loader service instead of
     * the client loader.
     *
     * @since 3.2.0
     * @property use_rls
     */

Copyright © 2011 Yahoo! Inc. All rights reserved.