Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
The YUI module contains the components required for building the YUI seed file.
3
This includes the script loading mechanism, a simple queue, and the core
4
utilities for the library.
5
 
6
@module yui
7
@main yui
8
@submodule yui-base
9
**/
10
 
11
/*jshint eqeqeq: false*/
12
if (typeof YUI != 'undefined') {
13
    YUI._YUI = YUI;
14
}
15
 
16
/**
17
The YUI global namespace object. This is the constructor for all YUI instances.
18
 
19
This is a self-instantiable factory function, meaning you don't need to precede
20
it with the `new` operator. You can invoke it directly like this:
21
 
22
    YUI().use('*', function (Y) {
23
        // Y is a new YUI instance.
24
    });
25
 
26
But it also works like this:
27
 
28
    var Y = YUI();
29
 
30
The `YUI` constructor accepts an optional config object, like this:
31
 
32
    YUI({
33
        debug: true,
34
        combine: false
35
    }).use('node', function (Y) {
36
        // Y.Node is ready to use.
37
    });
38
 
39
See the API docs for the <a href="config.html">Config</a> class for the complete
40
list of supported configuration properties accepted by the YUI constuctor.
41
 
42
If a global `YUI` object is already defined, the existing YUI object will not be
43
overwritten, to ensure that defined namespaces are preserved.
44
 
45
Each YUI instance has full custom event support, but only if the event system is
46
available.
47
 
48
@class YUI
49
@uses EventTarget
50
@constructor
51
@global
52
@param {Object} [config]* Zero or more optional configuration objects. Config
53
    values are stored in the `Y.config` property. See the
54
    <a href="config.html">Config</a> docs for the list of supported properties.
55
**/
56
 
57
    /*global YUI*/
58
    /*global YUI_config*/
59
    var YUI = function() {
60
        var i = 0,
61
            Y = this,
62
            args = arguments,
63
            l = args.length,
64
            instanceOf = function(o, type) {
65
                return (o && o.hasOwnProperty && (o instanceof type));
66
            },
67
            gconf = (typeof YUI_config !== 'undefined') && YUI_config;
68
 
69
        if (!(instanceOf(Y, YUI))) {
70
            Y = new YUI();
71
        } else {
72
            // set up the core environment
73
            Y._init();
74
 
75
            /**
76
            Master configuration that might span multiple contexts in a non-
77
            browser environment. It is applied first to all instances in all
78
            contexts.
79
 
80
            @example
81
 
82
                YUI.GlobalConfig = {
83
                    filter: 'debug'
84
                };
85
 
86
                YUI().use('node', function (Y) {
87
                    // debug files used here
88
                });
89
 
90
                YUI({
91
                    filter: 'min'
92
                }).use('node', function (Y) {
93
                    // min files used here
94
                });
95
 
96
            @property {Object} GlobalConfig
97
            @global
98
            @static
99
            **/
100
            if (YUI.GlobalConfig) {
101
                Y.applyConfig(YUI.GlobalConfig);
102
            }
103
 
104
            /**
105
            Page-level config applied to all YUI instances created on the
106
            current page. This is applied after `YUI.GlobalConfig` and before
107
            any instance-level configuration.
108
 
109
            @example
110
 
111
                // Single global var to include before YUI seed file
112
                YUI_config = {
113
                    filter: 'debug'
114
                };
115
 
116
                YUI().use('node', function (Y) {
117
                    // debug files used here
118
                });
119
 
120
                YUI({
121
                    filter: 'min'
122
                }).use('node', function (Y) {
123
                    // min files used here
124
                });
125
 
126
            @property {Object} YUI_config
127
            @global
128
            **/
129
            if (gconf) {
130
                Y.applyConfig(gconf);
131
            }
132
 
133
            // bind the specified additional modules for this instance
134
            if (!l) {
135
                Y._afterConfig();
136
                Y._setup();
137
            }
138
        }
139
 
140
        if (l) {
141
            // Each instance can accept one or more configuration objects.
142
            // These are applied after YUI.GlobalConfig and YUI_Config,
143
            // overriding values set in those config files if there is a
144
            // matching property.
145
            for (; i < l; i++) {
146
                Y.applyConfig(args[i]);
147
            }
148
 
149
            Y._afterConfig();
150
            Y._setup();
151
        }
152
 
153
        Y.instanceOf = instanceOf;
154
 
155
        return Y;
156
    };
157
 
158
(function() {
159
 
160
    var proto, prop,
161
        VERSION = '3.18.1',
162
        PERIOD = '.',
163
        BASE = 'http://yui.yahooapis.com/',
164
        /*
165
            These CSS class names can't be generated by
166
            getClassName since it is not available at the
167
            time they are being used.
168
        */
169
        DOC_LABEL = 'yui3-js-enabled',
170
        CSS_STAMP_EL = 'yui3-css-stamp',
171
        NOOP = function() {},
172
        SLICE = Array.prototype.slice,
173
        APPLY_TO_AUTH = { 'io.xdrReady': 1,   // the functions applyTo
174
                          'io.xdrResponse': 1,   // can call. this should
175
                          'SWF.eventHandler': 1 }, // be done at build time
176
        hasWin = (typeof window != 'undefined'),
177
        win = (hasWin) ? window : null,
178
        doc = (hasWin) ? win.document : null,
179
        docEl = doc && doc.documentElement,
180
        docClass = docEl && docEl.className,
181
        instances = {},
182
        time = new Date().getTime(),
183
        add = function(el, type, fn, capture) {
184
            if (el && el.addEventListener) {
185
                el.addEventListener(type, fn, capture);
186
            } else if (el && el.attachEvent) {
187
                el.attachEvent('on' + type, fn);
188
            }
189
        },
190
        remove = function(el, type, fn, capture) {
191
            if (el && el.removeEventListener) {
192
                // this can throw an uncaught exception in FF
193
                try {
194
                    el.removeEventListener(type, fn, capture);
195
                } catch (ex) {}
196
            } else if (el && el.detachEvent) {
197
                el.detachEvent('on' + type, fn);
198
            }
199
        },
200
        handleReady = function() {
201
            YUI.Env.DOMReady = true;
202
            if (hasWin) {
203
                remove(doc, 'DOMContentLoaded', handleReady);
204
            }
205
        },
206
        handleLoad = function() {
207
            YUI.Env.windowLoaded = true;
208
            YUI.Env.DOMReady = true;
209
            if (hasWin) {
210
                remove(window, 'load', handleLoad);
211
            }
212
        },
213
        getLoader = function(Y, o) {
214
            var loader = Y.Env._loader,
215
                lCore = [ 'loader-base' ],
216
                G_ENV = YUI.Env,
217
                mods = G_ENV.mods;
218
 
219
            if (loader) {
220
                //loader._config(Y.config);
221
                loader.ignoreRegistered = false;
222
                loader.onEnd = null;
223
                loader.data = null;
224
                loader.required = [];
225
                loader.loadType = null;
226
            } else {
227
                loader = new Y.Loader(Y.config);
228
                Y.Env._loader = loader;
229
            }
230
            if (mods && mods.loader) {
231
                lCore = [].concat(lCore, YUI.Env.loaderExtras);
232
            }
233
            YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore));
234
 
235
            return loader;
236
        },
237
 
238
        clobber = function(r, s) {
239
            for (var i in s) {
240
                if (s.hasOwnProperty(i)) {
241
                    r[i] = s[i];
242
                }
243
            }
244
        },
245
 
246
        ALREADY_DONE = { success: true };
247
 
248
//  Stamp the documentElement (HTML) with a class of "yui-loaded" to
249
//  enable styles that need to key off of JS being enabled.
250
if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
251
    if (docClass) {
252
        docClass += ' ';
253
    }
254
    docClass += DOC_LABEL;
255
    docEl.className = docClass;
256
}
257
 
258
if (VERSION.indexOf('@') > -1) {
259
    VERSION = '3.5.0'; // dev time hack for cdn test
260
}
261
 
262
proto = {
263
    /**
264
    Applies a new configuration object to the config of this YUI instance. This
265
    will merge new group/module definitions, and will also update the loader
266
    cache if necessary. Updating `Y.config` directly will not update the cache.
267
 
268
    @method applyConfig
269
    @param {Object} o the configuration object.
270
    @since 3.2.0
271
    **/
272
    applyConfig: function(o) {
273
 
274
        o = o || NOOP;
275
 
276
        var attr,
277
            name,
278
            // detail,
279
            config = this.config,
280
            mods = config.modules,
281
            groups = config.groups,
282
            aliases = config.aliases,
283
            loader = this.Env._loader;
284
 
285
        for (name in o) {
286
            if (o.hasOwnProperty(name)) {
287
                attr = o[name];
288
                if (mods && name == 'modules') {
289
                    clobber(mods, attr);
290
                } else if (aliases && name == 'aliases') {
291
                    clobber(aliases, attr);
292
                } else if (groups && name == 'groups') {
293
                    clobber(groups, attr);
294
                } else if (name == 'win') {
295
                    config[name] = (attr && attr.contentWindow) || attr;
296
                    config.doc = config[name] ? config[name].document : null;
297
                } else if (name == '_yuid') {
298
                    // preserve the guid
299
                } else {
300
                    config[name] = attr;
301
                }
302
            }
303
        }
304
 
305
        if (loader) {
306
            loader._config(o);
307
        }
308
 
309
    },
310
 
311
    /**
312
    Old way to apply a config to this instance (calls `applyConfig` under the
313
    hood).
314
 
315
    @private
316
    @method _config
317
    @param {Object} o The config to apply
318
    **/
319
    _config: function(o) {
320
        this.applyConfig(o);
321
    },
322
 
323
    /**
324
    Initializes this YUI instance.
325
 
326
    @private
327
    @method _init
328
    **/
329
    _init: function() {
330
        var filter, el,
331
            Y = this,
332
            G_ENV = YUI.Env,
333
            Env = Y.Env,
334
            prop;
335
 
336
        /**
337
        The version number of this YUI instance.
338
 
339
        This value is typically updated by a script when a YUI release is built,
340
        so it may not reflect the correct version number when YUI is run from
341
        the development source tree.
342
 
343
        @property {String} version
344
        **/
345
        Y.version = VERSION;
346
 
347
        if (!Env) {
348
            Y.Env = {
349
                core: ['intl-base'],
350
                loaderExtras: ['loader-rollup', 'loader-yui3'],
351
                mods: {}, // flat module map
352
                versions: {}, // version module map
353
                base: BASE,
354
                cdn: BASE + VERSION + '/',
355
                // bootstrapped: false,
356
                _idx: 0,
357
                _used: {},
358
                _attached: {},
359
                _exported: {},
360
                _missed: [],
361
                _yidx: 0,
362
                _uidx: 0,
363
                _guidp: 'y',
364
                _loaded: {},
365
                // serviced: {},
366
                // Regex in English:
367
                // I'll start at the \b(yui).
368
                // 1. Look in the test string for "yui" or
369
                //    "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break.  That is, it
370
                //    can't match "foyui" or "i_heart_yui". This can be anywhere in the string.
371
                // 2. After #1 must come a forward slash followed by the string matched in #1, so
372
                //    "yui-base/yui-base" or "yui-pants/yui-pants".
373
                // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
374
                //    so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
375
                // 4. This is followed by ".js", so "yui/yui.js".
376
                // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
377
                //    then capture the junk between the LAST "&" and the string in 1-4.  So
378
                //    "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
379
                //    will capture "3.3.0/build/"
380
                //
381
                // Regex Exploded:
382
                // (?:\?             Find a ?
383
                //   (?:[^&]*&)      followed by 0..n characters followed by an &
384
                //   *               in fact, find as many sets of characters followed by a & as you can
385
                //   ([^&]*)         capture the stuff after the last & in \1
386
                // )?                but it's ok if all this ?junk&more_junk stuff isn't even there
387
                // \b(               after a word break find either the string
388
                //    yui(?:-\w+)?   "yui" optionally followed by a -, then more characters
389
                // )                 and store the yui-* string in \2
390
                // \/\2              then comes a / followed by the yui-* string in \2
391
                // (?:-(min|debug))? optionally followed by "-min" or "-debug"
392
                // .js               and ending in ".js"
393
                _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
394
                parseBasePath: function(src, pattern) {
395
                    var match = src.match(pattern),
396
                        path, filter;
397
 
398
                    if (match) {
399
                        path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
400
 
401
                        // this is to set up the path to the loader.  The file
402
                        // filter for loader should match the yui include.
403
                        filter = match[3];
404
 
405
                        // extract correct path for mixed combo urls
406
                        // http://yuilibrary.com/projects/yui3/ticket/2528423
407
                        if (match[1]) {
408
                            path += '?' + match[1];
409
                        }
410
                        path = {
411
                            filter: filter,
412
                            path: path
413
                        };
414
                    }
415
                    return path;
416
                },
417
                getBase: G_ENV && G_ENV.getBase ||
418
                        function(pattern) {
419
                            var nodes = (doc && doc.getElementsByTagName('script')) || [],
420
                                path = Env.cdn, parsed,
421
                                i, len, src;
422
 
423
                            for (i = 0, len = nodes.length; i < len; ++i) {
424
                                src = nodes[i].src;
425
                                if (src) {
426
                                    parsed = Y.Env.parseBasePath(src, pattern);
427
                                    if (parsed) {
428
                                        filter = parsed.filter;
429
                                        path = parsed.path;
430
                                        break;
431
                                    }
432
                                }
433
                            }
434
 
435
                            // use CDN default
436
                            return path;
437
                        }
438
 
439
            };
440
 
441
            Env = Y.Env;
442
 
443
            Env._loaded[VERSION] = {};
444
 
445
            if (G_ENV && Y !== YUI) {
446
                Env._yidx = ++G_ENV._yidx;
447
                Env._guidp = ('yui_' + VERSION + '_' +
448
                             Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_');
449
            } else if (YUI._YUI) {
450
 
451
                G_ENV = YUI._YUI.Env;
452
                Env._yidx += G_ENV._yidx;
453
                Env._uidx += G_ENV._uidx;
454
 
455
                for (prop in G_ENV) {
456
                    if (!(prop in Env)) {
457
                        Env[prop] = G_ENV[prop];
458
                    }
459
                }
460
 
461
                delete YUI._YUI;
462
            }
463
 
464
            Y.id = Y.stamp(Y);
465
            instances[Y.id] = Y;
466
 
467
        }
468
 
469
        Y.constructor = YUI;
470
 
471
        // configuration defaults
472
        Y.config = Y.config || {
473
            bootstrap: true,
474
            cacheUse: true,
475
            debug: true,
476
            doc: doc,
477
            fetchCSS: true,
478
            throwFail: true,
479
            useBrowserConsole: true,
480
            useNativeES5: true,
481
            win: win
482
        };
483
 
484
        //Register the CSS stamp element
485
        if (doc && !doc.getElementById(CSS_STAMP_EL)) {
486
            el = doc.createElement('div');
487
            el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
488
            YUI.Env.cssStampEl = el.firstChild;
489
            if (doc.body) {
490
                doc.body.appendChild(YUI.Env.cssStampEl);
491
            } else {
492
                docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
493
            }
494
        } else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) {
495
            YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL);
496
        }
497
 
498
        Y.config.lang = Y.config.lang || 'en-US';
499
 
500
        Y.config.base = YUI.config.base ||
501
                (YUI.config.defaultBase && YUI.config.root && YUI.config.defaultBase + YUI.config.root) ||
502
                Y.Env.getBase(Y.Env._BASE_RE);
503
 
504
        if (!filter || (!('mindebug').indexOf(filter))) {
505
            filter = 'min';
506
        }
507
        filter = (filter) ? '-' + filter : filter;
508
        Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
509
 
510
    },
511
 
512
    /**
513
    This method is called after all other configuration has been applied to
514
    the YUI instance.
515
 
516
    @method _afterConfig
517
    @private
518
    **/
519
    _afterConfig: function () {
520
        var Y = this;
521
 
522
        // We need to set up Y.config.global after the rest of the configuration
523
        // so that setting it in user configuration prevents the library from
524
        // using eval(). This is critical for Content Security Policy enabled
525
        // sites and other environments like Chrome extensions
526
        if (!Y.config.hasOwnProperty('global')) {
527
            Y.config.global = Function('return this')();
528
        }
529
    },
530
 
531
    /**
532
    Finishes the instance setup. Attaches whatever YUI modules were defined
533
    at the time that this instance was created.
534
 
535
    @method _setup
536
    @private
537
    **/
538
    _setup: function() {
539
        var i, Y = this,
540
            core = [],
541
            mods = YUI.Env.mods,
542
            extendedCore = Y.config.extendedCore || [],
543
            extras = Y.config.core || [].concat(YUI.Env.core).concat(extendedCore); //Clone it..
544
 
545
        for (i = 0; i < extras.length; i++) {
546
            if (mods[extras[i]]) {
547
                core.push(extras[i]);
548
            }
549
        }
550
 
551
        Y._attach(['yui-base']);
552
        Y._attach(core);
553
 
554
        if (Y.Loader) {
555
            getLoader(Y);
556
        }
557
 
558
        // Y.log(Y.id + ' initialized', 'info', 'yui');
559
    },
560
 
561
    /**
562
    Executes the named method on the specified YUI instance if that method is
563
    whitelisted.
564
 
565
    @method applyTo
566
    @param {String} id YUI instance id.
567
    @param {String} method Name of the method to execute. For example:
568
        'Object.keys'.
569
    @param {Array} args Arguments to apply to the method.
570
    @return {Mixed} Return value from the applied method, or `null` if the
571
        specified instance was not found or the method was not whitelisted.
572
    **/
573
    applyTo: function(id, method, args) {
574
        if (!(method in APPLY_TO_AUTH)) {
575
            this.log(method + ': applyTo not allowed', 'warn', 'yui');
576
            return null;
577
        }
578
 
579
        var instance = instances[id], nest, m, i;
580
        if (instance) {
581
            nest = method.split('.');
582
            m = instance;
583
            for (i = 0; i < nest.length; i = i + 1) {
584
                m = m[nest[i]];
585
                if (!m) {
586
                    this.log('applyTo not found: ' + method, 'warn', 'yui');
587
                }
588
            }
589
            return m && m.apply(instance, args);
590
        }
591
 
592
        return null;
593
    },
594
 
595
/**
596
Registers a YUI module and makes it available for use in a `YUI().use()` call or
597
as a dependency for other modules.
598
 
599
The easiest way to create a first-class YUI module is to use
600
<a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
601
tool.
602
 
603
Shifter will automatically wrap your module code in a `YUI.add()` call along
604
with any configuration info required for the module.
605
 
606
@example
607
 
608
    YUI.add('davglass', function (Y) {
609
        Y.davglass = function () {
610
            Y.log('Dav was here!');
611
        };
612
    }, '3.4.0', {
613
        requires: ['harley-davidson', 'mt-dew']
614
    });
615
 
616
@method add
617
@param {String} name Module name.
618
@param {Function} fn Function containing module code. This function will be
619
    executed whenever the module is attached to a specific YUI instance.
620
 
621
    @param {YUI} fn.Y The YUI instance to which this module is attached.
622
    @param {String} fn.name Name of the module
623
 
624
@param {String} version Module version number. This is currently used only for
625
    informational purposes, and is not used internally by YUI.
626
 
627
@param {Object} [details] Module config.
628
    @param {Array} [details.requires] Array of other module names that must be
629
        attached before this module can be attached.
630
    @param {Array} [details.optional] Array of optional module names that should
631
        be attached before this module is attached if they've already been
632
        loaded. If the `loadOptional` YUI option is `true`, optional modules
633
        that have not yet been loaded will be loaded just as if they were hard
634
        requirements.
635
    @param {Array} [details.use] Array of module names that are included within
636
        or otherwise provided by this module, and which should be attached
637
        automatically when this module is attached. This makes it possible to
638
        create "virtual rollup" modules that simply attach a collection of other
639
        modules or submodules.
640
 
641
@return {YUI} This YUI instance.
642
**/
643
    add: function(name, fn, version, details) {
644
        details = details || {};
645
        var env = YUI.Env,
646
            mod = {
647
                name: name,
648
                fn: fn,
649
                version: version,
650
                details: details
651
            },
652
            //Instance hash so we don't apply it to the same instance twice
653
            applied = {},
654
            loader, inst, modInfo,
655
            i, versions = env.versions;
656
 
657
        env.mods[name] = mod;
658
        versions[version] = versions[version] || {};
659
        versions[version][name] = mod;
660
 
661
        for (i in instances) {
662
            if (instances.hasOwnProperty(i)) {
663
                inst = instances[i];
664
                if (!applied[inst.id]) {
665
                    applied[inst.id] = true;
666
                    loader = inst.Env._loader;
667
                    if (loader) {
668
                        modInfo = loader.getModuleInfo(name);
669
                        if (!modInfo || modInfo.temp) {
670
                            loader.addModule(details, name);
671
                        }
672
                    }
673
                }
674
            }
675
        }
676
 
677
        return this;
678
    },
679
 
680
    /**
681
    Executes the callback function associated with each required module,
682
    attaching the module to this YUI instance.
683
 
684
    @method _attach
685
    @param {Array} r The array of modules to attach
686
    @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
687
        is not attached.
688
    @private
689
    **/
690
    _attach: function(r, moot) {
691
        var i, name, mod, details, req, use, after,
692
            mods = YUI.Env.mods,
693
            aliases = YUI.Env.aliases,
694
            Y = this, j,
695
            cache = YUI.Env._renderedMods,
696
            loader = Y.Env._loader,
697
            done = Y.Env._attached,
698
            exported = Y.Env._exported,
699
            len = r.length, loader, def, go,
700
            c = [],
701
            modArgs, esCompat, reqlen, modInfo,
702
            condition,
703
            __exports__, __imports__;
704
 
705
        //Check for conditional modules (in a second+ instance) and add their requirements
706
        //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
707
        for (i = 0; i < len; i++) {
708
            name = r[i];
709
            mod = mods[name];
710
            c.push(name);
711
            if (loader && loader.conditions[name]) {
712
                for (j in loader.conditions[name]) {
713
                    if (loader.conditions[name].hasOwnProperty(j)) {
714
                        def = loader.conditions[name][j];
715
                        go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
716
                        if (go) {
717
                            c.push(def.name);
718
                        }
719
                    }
720
                }
721
            }
722
        }
723
        r = c;
724
        len = r.length;
725
 
726
        for (i = 0; i < len; i++) {
727
            if (!done[r[i]]) {
728
                name = r[i];
729
                mod = mods[name];
730
 
731
                if (aliases && aliases[name] && !mod) {
732
                    Y._attach(aliases[name]);
733
                    continue;
734
                }
735
                if (!mod) {
736
                    modInfo = loader && loader.getModuleInfo(name);
737
                    if (modInfo) {
738
                        mod = modInfo;
739
                        moot = true;
740
                    }
741
 
742
                    // Y.log('no js def for: ' + name, 'info', 'yui');
743
 
744
                    //if (!loader || !loader.moduleInfo[name]) {
745
                    //if ((!loader || !loader.moduleInfo[name]) && !moot) {
746
                    if (!moot && name) {
747
                        if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
748
                            Y.Env._missed.push(name);
749
                            Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
750
                            Y.message('NOT loaded: ' + name, 'warn', 'yui');
751
                        }
752
                    }
753
                } else {
754
                    done[name] = true;
755
                    //Don't like this, but in case a mod was asked for once, then we fetch it
756
                    //We need to remove it from the missed list ^davglass
757
                    for (j = 0; j < Y.Env._missed.length; j++) {
758
                        if (Y.Env._missed[j] === name) {
759
                            Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
760
                            Y.Env._missed.splice(j, 1);
761
                        }
762
                    }
763
 
764
                    // Optional dependencies normally work by modifying the
765
                    // dependency list of a module. If the dependency's test
766
                    // passes it is added to the list. If not, it's not loaded.
767
                    // This following check ensures that optional dependencies
768
                    // are not attached when they were already loaded into the
769
                    // page (when bundling for example)
770
                    if (loader && !loader._canBeAttached(name)) {
771
                        Y.log('Failed to attach module ' + name, 'warn', 'yui');
772
                        return true;
773
                    }
774
 
775
                    /*
776
                        If it's a temp module, we need to redo it's requirements if it's already loaded
777
                        since it may have been loaded by another instance and it's dependencies might
778
                        have been redefined inside the fetched file.
779
                    */
780
                    if (loader && cache && cache[name] && cache[name].temp) {
781
                        loader.getRequires(cache[name]);
782
                        req = [];
783
                        modInfo = loader.getModuleInfo(name);
784
                        for (j in modInfo.expanded_map) {
785
                            if (modInfo.expanded_map.hasOwnProperty(j)) {
786
                                req.push(j);
787
                            }
788
                        }
789
                        Y._attach(req);
790
                    }
791
 
792
                    details = mod.details;
793
                    req = details.requires;
794
                    esCompat = details.es;
795
                    use = details.use;
796
                    after = details.after;
797
                    //Force Intl load if there is a language (Loader logic) @todo fix this shit
798
                    if (details.lang) {
799
                        req = req || [];
800
                        req.unshift('intl');
801
                    }
802
 
803
                    if (req) {
804
                        reqlen = req.length;
805
                        for (j = 0; j < reqlen; j++) {
806
                            if (!done[req[j]]) {
807
                                if (!Y._attach(req)) {
808
                                    return false;
809
                                }
810
                                break;
811
                            }
812
                        }
813
                    }
814
 
815
                    if (after) {
816
                        for (j = 0; j < after.length; j++) {
817
                            if (!done[after[j]]) {
818
                                if (!Y._attach(after, true)) {
819
                                    return false;
820
                                }
821
                                break;
822
                            }
823
                        }
824
                    }
825
 
826
                    if (mod.fn) {
827
                        modArgs = [Y, name];
828
                        if (esCompat) {
829
                            __imports__ = {};
830
                            __exports__ = {};
831
                            // passing `exports` and `imports` onto the module function
832
                            modArgs.push(__imports__, __exports__);
833
                            if (req) {
834
                                reqlen = req.length;
835
                                for (j = 0; j < reqlen; j++) {
836
                                    __imports__[req[j]] = exported.hasOwnProperty(req[j]) ? exported[req[j]] : Y;
837
                                }
838
                            }
839
                        }
840
                        if (Y.config.throwFail) {
841
                            __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs);
842
                        } else {
843
                            try {
844
                                __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs);
845
                            } catch (e) {
846
                                Y.error('Attach error: ' + name, e, name);
847
                                return false;
848
                            }
849
                        }
850
                        if (esCompat) {
851
                            // store the `exports` in case others `es` modules requires it
852
                            exported[name] = __exports__;
853
 
854
                            // If an ES module is conditionally loaded and set
855
                            // to be used "instead" another module, replace the
856
                            // trigger module's content with the conditionally
857
                            // loaded one so the values returned by require()
858
                            // still makes sense
859
                            condition = mod.details.condition;
860
                            if (condition && condition.when === 'instead') {
861
                                exported[condition.trigger] = __exports__;
862
                            }
863
                        }
864
                    }
865
 
866
                    if (use) {
867
                        for (j = 0; j < use.length; j++) {
868
                            if (!done[use[j]]) {
869
                                if (!Y._attach(use)) {
870
                                    return false;
871
                                }
872
                                break;
873
                            }
874
                        }
875
                    }
876
 
877
 
878
 
879
                }
880
            }
881
        }
882
 
883
        return true;
884
    },
885
 
886
    /**
887
    Delays the `use` callback until another event has taken place such as
888
    `window.onload`, `domready`, `contentready`, or `available`.
889
 
890
    @private
891
    @method _delayCallback
892
    @param {Function} cb The original `use` callback.
893
    @param {String|Object} until Either an event name ('load', 'domready', etc.)
894
        or an object containing event/args keys for contentready/available.
895
    @return {Function}
896
    **/
897
    _delayCallback: function(cb, until) {
898
 
899
        var Y = this,
900
            mod = ['event-base'];
901
 
902
        until = (Y.Lang.isObject(until) ? until : { event: until });
903
 
904
        if (until.event === 'load') {
905
            mod.push('event-synthetic');
906
        }
907
 
908
        Y.log('Delaying use callback until: ' + until.event, 'info', 'yui');
909
        return function() {
910
            Y.log('Use callback fired, waiting on delay', 'info', 'yui');
911
            var args = arguments;
912
            Y._use(mod, function() {
913
                Y.log('Delayed use wrapper callback after dependencies', 'info', 'yui');
914
                Y.on(until.event, function() {
915
                    args[1].delayUntil = until.event;
916
                    Y.log('Delayed use callback done after ' + until.event, 'info', 'yui');
917
                    cb.apply(Y, args);
918
                }, until.args);
919
            });
920
        };
921
    },
922
 
923
    /**
924
    Attaches one or more modules to this YUI instance. When this is executed,
925
    the requirements of the desired modules are analyzed, and one of several
926
    things can happen:
927
 
928
 
929
      * All required modules have already been loaded, and just need to be
930
        attached to this YUI instance. In this case, the `use()` callback will
931
        be executed synchronously after the modules are attached.
932
 
933
      * One or more modules have not yet been loaded, or the Get utility is not
934
        available, or the `bootstrap` config option is `false`. In this case,
935
        a warning is issued indicating that modules are missing, but all
936
        available modules will still be attached and the `use()` callback will
937
        be executed synchronously.
938
 
939
      * One or more modules are missing and the Loader is not available but the
940
        Get utility is, and `bootstrap` is not `false`. In this case, the Get
941
        utility will be used to load the Loader, and we will then proceed to
942
        the following state:
943
 
944
      * One or more modules are missing and the Loader is available. In this
945
        case, the Loader will be used to resolve the dependency tree for the
946
        missing modules and load them and their dependencies. When the Loader is
947
        finished loading modules, the `use()` callback will be executed
948
        asynchronously.
949
 
950
    @example
951
 
952
        // Loads and attaches dd and its dependencies.
953
        YUI().use('dd', function (Y) {
954
            // ...
955
        });
956
 
957
        // Loads and attaches dd and node as well as all of their dependencies.
958
        YUI().use(['dd', 'node'], function (Y) {
959
            // ...
960
        });
961
 
962
        // Attaches all modules that have already been loaded.
963
        YUI().use('*', function (Y) {
964
            // ...
965
        });
966
 
967
        // Attaches a gallery module.
968
        YUI().use('gallery-yql', function (Y) {
969
            // ...
970
        });
971
 
972
        // Attaches a YUI 2in3 module.
973
        YUI().use('yui2-datatable', function (Y) {
974
            // ...
975
        });
976
 
977
    @method use
978
    @param {String|Array} modules* One or more module names to attach.
979
    @param {Function} [callback] Callback function to be executed once all
980
        specified modules and their dependencies have been attached.
981
    @param {YUI} callback.Y The YUI instance created for this sandbox.
982
    @param {Object} callback.status Object containing `success`, `msg` and
983
        `data` properties.
984
    @chainable
985
    **/
986
    use: function() {
987
        var args = SLICE.call(arguments, 0),
988
            callback = args[args.length - 1],
989
            Y = this,
990
            i = 0,
991
            name,
992
            Env = Y.Env,
993
            provisioned = true;
994
 
995
        // The last argument supplied to use can be a load complete callback
996
        if (Y.Lang.isFunction(callback)) {
997
            args.pop();
998
            if (Y.config.delayUntil) {
999
                callback = Y._delayCallback(callback, Y.config.delayUntil);
1000
            }
1001
        } else {
1002
            callback = null;
1003
        }
1004
        if (Y.Lang.isArray(args[0])) {
1005
            args = args[0];
1006
        }
1007
 
1008
        if (Y.config.cacheUse) {
1009
            while ((name = args[i++])) {
1010
                if (!Env._attached[name]) {
1011
                    provisioned = false;
1012
                    break;
1013
                }
1014
            }
1015
 
1016
            if (provisioned) {
1017
                if (args.length) {
1018
                    Y.log('already provisioned: ' + args, 'info', 'yui');
1019
                }
1020
                Y._notify(callback, ALREADY_DONE, args);
1021
                return Y;
1022
            }
1023
        }
1024
 
1025
        if (Y._loading) {
1026
            Y._useQueue = Y._useQueue || new Y.Queue();
1027
            Y._useQueue.add([args, callback]);
1028
        } else {
1029
            Y._use(args, function(Y, response) {
1030
                Y._notify(callback, response, args);
1031
            });
1032
        }
1033
 
1034
        return Y;
1035
    },
1036
 
1037
    /**
1038
    Sugar for loading both legacy and ES6-based YUI modules.
1039
 
1040
    @method require
1041
    @param {String} [modules*] List of module names to import or a single
1042
        module name.
1043
    @param {Function} callback Callback that gets called once all the modules
1044
        were loaded. Each parameter of the callback is the export value of the
1045
        corresponding module in the list. If the module is a legacy YUI module,
1046
        the YUI instance is used instead of the module exports.
1047
    @example
1048
    ```
1049
    YUI().require(['es6-set'], function (Y, imports) {
1050
        var Set = imports.Set,
1051
            set = new Set();
1052
    });
1053
    ```
1054
    **/
1055
    require: function () {
1056
        var args = SLICE.call(arguments),
1057
            callback;
1058
 
1059
        if (typeof args[args.length - 1] === 'function') {
1060
            callback = args.pop();
1061
 
1062
            // only add the callback if one was provided
1063
            // YUI().require('foo'); is valid
1064
            args.push(function (Y) {
1065
                var i, length = args.length,
1066
                    exported = Y.Env._exported,
1067
                    __imports__ = {};
1068
 
1069
                // Get only the imports requested as arguments
1070
                for (i = 0; i < length; i++) {
1071
                    if (exported.hasOwnProperty(args[i])) {
1072
                        __imports__[args[i]] = exported[args[i]];
1073
                    }
1074
                }
1075
 
1076
                // Using `undefined` because:
1077
                // - Using `Y.config.global` would force the value of `this` to be
1078
                //   the global object even in strict mode
1079
                // - Using `Y` goes against the goal of moving away from a shared
1080
                //   object and start thinking in terms of imported and exported
1081
                //   objects
1082
                callback.call(undefined, Y, __imports__);
1083
            });
1084
        }
1085
        // Do not return the Y object. This makes it hard to follow this
1086
        // traditional pattern:
1087
        //   var Y = YUI().use(...);
1088
        // This is a good idea in the light of ES6 modules, to avoid working
1089
        // in the global scope.
1090
        // This also leaves the door open for returning a promise, once the
1091
        // YUI loader is based on the ES6 loader which uses
1092
        // loader.import(...).then(...)
1093
        this.use.apply(this, args);
1094
    },
1095
 
1096
    /**
1097
    Handles Loader notifications about attachment/load errors.
1098
 
1099
    @method _notify
1100
    @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
1101
    @param {Object} response Response returned from Loader.
1102
    @param {Array} args Arguments passed from Loader.
1103
    @private
1104
    **/
1105
    _notify: function(callback, response, args) {
1106
        if (!response.success && this.config.loadErrorFn) {
1107
            this.config.loadErrorFn.call(this, this, callback, response, args);
1108
        } else if (callback) {
1109
            if (this.Env._missed && this.Env._missed.length) {
1110
                response.msg = 'Missing modules: ' + this.Env._missed.join();
1111
                response.success = false;
1112
            }
1113
            if (this.config.throwFail) {
1114
                callback(this, response);
1115
            } else {
1116
                try {
1117
                    callback(this, response);
1118
                } catch (e) {
1119
                    this.error('use callback error', e, args);
1120
                }
1121
            }
1122
        }
1123
    },
1124
 
1125
    /**
1126
    Called from the `use` method queue to ensure that only one set of loading
1127
    logic is performed at a time.
1128
 
1129
    @method _use
1130
    @param {String} args* One or more modules to attach.
1131
    @param {Function} [callback] Function to call once all required modules have
1132
        been attached.
1133
    @private
1134
    **/
1135
    _use: function(args, callback) {
1136
 
1137
        if (!this.Array) {
1138
            this._attach(['yui-base']);
1139
        }
1140
 
1141
        var len, loader, handleBoot,
1142
            Y = this,
1143
            G_ENV = YUI.Env,
1144
            mods = G_ENV.mods,
1145
            Env = Y.Env,
1146
            used = Env._used,
1147
            aliases = G_ENV.aliases,
1148
            queue = G_ENV._loaderQueue,
1149
            firstArg = args[0],
1150
            YArray = Y.Array,
1151
            config = Y.config,
1152
            boot = config.bootstrap,
1153
            missing = [],
1154
            i,
1155
            r = [],
1156
            ret = true,
1157
            fetchCSS = config.fetchCSS,
1158
            process = function(names, skip) {
1159
 
1160
                var i = 0, a = [], name, len, m, req, use;
1161
 
1162
                if (!names.length) {
1163
                    return;
1164
                }
1165
 
1166
                if (aliases) {
1167
                    len = names.length;
1168
                    for (i = 0; i < len; i++) {
1169
                        if (aliases[names[i]] && !mods[names[i]]) {
1170
                            a = [].concat(a, aliases[names[i]]);
1171
                        } else {
1172
                            a.push(names[i]);
1173
                        }
1174
                    }
1175
                    names = a;
1176
                }
1177
 
1178
                len = names.length;
1179
 
1180
                for (i = 0; i < len; i++) {
1181
                    name = names[i];
1182
                    if (!skip) {
1183
                        r.push(name);
1184
                    }
1185
 
1186
                    // only attach a module once
1187
                    if (used[name]) {
1188
                        continue;
1189
                    }
1190
 
1191
                    m = mods[name];
1192
                    req = null;
1193
                    use = null;
1194
 
1195
                    if (m) {
1196
                        used[name] = true;
1197
                        req = m.details.requires;
1198
                        use = m.details.use;
1199
                    } else {
1200
                        // CSS files don't register themselves, see if it has
1201
                        // been loaded
1202
                        if (!G_ENV._loaded[VERSION][name]) {
1203
                            missing.push(name);
1204
                        } else {
1205
                            used[name] = true; // probably css
1206
                        }
1207
                    }
1208
 
1209
                    // make sure requirements are attached
1210
                    if (req && req.length) {
1211
                        process(req);
1212
                    }
1213
 
1214
                    // make sure we grab the submodule dependencies too
1215
                    if (use && use.length) {
1216
                        process(use, 1);
1217
                    }
1218
                }
1219
 
1220
            },
1221
 
1222
            handleLoader = function(fromLoader) {
1223
                var response = fromLoader || {
1224
                        success: true,
1225
                        msg: 'not dynamic'
1226
                    },
1227
                    redo, origMissing,
1228
                    ret = true,
1229
                    data = response.data;
1230
 
1231
                Y._loading = false;
1232
 
1233
                if (data) {
1234
                    origMissing = missing;
1235
                    missing = [];
1236
                    r = [];
1237
                    process(data);
1238
                    redo = missing.length;
1239
                    if (redo) {
1240
                        if ([].concat(missing).sort().join() ==
1241
                                origMissing.sort().join()) {
1242
                            redo = false;
1243
                        }
1244
                    }
1245
                }
1246
 
1247
                if (redo && data) {
1248
                    Y._loading = true;
1249
                    Y._use(missing, function() {
1250
                        Y.log('Nested use callback: ' + data, 'info', 'yui');
1251
                        if (Y._attach(data)) {
1252
                            Y._notify(callback, response, data);
1253
                        }
1254
                    });
1255
                } else {
1256
                    if (data) {
1257
                        // Y.log('attaching from loader: ' + data, 'info', 'yui');
1258
                        ret = Y._attach(data);
1259
                    }
1260
                    if (ret) {
1261
                        Y._notify(callback, response, args);
1262
                    }
1263
                }
1264
 
1265
                if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
1266
                    Y._use.apply(Y, Y._useQueue.next());
1267
                }
1268
 
1269
            };
1270
 
1271
// Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');
1272
 
1273
        // YUI().use('*'); // bind everything available
1274
        if (firstArg === '*') {
1275
            args = [];
1276
            for (i in mods) {
1277
                if (mods.hasOwnProperty(i)) {
1278
                    args.push(i);
1279
                }
1280
            }
1281
            ret = Y._attach(args);
1282
            if (ret) {
1283
                handleLoader();
1284
            }
1285
            return Y;
1286
        }
1287
 
1288
        if ((mods.loader || mods['loader-base']) && !Y.Loader) {
1289
            Y.log('Loader was found in meta, but it is not attached. Attaching..', 'info', 'yui');
1290
            Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
1291
        }
1292
 
1293
        // Y.log('before loader requirements: ' + args, 'info', 'yui');
1294
 
1295
        // use loader to expand dependencies and sort the
1296
        // requirements if it is available.
1297
        if (boot && Y.Loader && args.length) {
1298
            Y.log('Using loader to expand dependencies', 'info', 'yui');
1299
            loader = getLoader(Y);
1300
            loader.require(args);
1301
            loader.ignoreRegistered = true;
1302
            loader._boot = true;
1303
            loader.calculate(null, (fetchCSS) ? null : 'js');
1304
            args = loader.sorted;
1305
            loader._boot = false;
1306
        }
1307
 
1308
        process(args);
1309
 
1310
        len = missing.length;
1311
 
1312
 
1313
        if (len) {
1314
            missing = YArray.dedupe(missing);
1315
            len = missing.length;
1316
Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
1317
        }
1318
 
1319
 
1320
        // dynamic load
1321
        if (boot && len && Y.Loader) {
1322
// Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
1323
            Y.log('Using Loader', 'info', 'yui');
1324
            Y._loading = true;
1325
            loader = getLoader(Y);
1326
            loader.onEnd = handleLoader;
1327
            loader.context = Y;
1328
            loader.data = args;
1329
            loader.ignoreRegistered = false;
1330
            loader.require(missing);
1331
            loader.insert(null, (fetchCSS) ? null : 'js');
1332
 
1333
        } else if (boot && len && Y.Get && !Env.bootstrapped) {
1334
 
1335
            Y._loading = true;
1336
 
1337
            handleBoot = function() {
1338
                Y._loading = false;
1339
                queue.running = false;
1340
                Env.bootstrapped = true;
1341
                G_ENV._bootstrapping = false;
1342
                if (Y._attach(['loader'])) {
1343
                    Y._use(args, callback);
1344
                }
1345
            };
1346
 
1347
            if (G_ENV._bootstrapping) {
1348
Y.log('Waiting for loader', 'info', 'yui');
1349
                queue.add(handleBoot);
1350
            } else {
1351
                G_ENV._bootstrapping = true;
1352
Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
1353
                Y.Get.script(config.base + config.loaderPath, {
1354
                    onEnd: handleBoot
1355
                });
1356
            }
1357
 
1358
        } else {
1359
            Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
1360
            ret = Y._attach(args);
1361
            if (ret) {
1362
                handleLoader();
1363
            }
1364
        }
1365
 
1366
        return Y;
1367
    },
1368
 
1369
 
1370
    /**
1371
    Utility method for safely creating namespaces if they don't already exist.
1372
    May be called statically on the YUI global object or as a method on a YUI
1373
    instance.
1374
 
1375
    When called statically, a namespace will be created on the YUI global
1376
    object:
1377
 
1378
        // Create `YUI.your.namespace.here` as nested objects, preserving any
1379
        // objects that already exist instead of overwriting them.
1380
        YUI.namespace('your.namespace.here');
1381
 
1382
    When called as a method on a YUI instance, a namespace will be created on
1383
    that instance:
1384
 
1385
        // Creates `Y.property.package`.
1386
        Y.namespace('property.package');
1387
 
1388
    Dots in the input string cause `namespace` to create nested objects for each
1389
    token. If any part of the requested namespace already exists, the current
1390
    object will be left in place and will not be overwritten. This allows
1391
    multiple calls to `namespace` to preserve existing namespaced properties.
1392
 
1393
    If the first token in the namespace string is "YAHOO", that token is
1394
    discarded. This is legacy behavior for backwards compatibility with YUI 2.
1395
 
1396
    Be careful with namespace tokens. Reserved words may work in some browsers
1397
    and not others. For instance, the following will fail in some browsers
1398
    because the supported version of JavaScript reserves the word "long":
1399
 
1400
        Y.namespace('really.long.nested.namespace');
1401
 
1402
    Note: If you pass multiple arguments to create multiple namespaces, only the
1403
    last one created is returned from this function.
1404
 
1405
    @method namespace
1406
    @param {String} namespace* One or more namespaces to create.
1407
    @return {Object} Reference to the last namespace object created.
1408
    **/
1409
    namespace: function() {
1410
        var a = arguments, o, i = 0, j, d, arg;
1411
 
1412
        for (; i < a.length; i++) {
1413
            o = this; //Reset base object per argument or it will get reused from the last
1414
            arg = a[i];
1415
            if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1416
                d = arg.split(PERIOD);
1417
                for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1418
                    o[d[j]] = o[d[j]] || {};
1419
                    o = o[d[j]];
1420
                }
1421
            } else {
1422
                o[arg] = o[arg] || {};
1423
                o = o[arg]; //Reset base object to the new object so it's returned
1424
            }
1425
        }
1426
        return o;
1427
    },
1428
 
1429
    // this is replaced if the log module is included
1430
    log: NOOP,
1431
    message: NOOP,
1432
    // this is replaced if the dump module is included
1433
    dump: function (o) { return ''+o; },
1434
 
1435
    /**
1436
    Reports an error.
1437
 
1438
    The reporting mechanism is controlled by the `throwFail` configuration
1439
    attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
1440
    truthy, a JS exception is thrown.
1441
 
1442
    If an `errorFn` is specified in the config it must return `true` to indicate
1443
    that the exception was handled and keep it from being thrown.
1444
 
1445
    @method error
1446
    @param {String} msg Error message.
1447
    @param {Error|String} [e] JavaScript error object or an error string.
1448
    @param {String} [src] Source of the error (such as the name of the module in
1449
        which the error occurred).
1450
    @chainable
1451
    **/
1452
    error: function(msg, e, src) {
1453
        //TODO Add check for window.onerror here
1454
 
1455
        var Y = this, ret;
1456
 
1457
        if (Y.config.errorFn) {
1458
            ret = Y.config.errorFn.apply(Y, arguments);
1459
        }
1460
 
1461
        if (!ret) {
1462
            throw (e || new Error(msg));
1463
        } else {
1464
            Y.message(msg, 'error', ''+src); // don't scrub this one
1465
        }
1466
 
1467
        return Y;
1468
    },
1469
 
1470
    /**
1471
    Generates an id string that is unique among all YUI instances in this
1472
    execution context.
1473
 
1474
    @method guid
1475
    @param {String} [pre] Prefix.
1476
    @return {String} Unique id.
1477
    **/
1478
    guid: function(pre) {
1479
        var id = this.Env._guidp + '_' + (++this.Env._uidx);
1480
        return (pre) ? (pre + id) : id;
1481
    },
1482
 
1483
    /**
1484
    Returns a unique id associated with the given object and (if *readOnly* is
1485
    falsy) stamps the object with that id so it can be identified in the future.
1486
 
1487
    Stamping an object involves adding a `_yuid` property to it that contains
1488
    the object's id. One exception to this is that in Internet Explorer, DOM
1489
    nodes have a `uniqueID` property that contains a browser-generated unique
1490
    id, which will be used instead of a YUI-generated id when available.
1491
 
1492
    @method stamp
1493
    @param {Object} o Object to stamp.
1494
    @param {Boolean} readOnly If truthy and the given object has not already
1495
        been stamped, the object will not be modified and `null` will be
1496
        returned.
1497
    @return {String} Object's unique id, or `null` if *readOnly* was truthy and
1498
        the given object was not already stamped.
1499
    **/
1500
    stamp: function(o, readOnly) {
1501
        var uid;
1502
        if (!o) {
1503
            return o;
1504
        }
1505
 
1506
        // IE generates its own unique ID for dom nodes
1507
        // The uniqueID property of a document node returns a new ID
1508
        if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1509
            uid = o.uniqueID;
1510
        } else {
1511
            uid = (typeof o === 'string') ? o : o._yuid;
1512
        }
1513
 
1514
        if (!uid) {
1515
            uid = this.guid();
1516
            if (!readOnly) {
1517
                try {
1518
                    o._yuid = uid;
1519
                } catch (e) {
1520
                    uid = null;
1521
                }
1522
            }
1523
        }
1524
        return uid;
1525
    },
1526
 
1527
    /**
1528
    Destroys this YUI instance.
1529
 
1530
    @method destroy
1531
    @since 3.3.0
1532
    **/
1533
    destroy: function() {
1534
        var Y = this;
1535
        if (Y.Event) {
1536
            Y.Event._unload();
1537
        }
1538
        delete instances[Y.id];
1539
        delete Y.Env;
1540
        delete Y.config;
1541
    }
1542
 
1543
    /**
1544
    Safe `instanceof` wrapper that works around a memory leak in IE when the
1545
    object being tested is `window` or `document`.
1546
 
1547
    Unless you are testing objects that may be `window` or `document`, you
1548
    should use the native `instanceof` operator instead of this method.
1549
 
1550
    @method instanceOf
1551
    @param {Object} o Object to check.
1552
    @param {Object} type Class to check against.
1553
    @since 3.3.0
1554
    **/
1555
};
1556
 
1557
    YUI.prototype = proto;
1558
 
1559
    // inheritance utilities are not available yet
1560
    for (prop in proto) {
1561
        if (proto.hasOwnProperty(prop)) {
1562
            YUI[prop] = proto[prop];
1563
        }
1564
    }
1565
 
1566
    /**
1567
    Applies a configuration to all YUI instances in this execution context.
1568
 
1569
    The main use case for this method is in "mashups" where several third-party
1570
    scripts need to write to a global YUI config, but cannot share a single
1571
    centrally-managed config object. This way they can all call
1572
    `YUI.applyConfig({})` instead of overwriting the single global config.
1573
 
1574
    @example
1575
 
1576
        YUI.applyConfig({
1577
            modules: {
1578
                davglass: {
1579
                    fullpath: './davglass.js'
1580
                }
1581
            }
1582
        });
1583
 
1584
        YUI.applyConfig({
1585
            modules: {
1586
                foo: {
1587
                    fullpath: './foo.js'
1588
                }
1589
            }
1590
        });
1591
 
1592
        YUI().use('davglass', function (Y) {
1593
            // Module davglass will be available here.
1594
        });
1595
 
1596
    @method applyConfig
1597
    @param {Object} o Configuration object to apply.
1598
    @static
1599
    @since 3.5.0
1600
    **/
1601
    YUI.applyConfig = function(o) {
1602
        if (!o) {
1603
            return;
1604
        }
1605
        //If there is a GlobalConfig, apply it first to set the defaults
1606
        if (YUI.GlobalConfig) {
1607
            this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1608
        }
1609
        //Apply this config to it
1610
        this.prototype.applyConfig.call(this, o);
1611
        //Reset GlobalConfig to the combined config
1612
        YUI.GlobalConfig = this.config;
1613
    };
1614
 
1615
    // set up the environment
1616
    YUI._init();
1617
 
1618
    if (hasWin) {
1619
        add(doc, 'DOMContentLoaded', handleReady);
1620
 
1621
        // add a window load event at load time so we can capture
1622
        // the case where it fires before dynamic loading is
1623
        // complete.
1624
        add(window, 'load', handleLoad);
1625
    } else {
1626
        handleReady();
1627
        handleLoad();
1628
    }
1629
 
1630
    YUI.Env.add = add;
1631
    YUI.Env.remove = remove;
1632
 
1633
    /*global exports*/
1634
    // Support the CommonJS method for exporting our single global
1635
    if (typeof exports == 'object') {
1636
        exports.YUI = YUI;
1637
        /**
1638
        * Set a method to be called when `Get.script` is called in Node.js
1639
        * `Get` will open the file, then pass it's content and it's path
1640
        * to this method before attaching it. Commonly used for code coverage
1641
        * instrumentation. <strong>Calling this multiple times will only
1642
        * attach the last hook method</strong>. This method is only
1643
        * available in Node.js.
1644
        * @method setLoadHook
1645
        * @static
1646
        * @param {Function} fn The function to set
1647
        * @param {String} fn.data The content of the file
1648
        * @param {String} fn.path The file path of the file
1649
        */
1650
        YUI.setLoadHook = function(fn) {
1651
            YUI._getLoadHook = fn;
1652
        };
1653
        /**
1654
        * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
1655
        * @method _getLoadHook
1656
        * @private
1657
        * @param {String} data The content of the file
1658
        * @param {String} path The file path of the file
1659
        */
1660
        YUI._getLoadHook = null;
1661
    }
1662
 
1663
    YUI.Env[VERSION] = {};
1664
}());
1665
 
1666
 
1667
/**
1668
Config object that contains all of the configuration options for
1669
this `YUI` instance.
1670
 
1671
This object is supplied by the implementer when instantiating YUI. Some
1672
properties have default values if they are not supplied by the implementer.
1673
 
1674
This object should not be updated directly because some values are cached. Use
1675
`applyConfig()` to update the config object on a YUI instance that has already
1676
been configured.
1677
 
1678
@class config
1679
@static
1680
**/
1681
 
1682
/**
1683
If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
1684
if they're needed to load additional dependencies and aren't already available.
1685
 
1686
Setting this to `false` will prevent YUI from automatically loading the Loader
1687
and module metadata, so you will need to manually ensure that they're available
1688
or handle dependency resolution yourself.
1689
 
1690
@property {Boolean} bootstrap
1691
@default true
1692
**/
1693
 
1694
/**
1695
If `true`, `Y.log()` messages will be written to the browser's debug console
1696
when available and when `useBrowserConsole` is also `true`.
1697
 
1698
@property {Boolean} debug
1699
@default true
1700
**/
1701
 
1702
/**
1703
Log messages to the browser console if `debug` is `true` and the browser has a
1704
supported console.
1705
 
1706
@property {Boolean} useBrowserConsole
1707
@default true
1708
**/
1709
 
1710
/**
1711
A hash of log sources that should be logged. If specified, only messages from
1712
these sources will be logged. Others will be discarded.
1713
 
1714
@property {Object} logInclude
1715
@type object
1716
**/
1717
 
1718
/**
1719
A hash of log sources that should be not be logged. If specified, all sources
1720
will be logged *except* those on this list.
1721
 
1722
@property {Object} logExclude
1723
**/
1724
 
1725
/**
1726
When the YUI seed file is dynamically loaded after the `window.onload` event has
1727
fired, set this to `true` to tell YUI that it shouldn't wait for `window.onload`
1728
to occur.
1729
 
1730
This ensures that components that rely on `window.onload` and the `domready`
1731
custom event will work as expected even when YUI is dynamically injected.
1732
 
1733
@property {Boolean} injected
1734
@default false
1735
**/
1736
 
1737
/**
1738
If `true`, `Y.error()` will generate or re-throw a JavaScript error. Otherwise,
1739
errors are merely logged silently.
1740
 
1741
@property {Boolean} throwFail
1742
@default true
1743
**/
1744
 
1745
/**
1746
Reference to the global object for this execution context.
1747
 
1748
In a browser, this is the current `window` object. In Node.js, this is the
1749
Node.js `global` object.
1750
 
1751
@property {Object} global
1752
**/
1753
 
1754
/**
1755
The browser window or frame that this YUI instance should operate in.
1756
 
1757
When running in Node.js, this property is `undefined`, since there is no
1758
`window` object. Use `global` to get a reference to the global object that will
1759
work in both browsers and Node.js.
1760
 
1761
@property {Window} win
1762
**/
1763
 
1764
/**
1765
The browser `document` object associated with this YUI instance's `win` object.
1766
 
1767
When running in Node.js, this property is `undefined`, since there is no
1768
`document` object.
1769
 
1770
@property {Document} doc
1771
**/
1772
 
1773
/**
1774
A list of modules that defines the YUI core (overrides the default list).
1775
 
1776
@property {Array} core
1777
@type Array
1778
@default ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3']
1779
**/
1780
 
1781
/**
1782
A list of languages to use in order of preference.
1783
 
1784
This list is matched against the list of available languages in modules that the
1785
YUI instance uses to determine the best possible localization of language
1786
sensitive modules.
1787
 
1788
Languages are represented using BCP 47 language tags, such as "en-GB" for
1789
English as used in the United Kingdom, or "zh-Hans-CN" for simplified Chinese as
1790
used in China. The list may be provided as a comma-separated string or as an
1791
array.
1792
 
1793
@property {String|String[]} lang
1794
**/
1795
 
1796
/**
1797
Default date format.
1798
 
1799
@property {String} dateFormat
1800
@deprecated Use configuration in `DataType.Date.format()` instead.
1801
**/
1802
 
1803
/**
1804
Default locale.
1805
 
1806
@property {String} locale
1807
@deprecated Use `config.lang` instead.
1808
**/
1809
 
1810
/**
1811
Default generic polling interval in milliseconds.
1812
 
1813
@property {Number} pollInterval
1814
@default 20
1815
**/
1816
 
1817
/**
1818
The number of dynamic `<script>` nodes to insert by default before automatically
1819
removing them when loading scripts.
1820
 
1821
This applies only to script nodes because removing the node will not make the
1822
evaluated script unavailable. Dynamic CSS nodes are not auto purged, because
1823
removing a linked style sheet will also remove the style definitions.
1824
 
1825
@property {Number} purgethreshold
1826
@default 20
1827
**/
1828
 
1829
/**
1830
Delay in milliseconds to wait after a window `resize` event before firing the
1831
event. If another `resize` event occurs before this delay has elapsed, the
1832
delay will start over to ensure that `resize` events are throttled.
1833
 
1834
@property {Number} windowResizeDelay
1835
@default 40
1836
**/
1837
 
1838
/**
1839
Base directory for dynamic loading.
1840
 
1841
@property {String} base
1842
**/
1843
 
1844
/**
1845
Base URL for a dynamic combo handler. This will be used to make combo-handled
1846
module requests if `combine` is set to `true.
1847
 
1848
@property {String} comboBase
1849
@default "http://yui.yahooapis.com/combo?"
1850
**/
1851
 
1852
/**
1853
Root path to prepend to each module path when creating a combo-handled request.
1854
 
1855
This is updated for each YUI release to point to a specific version of the
1856
library; for example: "3.8.0/build/".
1857
 
1858
@property {String} root
1859
**/
1860
 
1861
/**
1862
Filter to apply to module urls. This filter will modify the default path for all
1863
modules.
1864
 
1865
The default path for the YUI library is the minified version of the files (e.g.,
1866
event-min.js). The filter property can be a predefined filter or a custom
1867
filter. The valid predefined filters are:
1868
 
1869
  - **debug**: Loads debug versions of modules (e.g., event-debug.js).
1870
  - **raw**: Loads raw, non-minified versions of modules without debug logging
1871
    (e.g., event.js).
1872
 
1873
You can also define a custom filter, which must be an object literal containing
1874
a search regular expression and a replacement string:
1875
 
1876
    myFilter: {
1877
        searchExp : "-min\\.js",
1878
        replaceStr: "-debug.js"
1879
    }
1880
 
1881
@property {Object|String} filter
1882
**/
1883
 
1884
/**
1885
Skin configuration and customizations.
1886
 
1887
@property {Object} skin
1888
@param {String} [skin.defaultSkin='sam'] Default skin name. This skin will be
1889
    applied automatically to skinnable components if not overridden by a
1890
    component-specific skin name.
1891
@param {String} [skin.base='assets/skins/'] Default base path for a skin,
1892
    relative to Loader's `base` path.
1893
@param {Object} [skin.overrides] Component-specific skin name overrides. Specify
1894
    a component name as the key and, as the value, a string or array of strings
1895
    for a skin or skins that should be loaded for that component instead of the
1896
    `defaultSkin`.
1897
**/
1898
 
1899
/**
1900
Hash of per-component filter specifications. If specified for a given component,
1901
this overrides the global `filter` config.
1902
 
1903
@example
1904
    YUI({
1905
        modules: {
1906
            'foo': './foo.js',
1907
            'bar': './bar.js',
1908
            'baz': './baz.js'
1909
        },
1910
        filters: {
1911
            'foo': {
1912
                searchExp: '.js',
1913
                replaceStr: '-coverage.js'
1914
            }
1915
        }
1916
    }).use('foo', 'bar', 'baz', function (Y) {
1917
        // foo-coverage.js is loaded
1918
        // bar.js is loaded
1919
        // baz.js is loaded
1920
    });
1921
 
1922
@property {Object} filters
1923
**/
1924
 
1925
/**
1926
If `true`, YUI will use a combo handler to load multiple modules in as few
1927
requests as possible.
1928
 
1929
The YUI CDN (which YUI uses by default) supports combo handling, but other
1930
servers may not. If the server from which you're loading YUI does not support
1931
combo handling, set this to `false`.
1932
 
1933
Providing a value for the `base` config property will cause `combine` to default
1934
to `false` instead of `true`.
1935
 
1936
@property {Boolean} combine
1937
@default true
1938
*/
1939
 
1940
/**
1941
Array of module names that should never be dynamically loaded.
1942
 
1943
@property {String[]} ignore
1944
**/
1945
 
1946
/**
1947
Array of module names that should always be loaded when required, even if
1948
already present on the page.
1949
 
1950
@property {String[]} force
1951
**/
1952
 
1953
/**
1954
DOM element or id that should be used as the insertion point for dynamically
1955
added `<script>` and `<link>` nodes.
1956
 
1957
@property {HTMLElement|String} insertBefore
1958
**/
1959
 
1960
/**
1961
Object hash containing attributes to add to dynamically added `<script>` nodes.
1962
 
1963
@property {Object} jsAttributes
1964
**/
1965
 
1966
/**
1967
Object hash containing attributes to add to dynamically added `<link>` nodes.
1968
 
1969
@property {Object} cssAttributes
1970
**/
1971
 
1972
/**
1973
Timeout in milliseconds before a dynamic JS or CSS request will be considered a
1974
failure. If not set, no timeout will be enforced.
1975
 
1976
@property {Number} timeout
1977
**/
1978
 
1979
/**
1980
A hash of module definitions to add to the list of available YUI modules. These
1981
modules can then be dynamically loaded via the `use()` method.
1982
 
1983
This is a hash in which keys are module names and values are objects containing
1984
module metadata.
1985
 
1986
See `Loader.addModule()` for the supported module metadata fields. Also see
1987
`groups`, which provides a way to configure the base and combo spec for a set of
1988
modules.
1989
 
1990
@example
1991
 
1992
    modules: {
1993
        mymod1: {
1994
            requires: ['node'],
1995
            fullpath: '/mymod1/mymod1.js'
1996
        },
1997
 
1998
        mymod2: {
1999
            requires: ['mymod1'],
2000
            fullpath: '/mymod2/mymod2.js'
2001
        },
2002
 
2003
        mymod3: '/js/mymod3.js',
2004
        mycssmod: '/css/mycssmod.css'
2005
    }
2006
 
2007
@property {Object} modules
2008
**/
2009
 
2010
/**
2011
Aliases are dynamic groups of modules that can be used as shortcuts.
2012
 
2013
@example
2014
 
2015
    YUI({
2016
        aliases: {
2017
            davglass: [ 'node', 'yql', 'dd' ],
2018
            mine: [ 'davglass', 'autocomplete']
2019
        }
2020
    }).use('mine', function (Y) {
2021
        // Node, YQL, DD & AutoComplete available here.
2022
    });
2023
 
2024
@property {Object} aliases
2025
**/
2026
 
2027
/**
2028
A hash of module group definitions.
2029
 
2030
For each group you can specify a list of modules and the base path and
2031
combo spec to use when dynamically loading the modules.
2032
 
2033
@example
2034
 
2035
    groups: {
2036
        yui2: {
2037
            // specify whether or not this group has a combo service
2038
            combine: true,
2039
 
2040
            // The comboSeperator to use with this group's combo handler
2041
            comboSep: ';',
2042
 
2043
            // The maxURLLength for this server
2044
            maxURLLength: 500,
2045
 
2046
            // the base path for non-combo paths
2047
            base: 'http://yui.yahooapis.com/2.8.0r4/build/',
2048
 
2049
            // the path to the combo service
2050
            comboBase: 'http://yui.yahooapis.com/combo?',
2051
 
2052
            // a fragment to prepend to the path attribute when
2053
            // when building combo urls
2054
            root: '2.8.0r4/build/',
2055
 
2056
            // the module definitions
2057
            modules:  {
2058
                yui2_yde: {
2059
                    path: "yahoo-dom-event/yahoo-dom-event.js"
2060
                },
2061
                yui2_anim: {
2062
                    path: "animation/animation.js",
2063
                    requires: ['yui2_yde']
2064
                }
2065
            }
2066
        }
2067
    }
2068
 
2069
@property {Object} groups
2070
**/
2071
 
2072
/**
2073
Path to the Loader JS file, relative to the `base` path.
2074
 
2075
This is used to dynamically bootstrap the Loader when it's needed and isn't yet
2076
available.
2077
 
2078
@property {String} loaderPath
2079
@default "loader/loader-min.js"
2080
**/
2081
 
2082
/**
2083
If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
2084
`false` to prevent YUI from loading any CSS, or set it to the string `"force"`
2085
to force CSS dependencies to be loaded even if their associated JS modules are
2086
already loaded.
2087
 
2088
@property {Boolean|String} fetchCSS
2089
@default true
2090
**/
2091
 
2092
/**
2093
Default gallery version used to build gallery module urls.
2094
 
2095
@property {String} gallery
2096
@since 3.1.0
2097
**/
2098
 
2099
/**
2100
Default YUI 2 version used to build YUI 2 module urls.
2101
 
2102
This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
2103
`2in3` config for pulling different revisions of the wrapped YUI 2 modules.
2104
 
2105
@property {String} yui2
2106
@default "2.9.0"
2107
@since 3.1.0
2108
**/
2109
 
2110
/**
2111
Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
2112
 
2113
@property {String} 2in3
2114
@default "4"
2115
@since 3.1.0
2116
**/
2117
 
2118
/**
2119
Alternate console log function that should be used in environments without a
2120
supported native console. This function is executed with the YUI instance as its
2121
`this` object.
2122
 
2123
@property {Function} logFn
2124
@since 3.1.0
2125
**/
2126
 
2127
/**
2128
The minimum log level to log messages for. Log levels are defined
2129
incrementally. Messages greater than or equal to the level specified will
2130
be shown. All others will be discarded. The order of log levels in
2131
increasing priority is:
2132
 
2133
    debug
2134
    info
2135
    warn
2136
    error
2137
 
2138
@property {String} logLevel
2139
@default 'debug'
2140
@since 3.10.0
2141
**/
2142
 
2143
/**
2144
Callback to execute when `Y.error()` is called. It receives the error message
2145
and a JavaScript error object if one was provided.
2146
 
2147
This function is executed with the YUI instance as its `this` object.
2148
 
2149
Returning `true` from this function will prevent an exception from being thrown.
2150
 
2151
@property {Function} errorFn
2152
@param {String} errorFn.msg Error message
2153
@param {Object} [errorFn.err] Error object (if one was provided).
2154
@since 3.2.0
2155
**/
2156
 
2157
/**
2158
A callback to execute when Loader fails to load one or more resources.
2159
 
2160
This could be because of a script load failure. It could also be because a
2161
module fails to register itself when the `requireRegistration` config is `true`.
2162
 
2163
If this function is defined, the `use()` callback will only be called when the
2164
loader succeeds. Otherwise, `use()` will always executes unless there was a
2165
JavaScript error when attaching a module.
2166
 
2167
@property {Function} loadErrorFn
2168
@since 3.3.0
2169
**/
2170
 
2171
/**
2172
If `true`, Loader will expect all loaded scripts to be first-class YUI modules
2173
that register themselves with the YUI global, and will trigger a failure if a
2174
loaded script does not register a YUI module.
2175
 
2176
@property {Boolean} requireRegistration
2177
@default false
2178
@since 3.3.0
2179
**/
2180
 
2181
/**
2182
Cache serviced use() requests.
2183
 
2184
@property {Boolean} cacheUse
2185
@default true
2186
@since 3.3.0
2187
@deprecated No longer used.
2188
**/
2189
 
2190
/**
2191
Whether or not YUI should use native ES5 functionality when available for
2192
features like `Y.Array.each()`, `Y.Object()`, etc.
2193
 
2194
When `false`, YUI will always use its own fallback implementations instead of
2195
relying on ES5 functionality, even when ES5 functionality is available.
2196
 
2197
@property {Boolean} useNativeES5
2198
@default true
2199
@since 3.5.0
2200
**/
2201
 
2202
/**
2203
 * Leverage native JSON stringify if the browser has a native
2204
 * implementation.  In general, this is a good idea.  See the Known Issues
2205
 * section in the JSON user guide for caveats.  The default value is true
2206
 * for browsers with native JSON support.
2207
 *
2208
 * @property useNativeJSONStringify
2209
 * @type Boolean
2210
 * @default true
2211
 * @since 3.8.0
2212
 */
2213
 
2214
 /**
2215
 * Leverage native JSON parse if the browser has a native implementation.
2216
 * In general, this is a good idea.  See the Known Issues section in the
2217
 * JSON user guide for caveats.  The default value is true for browsers with
2218
 * native JSON support.
2219
 *
2220
 * @property useNativeJSONParse
2221
 * @type Boolean
2222
 * @default true
2223
 * @since 3.8.0
2224
 */
2225
 
2226
/**
2227
Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
2228
 
2229
@property {Object|String} delayUntil
2230
@since 3.6.0
2231
@example
2232
 
2233
You can use `load` or `domready` strings by default:
2234
 
2235
    YUI({
2236
        delayUntil: 'domready'
2237
    }, function (Y) {
2238
        // This will not execute until 'domeready' occurs.
2239
    });
2240
 
2241
Or you can delay until a node is available (with `available` or `contentready`):
2242
 
2243
    YUI({
2244
        delayUntil: {
2245
            event: 'available',
2246
            args : '#foo'
2247
        }
2248
    }, function (Y) {
2249
        // This will not execute until a node matching the selector "#foo" is
2250
        // available in the DOM.
2251
    });
2252
 
2253
**/
2254
YUI.add('yui-base', function (Y, NAME) {
2255
 
2256
/*
2257
 * YUI stub
2258
 * @module yui
2259
 * @submodule yui-base
2260
 */
2261
/**
2262
 * The YUI module contains the components required for building the YUI
2263
 * seed file.  This includes the script loading mechanism, a simple queue,
2264
 * and the core utilities for the library.
2265
 * @module yui
2266
 * @submodule yui-base
2267
 */
2268
 
2269
/**
2270
 * Provides core language utilites and extensions used throughout YUI.
2271
 *
2272
 * @class Lang
2273
 * @static
2274
 */
2275
 
2276
var L = Y.Lang || (Y.Lang = {}),
2277
 
2278
STRING_PROTO = String.prototype,
2279
TOSTRING     = Object.prototype.toString,
2280
 
2281
TYPES = {
2282
    'undefined'        : 'undefined',
2283
    'number'           : 'number',
2284
    'boolean'          : 'boolean',
2285
    'string'           : 'string',
2286
    '[object Function]': 'function',
2287
    '[object RegExp]'  : 'regexp',
2288
    '[object Array]'   : 'array',
2289
    '[object Date]'    : 'date',
2290
    '[object Error]'   : 'error'
2291
},
2292
 
2293
SUBREGEX         = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
2294
 
2295
WHITESPACE       = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF",
2296
WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+",
2297
TRIM_LEFT_REGEX  = new RegExp("^" + WHITESPACE_CLASS),
2298
TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"),
2299
TRIMREGEX        = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"),
2300
 
2301
NATIVE_FN_REGEX  = /\{\s*\[(?:native code|function)\]\s*\}/i;
2302
 
2303
// -- Protected Methods --------------------------------------------------------
2304
 
2305
/**
2306
Returns `true` if the given function appears to be implemented in native code,
2307
`false` otherwise. Will always return `false` -- even in ES5-capable browsers --
2308
if the `useNativeES5` YUI config option is set to `false`.
2309
 
2310
This isn't guaranteed to be 100% accurate and won't work for anything other than
2311
functions, but it can be useful for determining whether a function like
2312
`Array.prototype.forEach` is native or a JS shim provided by another library.
2313
 
2314
There's a great article by @kangax discussing certain flaws with this technique:
2315
<http://perfectionkills.com/detecting-built-in-host-methods/>
2316
 
2317
While his points are valid, it's still possible to benefit from this function
2318
as long as it's used carefully and sparingly, and in such a way that false
2319
negatives have minimal consequences. It's used internally to avoid using
2320
potentially broken non-native ES5 shims that have been added to the page by
2321
other libraries.
2322
 
2323
@method _isNative
2324
@param {Function} fn Function to test.
2325
@return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
2326
@static
2327
@protected
2328
@since 3.5.0
2329
**/
2330
L._isNative = function (fn) {
2331
    return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
2332
};
2333
 
2334
// -- Public Methods -----------------------------------------------------------
2335
 
2336
/**
2337
 * Determines whether or not the provided item is an array.
2338
 *
2339
 * Returns `false` for array-like collections such as the function `arguments`
2340
 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
2341
 * test for an array-like collection.
2342
 *
2343
 * @method isArray
2344
 * @param o The object to test.
2345
 * @return {boolean} true if o is an array.
2346
 * @static
2347
 */
2348
L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
2349
    return L.type(o) === 'array';
2350
};
2351
 
2352
/**
2353
 * Determines whether or not the provided item is a boolean.
2354
 * @method isBoolean
2355
 * @static
2356
 * @param o The object to test.
2357
 * @return {boolean} true if o is a boolean.
2358
 */
2359
L.isBoolean = function(o) {
2360
    return typeof o === 'boolean';
2361
};
2362
 
2363
/**
2364
 * Determines whether or not the supplied item is a date instance.
2365
 * @method isDate
2366
 * @static
2367
 * @param o The object to test.
2368
 * @return {boolean} true if o is a date.
2369
 */
2370
L.isDate = function(o) {
2371
    return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
2372
};
2373
 
2374
/**
2375
 * <p>
2376
 * Determines whether or not the provided item is a function.
2377
 * Note: Internet Explorer thinks certain functions are objects:
2378
 * </p>
2379
 *
2380
 * <pre>
2381
 * var obj = document.createElement("object");
2382
 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
2383
 * &nbsp;
2384
 * var input = document.createElement("input"); // append to body
2385
 * Y.Lang.isFunction(input.focus) // reports false in IE
2386
 * </pre>
2387
 *
2388
 * <p>
2389
 * You will have to implement additional tests if these functions
2390
 * matter to you.
2391
 * </p>
2392
 *
2393
 * @method isFunction
2394
 * @static
2395
 * @param o The object to test.
2396
 * @return {boolean} true if o is a function.
2397
 */
2398
L.isFunction = function(o) {
2399
    return L.type(o) === 'function';
2400
};
2401
 
2402
/**
2403
 * Determines whether or not the provided item is null.
2404
 * @method isNull
2405
 * @static
2406
 * @param o The object to test.
2407
 * @return {boolean} true if o is null.
2408
 */
2409
L.isNull = function(o) {
2410
    return o === null;
2411
};
2412
 
2413
/**
2414
 * Determines whether or not the provided item is a legal number.
2415
 * @method isNumber
2416
 * @static
2417
 * @param o The object to test.
2418
 * @return {boolean} true if o is a number.
2419
 */
2420
L.isNumber = function(o) {
2421
    return typeof o === 'number' && isFinite(o);
2422
};
2423
 
2424
/**
2425
 * Determines whether or not the provided item is of type object
2426
 * or function. Note that arrays are also objects, so
2427
 * <code>Y.Lang.isObject([]) === true</code>.
2428
 * @method isObject
2429
 * @static
2430
 * @param o The object to test.
2431
 * @param failfn {boolean} fail if the input is a function.
2432
 * @return {boolean} true if o is an object.
2433
 * @see isPlainObject
2434
 */
2435
L.isObject = function(o, failfn) {
2436
    var t = typeof o;
2437
    return (o && (t === 'object' ||
2438
        (!failfn && (t === 'function' || L.isFunction(o))))) || false;
2439
};
2440
 
2441
/**
2442
 * Determines whether or not the provided value is a regexp.
2443
 * @method isRegExp
2444
 * @static
2445
 * @param value The value or object to test.
2446
 * @return {boolean} true if value is a regexp.
2447
 */
2448
L.isRegExp = function(value) {
2449
    return L.type(value) === 'regexp';
2450
};
2451
 
2452
/**
2453
 * Determines whether or not the provided item is a string.
2454
 * @method isString
2455
 * @static
2456
 * @param o The object to test.
2457
 * @return {boolean} true if o is a string.
2458
 */
2459
L.isString = function(o) {
2460
    return typeof o === 'string';
2461
};
2462
 
2463
/**
2464
 * Determines whether or not the provided item is undefined.
2465
 * @method isUndefined
2466
 * @static
2467
 * @param o The object to test.
2468
 * @return {boolean} true if o is undefined.
2469
 */
2470
L.isUndefined = function(o) {
2471
    return typeof o === 'undefined';
2472
};
2473
 
2474
/**
2475
 * A convenience method for detecting a legitimate non-null value.
2476
 * Returns false for null/undefined/NaN, true for other values,
2477
 * including 0/false/''
2478
 * @method isValue
2479
 * @static
2480
 * @param o The item to test.
2481
 * @return {boolean} true if it is not null/undefined/NaN || false.
2482
 */
2483
L.isValue = function(o) {
2484
    var t = L.type(o);
2485
 
2486
    switch (t) {
2487
        case 'number':
2488
            return isFinite(o);
2489
 
2490
        case 'null': // fallthru
2491
        case 'undefined':
2492
            return false;
2493
 
2494
        default:
2495
            return !!t;
2496
    }
2497
};
2498
 
2499
/**
2500
 * Returns the current time in milliseconds.
2501
 *
2502
 * @method now
2503
 * @return {Number} Current time in milliseconds.
2504
 * @static
2505
 * @since 3.3.0
2506
 */
2507
L.now = Date.now || function () {
2508
    return new Date().getTime();
2509
};
2510
 
2511
/**
2512
 * Performs `{placeholder}` substitution on a string. The object passed as the
2513
 * second parameter provides values to replace the `{placeholder}`s.
2514
 * `{placeholder}` token names must match property names of the object. For example,
2515
 *
2516
 *`var greeting = Y.Lang.sub("Hello, {who}!", { who: "World" });`
2517
 *
2518
 * `{placeholder}` tokens that are undefined on the object map will be left
2519
 * in tact (leaving unsightly `{placeholder}`'s in the output string).
2520
 *
2521
 * @method sub
2522
 * @param {string} s String to be modified.
2523
 * @param {object} o Object containing replacement values.
2524
 * @return {string} the substitute result.
2525
 * @static
2526
 * @since 3.2.0
2527
 */
2528
L.sub = function(s, o) {
2529
 
2530
    /**
2531
    Finds the value of `key` in given object.
2532
    If the key has a 'dot' notation e.g. 'foo.bar.baz', the function will
2533
    try to resolve this path if it doesn't exist as a property
2534
    @example
2535
        value({ 'a.b': 1, a: { b: 2 } }, 'a.b'); // 1
2536
        value({ a: { b: 2 } }          , 'a.b'); // 2
2537
    @param {Object} obj A key/value pairs object
2538
    @param {String} key
2539
    @return {Any}
2540
    @private
2541
    **/
2542
    function value(obj, key) {
2543
 
2544
        var subkey;
2545
 
2546
        if ( typeof obj[key] !== 'undefined' ) {
2547
            return obj[key];
2548
        }
2549
 
2550
        key    = key.split('.');         // given 'a.b.c'
2551
        subkey = key.slice(1).join('.'); // 'b.c'
2552
        key    = key[0];                 // 'a'
2553
 
2554
        // special case for null as typeof returns object and we don't want that.
2555
        if ( subkey && typeof obj[key] === 'object' && obj[key] !== null ) {
2556
            return value(obj[key], subkey);
2557
        }
2558
    }
2559
 
2560
    return s.replace ? s.replace(SUBREGEX, function (match, key) {
2561
        var val = key.indexOf('.')>-1 ? value(o, key) : o[key];
2562
        return typeof val === 'undefined' ? match : val;
2563
    }) : s;
2564
};
2565
 
2566
/**
2567
 * Returns a string without any leading or trailing whitespace.  If
2568
 * the input is not a string, the input will be returned untouched.
2569
 * @method trim
2570
 * @static
2571
 * @param s {string} the string to trim.
2572
 * @return {string} the trimmed string.
2573
 */
2574
L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) {
2575
    return s && s.trim ? s.trim() : s;
2576
} : function (s) {
2577
    try {
2578
        return s.replace(TRIMREGEX, '');
2579
    } catch (e) {
2580
        return s;
2581
    }
2582
};
2583
 
2584
/**
2585
 * Returns a string without any leading whitespace.
2586
 * @method trimLeft
2587
 * @static
2588
 * @param s {string} the string to trim.
2589
 * @return {string} the trimmed string.
2590
 */
2591
L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) {
2592
    return s.trimLeft();
2593
} : function (s) {
2594
    return s.replace(TRIM_LEFT_REGEX, '');
2595
};
2596
 
2597
/**
2598
 * Returns a string without any trailing whitespace.
2599
 * @method trimRight
2600
 * @static
2601
 * @param s {string} the string to trim.
2602
 * @return {string} the trimmed string.
2603
 */
2604
L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) {
2605
    return s.trimRight();
2606
} : function (s) {
2607
    return s.replace(TRIM_RIGHT_REGEX, '');
2608
};
2609
 
2610
/**
2611
Returns one of the following strings, representing the type of the item passed
2612
in:
2613
 
2614
 * "array"
2615
 * "boolean"
2616
 * "date"
2617
 * "error"
2618
 * "function"
2619
 * "null"
2620
 * "number"
2621
 * "object"
2622
 * "regexp"
2623
 * "string"
2624
 * "undefined"
2625
 
2626
Known issues:
2627
 
2628
 * `typeof HTMLElementCollection` returns function in Safari, but
2629
    `Y.Lang.type()` reports "object", which could be a good thing --
2630
    but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2631
 
2632
@method type
2633
@param o the item to test.
2634
@return {string} the detected type.
2635
@static
2636
**/
2637
L.type = function(o) {
2638
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2639
};
2640
/**
2641
@module yui
2642
@submodule yui-base
2643
*/
2644
 
2645
var Lang   = Y.Lang,
2646
    Native = Array.prototype,
2647
 
2648
    hasOwn = Object.prototype.hasOwnProperty;
2649
 
2650
/**
2651
Provides utility methods for working with arrays. Additional array helpers can
2652
be found in the `collection` and `array-extras` modules.
2653
 
2654
`Y.Array(thing)` returns a native array created from _thing_. Depending on
2655
_thing_'s type, one of the following will happen:
2656
 
2657
  * Arrays are returned unmodified unless a non-zero _startIndex_ is
2658
    specified.
2659
  * Array-like collections (see `Array.test()`) are converted to arrays.
2660
  * For everything else, a new array is created with _thing_ as the sole
2661
    item.
2662
 
2663
Note: elements that are also collections, such as `<form>` and `<select>`
2664
elements, are not automatically converted to arrays. To force a conversion,
2665
pass `true` as the value of the _force_ parameter.
2666
 
2667
@class Array
2668
@constructor
2669
@param {Any} thing The thing to arrayify.
2670
@param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2671
  collection, a subset of items starting at the specified index will be
2672
  returned.
2673
@param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2674
  array-like collection no matter what.
2675
@return {Array} A native array created from _thing_, according to the rules
2676
  described above.
2677
**/
2678
function YArray(thing, startIndex, force) {
2679
    var len, result;
2680
 
2681
    /*jshint expr: true*/
2682
    startIndex || (startIndex = 0);
2683
 
2684
    if (force || YArray.test(thing)) {
2685
        // IE throws when trying to slice HTMLElement collections.
2686
        try {
2687
            return Native.slice.call(thing, startIndex);
2688
        } catch (ex) {
2689
            result = [];
2690
 
2691
            for (len = thing.length; startIndex < len; ++startIndex) {
2692
                result.push(thing[startIndex]);
2693
            }
2694
 
2695
            return result;
2696
        }
2697
    }
2698
 
2699
    return [thing];
2700
}
2701
 
2702
Y.Array = YArray;
2703
 
2704
/**
2705
Dedupes an array of strings, returning an array that's guaranteed to contain
2706
only one copy of a given string.
2707
 
2708
This method differs from `Array.unique()` in that it's optimized for use only
2709
with arrays consisting entirely of strings or entirely of numbers, whereas
2710
`unique` may be used with other value types (but is slower).
2711
 
2712
Using `dedupe()` with values other than strings or numbers, or with arrays
2713
containing a mix of strings and numbers, may result in unexpected behavior.
2714
 
2715
@method dedupe
2716
@param {String[]|Number[]} array Array of strings or numbers to dedupe.
2717
@return {Array} Copy of _array_ containing no duplicate values.
2718
@static
2719
@since 3.4.0
2720
**/
2721
YArray.dedupe = Lang._isNative(Object.create) ? function (array) {
2722
    var hash    = Object.create(null),
2723
        results = [],
2724
        i, item, len;
2725
 
2726
    for (i = 0, len = array.length; i < len; ++i) {
2727
        item = array[i];
2728
 
2729
        if (!hash[item]) {
2730
            hash[item] = 1;
2731
            results.push(item);
2732
        }
2733
    }
2734
 
2735
    return results;
2736
} : function (array) {
2737
    var hash    = {},
2738
        results = [],
2739
        i, item, len;
2740
 
2741
    for (i = 0, len = array.length; i < len; ++i) {
2742
        item = array[i];
2743
 
2744
        if (!hasOwn.call(hash, item)) {
2745
            hash[item] = 1;
2746
            results.push(item);
2747
        }
2748
    }
2749
 
2750
    return results;
2751
};
2752
 
2753
/**
2754
Executes the supplied function on each item in the array. This method wraps
2755
the native ES5 `Array.forEach()` method if available.
2756
 
2757
@method each
2758
@param {Array} array Array to iterate.
2759
@param {Function} fn Function to execute on each item in the array. The function
2760
  will receive the following arguments:
2761
    @param {Any} fn.item Current array item.
2762
    @param {Number} fn.index Current array index.
2763
    @param {Array} fn.array Array being iterated.
2764
@param {Object} [thisObj] `this` object to use when calling _fn_.
2765
@return {YUI} The YUI instance.
2766
@static
2767
**/
2768
YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2769
    Native.forEach.call(array || [], fn, thisObj || Y);
2770
    return Y;
2771
} : function (array, fn, thisObj) {
2772
    for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2773
        if (i in array) {
2774
            fn.call(thisObj || Y, array[i], i, array);
2775
        }
2776
    }
2777
 
2778
    return Y;
2779
};
2780
 
2781
/**
2782
Alias for `each()`.
2783
 
2784
@method forEach
2785
@static
2786
**/
2787
 
2788
/**
2789
Returns an object using the first array as keys and the second as values. If
2790
the second array is not provided, or if it doesn't contain the same number of
2791
values as the first array, then `true` will be used in place of the missing
2792
values.
2793
 
2794
@example
2795
 
2796
    Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2797
    // => {a: 'foo', b: 'bar', c: true}
2798
 
2799
@method hash
2800
@param {String[]} keys Array of strings to use as keys.
2801
@param {Array} [values] Array to use as values.
2802
@return {Object} Hash using the first array as keys and the second as values.
2803
@static
2804
**/
2805
YArray.hash = function (keys, values) {
2806
    var hash = {},
2807
        vlen = (values && values.length) || 0,
2808
        i, len;
2809
 
2810
    for (i = 0, len = keys.length; i < len; ++i) {
2811
        if (i in keys) {
2812
            hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2813
        }
2814
    }
2815
 
2816
    return hash;
2817
};
2818
 
2819
/**
2820
Returns the index of the first item in the array that's equal (using a strict
2821
equality check) to the specified _value_, or `-1` if the value isn't found.
2822
 
2823
This method wraps the native ES5 `Array.indexOf()` method if available.
2824
 
2825
@method indexOf
2826
@param {Array} array Array to search.
2827
@param {Any} value Value to search for.
2828
@param {Number} [from=0] The index at which to begin the search.
2829
@return {Number} Index of the item strictly equal to _value_, or `-1` if not
2830
    found.
2831
@static
2832
**/
2833
YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2834
    return Native.indexOf.call(array, value, from);
2835
} : function (array, value, from) {
2836
    // http://es5.github.com/#x15.4.4.14
2837
    var len = array.length;
2838
 
2839
    from = +from || 0;
2840
    from = (from > 0 || -1) * Math.floor(Math.abs(from));
2841
 
2842
    if (from < 0) {
2843
        from += len;
2844
 
2845
        if (from < 0) {
2846
            from = 0;
2847
        }
2848
    }
2849
 
2850
    for (; from < len; ++from) {
2851
        if (from in array && array[from] === value) {
2852
            return from;
2853
        }
2854
    }
2855
 
2856
    return -1;
2857
};
2858
 
2859
/**
2860
Numeric sort convenience function.
2861
 
2862
The native `Array.prototype.sort()` function converts values to strings and
2863
sorts them in lexicographic order, which is unsuitable for sorting numeric
2864
values. Provide `Array.numericSort` as a custom sort function when you want
2865
to sort values in numeric order.
2866
 
2867
@example
2868
 
2869
    [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2870
    // => [4, 8, 15, 16, 23, 42]
2871
 
2872
@method numericSort
2873
@param {Number} a First value to compare.
2874
@param {Number} b Second value to compare.
2875
@return {Number} Difference between _a_ and _b_.
2876
@static
2877
**/
2878
YArray.numericSort = function (a, b) {
2879
    return a - b;
2880
};
2881
 
2882
/**
2883
Executes the supplied function on each item in the array. Returning a truthy
2884
value from the function will stop the processing of remaining items.
2885
 
2886
@method some
2887
@param {Array} array Array to iterate over.
2888
@param {Function} fn Function to execute on each item. The function will receive
2889
  the following arguments:
2890
    @param {Any} fn.value Current array item.
2891
    @param {Number} fn.index Current array index.
2892
    @param {Array} fn.array Array being iterated over.
2893
@param {Object} [thisObj] `this` object to use when calling _fn_.
2894
@return {Boolean} `true` if the function returns a truthy value on any of the
2895
  items in the array; `false` otherwise.
2896
@static
2897
**/
2898
YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2899
    return Native.some.call(array, fn, thisObj);
2900
} : function (array, fn, thisObj) {
2901
    for (var i = 0, len = array.length; i < len; ++i) {
2902
        if (i in array && fn.call(thisObj, array[i], i, array)) {
2903
            return true;
2904
        }
2905
    }
2906
 
2907
    return false;
2908
};
2909
 
2910
/**
2911
Evaluates _obj_ to determine if it's an array, an array-like collection, or
2912
something else. This is useful when working with the function `arguments`
2913
collection and `HTMLElement` collections.
2914
 
2915
Note: This implementation doesn't consider elements that are also
2916
collections, such as `<form>` and `<select>`, to be array-like.
2917
 
2918
@method test
2919
@param {Object} obj Object to test.
2920
@return {Number} A number indicating the results of the test:
2921
 
2922
  * 0: Neither an array nor an array-like collection.
2923
  * 1: Real array.
2924
  * 2: Array-like collection.
2925
 
2926
@static
2927
**/
2928
YArray.test = function (obj) {
2929
    var result = 0;
2930
 
2931
    if (Lang.isArray(obj)) {
2932
        result = 1;
2933
    } else if (Lang.isObject(obj)) {
2934
        try {
2935
            // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
2936
            // or functions without apply/call (Safari
2937
            // HTMLElementCollection bug).
2938
            if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
2939
                result = 2;
2940
            }
2941
        } catch (ex) {}
2942
    }
2943
 
2944
    return result;
2945
};
2946
/**
2947
 * The YUI module contains the components required for building the YUI
2948
 * seed file.  This includes the script loading mechanism, a simple queue,
2949
 * and the core utilities for the library.
2950
 * @module yui
2951
 * @submodule yui-base
2952
 */
2953
 
2954
/**
2955
 * A simple FIFO queue.  Items are added to the Queue with add(1..n items) and
2956
 * removed using next().
2957
 *
2958
 * @class Queue
2959
 * @constructor
2960
 * @param {MIXED} item* 0..n items to seed the queue.
2961
 */
2962
function Queue() {
2963
    this._init();
2964
    this.add.apply(this, arguments);
2965
}
2966
 
2967
Queue.prototype = {
2968
    /**
2969
     * Initialize the queue
2970
     *
2971
     * @method _init
2972
     * @protected
2973
     */
2974
    _init: function() {
2975
        /**
2976
         * The collection of enqueued items
2977
         *
2978
         * @property _q
2979
         * @type Array
2980
         * @protected
2981
         */
2982
        this._q = [];
2983
    },
2984
 
2985
    /**
2986
     * Get the next item in the queue. FIFO support
2987
     *
2988
     * @method next
2989
     * @return {MIXED} the next item in the queue.
2990
     */
2991
    next: function() {
2992
        return this._q.shift();
2993
    },
2994
 
2995
    /**
2996
     * Get the last in the queue. LIFO support.
2997
     *
2998
     * @method last
2999
     * @return {MIXED} the last item in the queue.
3000
     */
3001
    last: function() {
3002
        return this._q.pop();
3003
    },
3004
 
3005
    /**
3006
     * Add 0..n items to the end of the queue.
3007
     *
3008
     * @method add
3009
     * @param {MIXED} item* 0..n items.
3010
     * @return {object} this queue.
3011
     */
3012
    add: function() {
3013
        this._q.push.apply(this._q, arguments);
3014
 
3015
        return this;
3016
    },
3017
 
3018
    /**
3019
     * Returns the current number of queued items.
3020
     *
3021
     * @method size
3022
     * @return {Number} The size.
3023
     */
3024
    size: function() {
3025
        return this._q.length;
3026
    }
3027
};
3028
 
3029
Y.Queue = Queue;
3030
 
3031
YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
3032
 
3033
/**
3034
The YUI module contains the components required for building the YUI seed file.
3035
This includes the script loading mechanism, a simple queue, and the core
3036
utilities for the library.
3037
 
3038
@module yui
3039
@submodule yui-base
3040
**/
3041
 
3042
var CACHED_DELIMITER = '__',
3043
 
3044
    hasOwn   = Object.prototype.hasOwnProperty,
3045
    isObject = Y.Lang.isObject;
3046
 
3047
/**
3048
Returns a wrapper for a function which caches the return value of that function,
3049
keyed off of the combined string representation of the argument values provided
3050
when the wrapper is called.
3051
 
3052
Calling this function again with the same arguments will return the cached value
3053
rather than executing the wrapped function.
3054
 
3055
Note that since the cache is keyed off of the string representation of arguments
3056
passed to the wrapper function, arguments that aren't strings and don't provide
3057
a meaningful `toString()` method may result in unexpected caching behavior. For
3058
example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
3059
string `[object Object]` when used as a cache key.
3060
 
3061
@method cached
3062
@param {Function} source The function to memoize.
3063
@param {Object} [cache={}] Object in which to store cached values. You may seed
3064
  this object with pre-existing cached values if desired.
3065
@param {any} [refetch] If supplied, this value is compared with the cached value
3066
  using a `==` comparison. If the values are equal, the wrapped function is
3067
  executed again even though a cached value exists.
3068
@return {Function} Wrapped function.
3069
@for YUI
3070
**/
3071
Y.cached = function (source, cache, refetch) {
3072
    /*jshint expr: true*/
3073
    cache || (cache = {});
3074
 
3075
    return function (arg) {
3076
        var key = arguments.length > 1 ?
3077
                Array.prototype.join.call(arguments, CACHED_DELIMITER) :
3078
                String(arg);
3079
 
3080
        /*jshint eqeqeq: false*/
3081
        if (!(key in cache) || (refetch && cache[key] == refetch)) {
3082
            cache[key] = source.apply(source, arguments);
3083
        }
3084
 
3085
        return cache[key];
3086
    };
3087
};
3088
 
3089
/**
3090
Returns the `location` object from the window/frame in which this YUI instance
3091
operates, or `undefined` when executing in a non-browser environment
3092
(e.g. Node.js).
3093
 
3094
It is _not_ recommended to hold references to the `window.location` object
3095
outside of the scope of a function in which its properties are being accessed or
3096
its methods are being called. This is because of a nasty bug/issue that exists
3097
in both Safari and MobileSafari browsers:
3098
[WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
3099
 
3100
@method getLocation
3101
@return {location} The `location` object from the window/frame in which this YUI
3102
    instance operates.
3103
@since 3.5.0
3104
**/
3105
Y.getLocation = function () {
3106
    // It is safer to look this up every time because yui-base is attached to a
3107
    // YUI instance before a user's config is applied; i.e. `Y.config.win` does
3108
    // not point the correct window object when this file is loaded.
3109
    var win = Y.config.win;
3110
 
3111
    // It is not safe to hold a reference to the `location` object outside the
3112
    // scope in which it is being used. The WebKit engine used in Safari and
3113
    // MobileSafari will "disconnect" the `location` object from the `window`
3114
    // when a page is restored from back/forward history cache.
3115
    return win && win.location;
3116
};
3117
 
3118
/**
3119
Returns a new object containing all of the properties of all the supplied
3120
objects. The properties from later objects will overwrite those in earlier
3121
objects.
3122
 
3123
Passing in a single object will create a shallow copy of it. For a deep copy,
3124
use `clone()`.
3125
 
3126
@method merge
3127
@param {Object} objects* One or more objects to merge.
3128
@return {Object} A new merged object.
3129
**/
3130
Y.merge = function () {
3131
    var i      = 0,
3132
        len    = arguments.length,
3133
        result = {},
3134
        key,
3135
        obj;
3136
 
3137
    for (; i < len; ++i) {
3138
        obj = arguments[i];
3139
 
3140
        for (key in obj) {
3141
            if (hasOwn.call(obj, key)) {
3142
                result[key] = obj[key];
3143
            }
3144
        }
3145
    }
3146
 
3147
    return result;
3148
};
3149
 
3150
/**
3151
Mixes _supplier_'s properties into _receiver_.
3152
 
3153
Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
3154
shadowed unless the _overwrite_ parameter is `true`, and will not be merged
3155
unless the _merge_ parameter is `true`.
3156
 
3157
In the default mode (0), only properties the supplier owns are copied (prototype
3158
properties are not copied). The following copying modes are available:
3159
 
3160
  * `0`: _Default_. Object to object.
3161
  * `1`: Prototype to prototype.
3162
  * `2`: Prototype to prototype and object to object.
3163
  * `3`: Prototype to object.
3164
  * `4`: Object to prototype.
3165
 
3166
@method mix
3167
@param {Function|Object} receiver The object or function to receive the mixed
3168
  properties.
3169
@param {Function|Object} supplier The object or function supplying the
3170
  properties to be mixed.
3171
@param {Boolean} [overwrite=false] If `true`, properties that already exist
3172
  on the receiver will be overwritten with properties from the supplier.
3173
@param {String[]} [whitelist] An array of property names to copy. If
3174
  specified, only the whitelisted properties will be copied, and all others
3175
  will be ignored.
3176
@param {Number} [mode=0] Mix mode to use. See above for available modes.
3177
@param {Boolean} [merge=false] If `true`, objects and arrays that already
3178
  exist on the receiver will have the corresponding object/array from the
3179
  supplier merged into them, rather than being skipped or overwritten. When
3180
  both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
3181
@return {Function|Object|YUI} The receiver, or the YUI instance if the
3182
  specified receiver is falsy.
3183
**/
3184
Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
3185
    var alwaysOverwrite, exists, from, i, key, len, to;
3186
 
3187
    // If no supplier is given, we return the receiver. If no receiver is given,
3188
    // we return Y. Returning Y doesn't make much sense to me, but it's
3189
    // grandfathered in for backcompat reasons.
3190
    if (!receiver || !supplier) {
3191
        return receiver || Y;
3192
    }
3193
 
3194
    if (mode) {
3195
        // In mode 2 (prototype to prototype and object to object), we recurse
3196
        // once to do the proto to proto mix. The object to object mix will be
3197
        // handled later on.
3198
        if (mode === 2) {
3199
            Y.mix(receiver.prototype, supplier.prototype, overwrite,
3200
                    whitelist, 0, merge);
3201
        }
3202
 
3203
        // Depending on which mode is specified, we may be copying from or to
3204
        // the prototypes of the supplier and receiver.
3205
        from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
3206
        to   = mode === 1 || mode === 4 ? receiver.prototype : receiver;
3207
 
3208
        // If either the supplier or receiver doesn't actually have a
3209
        // prototype property, then we could end up with an undefined `from`
3210
        // or `to`. If that happens, we abort and return the receiver.
3211
        if (!from || !to) {
3212
            return receiver;
3213
        }
3214
    } else {
3215
        from = supplier;
3216
        to   = receiver;
3217
    }
3218
 
3219
    // If `overwrite` is truthy and `merge` is falsy, then we can skip a
3220
    // property existence check on each iteration and save some time.
3221
    alwaysOverwrite = overwrite && !merge;
3222
 
3223
    if (whitelist) {
3224
        for (i = 0, len = whitelist.length; i < len; ++i) {
3225
            key = whitelist[i];
3226
 
3227
            // We call `Object.prototype.hasOwnProperty` instead of calling
3228
            // `hasOwnProperty` on the object itself, since the object's
3229
            // `hasOwnProperty` method may have been overridden or removed.
3230
            // Also, some native objects don't implement a `hasOwnProperty`
3231
            // method.
3232
            if (!hasOwn.call(from, key)) {
3233
                continue;
3234
            }
3235
 
3236
            // The `key in to` check here is (sadly) intentional for backwards
3237
            // compatibility reasons. It prevents undesired shadowing of
3238
            // prototype members on `to`.
3239
            exists = alwaysOverwrite ? false : key in to;
3240
 
3241
            if (merge && exists && isObject(to[key], true)
3242
                    && isObject(from[key], true)) {
3243
                // If we're in merge mode, and the key is present on both
3244
                // objects, and the value on both objects is either an object or
3245
                // an array (but not a function), then we recurse to merge the
3246
                // `from` value into the `to` value instead of overwriting it.
3247
                //
3248
                // Note: It's intentional that the whitelist isn't passed to the
3249
                // recursive call here. This is legacy behavior that lots of
3250
                // code still depends on.
3251
                Y.mix(to[key], from[key], overwrite, null, 0, merge);
3252
            } else if (overwrite || !exists) {
3253
                // We're not in merge mode, so we'll only copy the `from` value
3254
                // to the `to` value if we're in overwrite mode or if the
3255
                // current key doesn't exist on the `to` object.
3256
                to[key] = from[key];
3257
            }
3258
        }
3259
    } else {
3260
        for (key in from) {
3261
            // The code duplication here is for runtime performance reasons.
3262
            // Combining whitelist and non-whitelist operations into a single
3263
            // loop or breaking the shared logic out into a function both result
3264
            // in worse performance, and Y.mix is critical enough that the byte
3265
            // tradeoff is worth it.
3266
            if (!hasOwn.call(from, key)) {
3267
                continue;
3268
            }
3269
 
3270
            // The `key in to` check here is (sadly) intentional for backwards
3271
            // compatibility reasons. It prevents undesired shadowing of
3272
            // prototype members on `to`.
3273
            exists = alwaysOverwrite ? false : key in to;
3274
 
3275
            if (merge && exists && isObject(to[key], true)
3276
                    && isObject(from[key], true)) {
3277
                Y.mix(to[key], from[key], overwrite, null, 0, merge);
3278
            } else if (overwrite || !exists) {
3279
                to[key] = from[key];
3280
            }
3281
        }
3282
 
3283
        // If this is an IE browser with the JScript enumeration bug, force
3284
        // enumeration of the buggy properties by making a recursive call with
3285
        // the buggy properties as the whitelist.
3286
        if (Y.Object._hasEnumBug) {
3287
            Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
3288
        }
3289
    }
3290
 
3291
    return receiver;
3292
};
3293
/**
3294
 * The YUI module contains the components required for building the YUI
3295
 * seed file.  This includes the script loading mechanism, a simple queue,
3296
 * and the core utilities for the library.
3297
 * @module yui
3298
 * @submodule yui-base
3299
 */
3300
 
3301
/**
3302
 * Adds utilities to the YUI instance for working with objects.
3303
 *
3304
 * @class Object
3305
 */
3306
 
3307
var Lang   = Y.Lang,
3308
    hasOwn = Object.prototype.hasOwnProperty,
3309
 
3310
    UNDEFINED, // <-- Note the comma. We're still declaring vars.
3311
 
3312
/**
3313
 * Returns a new object that uses _obj_ as its prototype. This method wraps the
3314
 * native ES5 `Object.create()` method if available, but doesn't currently
3315
 * pass through `Object.create()`'s second argument (properties) in order to
3316
 * ensure compatibility with older browsers.
3317
 *
3318
 * @method ()
3319
 * @param {Object} obj Prototype object.
3320
 * @return {Object} New object using _obj_ as its prototype.
3321
 * @static
3322
 */
3323
O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
3324
    // We currently wrap the native Object.create instead of simply aliasing it
3325
    // to ensure consistency with our fallback shim, which currently doesn't
3326
    // support Object.create()'s second argument (properties). Once we have a
3327
    // safe fallback for the properties arg, we can stop wrapping
3328
    // Object.create().
3329
    return Object.create(obj);
3330
} : (function () {
3331
    // Reusable constructor function for the Object.create() shim.
3332
    function F() {}
3333
 
3334
    // The actual shim.
3335
    return function (obj) {
3336
        F.prototype = obj;
3337
        return new F();
3338
    };
3339
}()),
3340
 
3341
/**
3342
 * Property names that IE doesn't enumerate in for..in loops, even when they
3343
 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
3344
 * manually enumerate these properties.
3345
 *
3346
 * @property _forceEnum
3347
 * @type String[]
3348
 * @protected
3349
 * @static
3350
 */
3351
forceEnum = O._forceEnum = [
3352
    'hasOwnProperty',
3353
    'isPrototypeOf',
3354
    'propertyIsEnumerable',
3355
    'toString',
3356
    'toLocaleString',
3357
    'valueOf'
3358
],
3359
 
3360
/**
3361
 * `true` if this browser has the JScript enumeration bug that prevents
3362
 * enumeration of the properties named in the `_forceEnum` array, `false`
3363
 * otherwise.
3364
 *
3365
 * See:
3366
 *   - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
3367
 *   - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
3368
 *
3369
 * @property _hasEnumBug
3370
 * @type Boolean
3371
 * @protected
3372
 * @static
3373
 */
3374
hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
3375
 
3376
/**
3377
 * `true` if this browser incorrectly considers the `prototype` property of
3378
 * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x.
3379
 *
3380
 * @property _hasProtoEnumBug
3381
 * @type Boolean
3382
 * @protected
3383
 * @static
3384
 */
3385
hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
3386
 
3387
/**
3388
 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
3389
 * exists only on _obj_'s prototype. This is essentially a safer version of
3390
 * `obj.hasOwnProperty()`.
3391
 *
3392
 * @method owns
3393
 * @param {Object} obj Object to test.
3394
 * @param {String} key Property name to look for.
3395
 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3396
 * @static
3397
 */
3398
owns = O.owns = function (obj, key) {
3399
    return !!obj && hasOwn.call(obj, key);
3400
}; // <-- End of var declarations.
3401
 
3402
/**
3403
 * Alias for `owns()`.
3404
 *
3405
 * @method hasKey
3406
 * @param {Object} obj Object to test.
3407
 * @param {String} key Property name to look for.
3408
 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3409
 * @static
3410
 */
3411
O.hasKey = owns;
3412
 
3413
/**
3414
 * Returns an array containing the object's enumerable keys. Does not include
3415
 * prototype keys or non-enumerable keys.
3416
 *
3417
 * Note that keys are returned in enumeration order (that is, in the same order
3418
 * that they would be enumerated by a `for-in` loop), which may not be the same
3419
 * as the order in which they were defined.
3420
 *
3421
 * This method is an alias for the native ES5 `Object.keys()` method if
3422
 * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of
3423
 * `Object.keys()` have an inconsistency as they consider `prototype` to be
3424
 * enumerable, so a non-native shim is used to rectify the difference.
3425
 *
3426
 * @example
3427
 *
3428
 *     Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
3429
 *     // => ['a', 'b', 'c']
3430
 *
3431
 * @method keys
3432
 * @param {Object} obj An object.
3433
 * @return {String[]} Array of keys.
3434
 * @static
3435
 */
3436
O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) {
3437
    if (!Lang.isObject(obj)) {
3438
        throw new TypeError('Object.keys called on a non-object');
3439
    }
3440
 
3441
    var keys = [],
3442
        i, key, len;
3443
 
3444
    if (hasProtoEnumBug && typeof obj === 'function') {
3445
        for (key in obj) {
3446
            if (owns(obj, key) && key !== 'prototype') {
3447
                keys.push(key);
3448
            }
3449
        }
3450
    } else {
3451
        for (key in obj) {
3452
            if (owns(obj, key)) {
3453
                keys.push(key);
3454
            }
3455
        }
3456
    }
3457
 
3458
    if (hasEnumBug) {
3459
        for (i = 0, len = forceEnum.length; i < len; ++i) {
3460
            key = forceEnum[i];
3461
 
3462
            if (owns(obj, key)) {
3463
                keys.push(key);
3464
            }
3465
        }
3466
    }
3467
 
3468
    return keys;
3469
};
3470
 
3471
/**
3472
 * Returns an array containing the values of the object's enumerable keys.
3473
 *
3474
 * Note that values are returned in enumeration order (that is, in the same
3475
 * order that they would be enumerated by a `for-in` loop), which may not be the
3476
 * same as the order in which they were defined.
3477
 *
3478
 * @example
3479
 *
3480
 *     Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
3481
 *     // => ['foo', 'bar', 'baz']
3482
 *
3483
 * @method values
3484
 * @param {Object} obj An object.
3485
 * @return {Array} Array of values.
3486
 * @static
3487
 */
3488
O.values = function (obj) {
3489
    var keys   = O.keys(obj),
3490
        i      = 0,
3491
        len    = keys.length,
3492
        values = [];
3493
 
3494
    for (; i < len; ++i) {
3495
        values.push(obj[keys[i]]);
3496
    }
3497
 
3498
    return values;
3499
};
3500
 
3501
/**
3502
 * Returns the number of enumerable keys owned by an object.
3503
 *
3504
 * @method size
3505
 * @param {Object} obj An object.
3506
 * @return {Number} The object's size.
3507
 * @static
3508
 */
3509
O.size = function (obj) {
3510
    try {
3511
        return O.keys(obj).length;
3512
    } catch (ex) {
3513
        return 0; // Legacy behavior for non-objects.
3514
    }
3515
};
3516
 
3517
/**
3518
 * Returns `true` if the object owns an enumerable property with the specified
3519
 * value.
3520
 *
3521
 * @method hasValue
3522
 * @param {Object} obj An object.
3523
 * @param {any} value The value to search for.
3524
 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3525
 * @static
3526
 */
3527
O.hasValue = function (obj, value) {
3528
    return Y.Array.indexOf(O.values(obj), value) > -1;
3529
};
3530
 
3531
/**
3532
 * Executes a function on each enumerable property in _obj_. The function
3533
 * receives the value, the key, and the object itself as parameters (in that
3534
 * order).
3535
 *
3536
 * By default, only properties owned by _obj_ are enumerated. To include
3537
 * prototype properties, set the _proto_ parameter to `true`.
3538
 *
3539
 * @method each
3540
 * @param {Object} obj Object to enumerate.
3541
 * @param {Function} fn Function to execute on each enumerable property.
3542
 *   @param {mixed} fn.value Value of the current property.
3543
 *   @param {String} fn.key Key of the current property.
3544
 *   @param {Object} fn.obj Object being enumerated.
3545
 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3546
 * @param {Boolean} [proto=false] Include prototype properties.
3547
 * @return {YUI} the YUI instance.
3548
 * @chainable
3549
 * @static
3550
 */
3551
O.each = function (obj, fn, thisObj, proto) {
3552
    var key;
3553
 
3554
    for (key in obj) {
3555
        if (proto || owns(obj, key)) {
3556
            fn.call(thisObj || Y, obj[key], key, obj);
3557
        }
3558
    }
3559
 
3560
    return Y;
3561
};
3562
 
3563
/**
3564
 * Executes a function on each enumerable property in _obj_, but halts if the
3565
 * function returns a truthy value. The function receives the value, the key,
3566
 * and the object itself as paramters (in that order).
3567
 *
3568
 * By default, only properties owned by _obj_ are enumerated. To include
3569
 * prototype properties, set the _proto_ parameter to `true`.
3570
 *
3571
 * @method some
3572
 * @param {Object} obj Object to enumerate.
3573
 * @param {Function} fn Function to execute on each enumerable property.
3574
 *   @param {mixed} fn.value Value of the current property.
3575
 *   @param {String} fn.key Key of the current property.
3576
 *   @param {Object} fn.obj Object being enumerated.
3577
 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3578
 * @param {Boolean} [proto=false] Include prototype properties.
3579
 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3580
 *   `false` otherwise.
3581
 * @static
3582
 */
3583
O.some = function (obj, fn, thisObj, proto) {
3584
    var key;
3585
 
3586
    for (key in obj) {
3587
        if (proto || owns(obj, key)) {
3588
            if (fn.call(thisObj || Y, obj[key], key, obj)) {
3589
                return true;
3590
            }
3591
        }
3592
    }
3593
 
3594
    return false;
3595
};
3596
 
3597
/**
3598
 * Retrieves the sub value at the provided path,
3599
 * from the value object provided.
3600
 *
3601
 * @method getValue
3602
 * @static
3603
 * @param o The object from which to extract the property value.
3604
 * @param path {Array} A path array, specifying the object traversal path
3605
 * from which to obtain the sub value.
3606
 * @return {Any} The value stored in the path, undefined if not found,
3607
 * undefined if the source is not an object.  Returns the source object
3608
 * if an empty path is provided.
3609
 */
3610
O.getValue = function(o, path) {
3611
    if (!Lang.isObject(o)) {
3612
        return UNDEFINED;
3613
    }
3614
 
3615
    var i,
3616
        p = Y.Array(path),
3617
        l = p.length;
3618
 
3619
    for (i = 0; o !== UNDEFINED && i < l; i++) {
3620
        o = o[p[i]];
3621
    }
3622
 
3623
    return o;
3624
};
3625
 
3626
/**
3627
 * Sets the sub-attribute value at the provided path on the
3628
 * value object.  Returns the modified value object, or
3629
 * undefined if the path is invalid.
3630
 *
3631
 * @method setValue
3632
 * @static
3633
 * @param o             The object on which to set the sub value.
3634
 * @param path {Array}  A path array, specifying the object traversal path
3635
 *                      at which to set the sub value.
3636
 * @param val {Any}     The new value for the sub-attribute.
3637
 * @return {Object}     The modified object, with the new sub value set, or
3638
 *                      undefined, if the path was invalid.
3639
 */
3640
O.setValue = function(o, path, val) {
3641
    var i,
3642
        p = Y.Array(path),
3643
        leafIdx = p.length - 1,
3644
        ref = o;
3645
 
3646
    if (leafIdx >= 0) {
3647
        for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3648
            ref = ref[p[i]];
3649
        }
3650
 
3651
        if (ref !== UNDEFINED) {
3652
            ref[p[i]] = val;
3653
        } else {
3654
            return UNDEFINED;
3655
        }
3656
    }
3657
 
3658
    return o;
3659
};
3660
 
3661
/**
3662
 * Returns `true` if the object has no enumerable properties of its own.
3663
 *
3664
 * @method isEmpty
3665
 * @param {Object} obj An object.
3666
 * @return {Boolean} `true` if the object is empty.
3667
 * @static
3668
 * @since 3.2.0
3669
 */
3670
O.isEmpty = function (obj) {
3671
    return !O.keys(Object(obj)).length;
3672
};
3673
/**
3674
 * The YUI module contains the components required for building the YUI seed
3675
 * file.  This includes the script loading mechanism, a simple queue, and the
3676
 * core utilities for the library.
3677
 * @module yui
3678
 * @submodule yui-base
3679
 */
3680
 
3681
/**
3682
 * YUI user agent detection.
3683
 * Do not fork for a browser if it can be avoided.  Use feature detection when
3684
 * you can.  Use the user agent as a last resort.  For all fields listed
3685
 * as @type float, UA stores a version number for the browser engine,
3686
 * 0 otherwise.  This value may or may not map to the version number of
3687
 * the browser using the engine.  The value is presented as a float so
3688
 * that it can easily be used for boolean evaluation as well as for
3689
 * looking for a particular range of versions.  Because of this,
3690
 * some of the granularity of the version info may be lost.  The fields that
3691
 * are @type string default to null.  The API docs list the values that
3692
 * these fields can have.
3693
 * @class UA
3694
 * @static
3695
 */
3696
 
3697
/**
3698
* Static method on `YUI.Env` for parsing a UA string.  Called at instantiation
3699
* to populate `Y.UA`.
3700
*
3701
* @static
3702
* @method parseUA
3703
* @param {String} [subUA=navigator.userAgent] UA string to parse
3704
* @return {Object} The Y.UA object
3705
*/
3706
YUI.Env.parseUA = function(subUA) {
3707
 
3708
    var numberify = function(s) {
3709
            var c = 0;
3710
            return parseFloat(s.replace(/\./g, function() {
3711
                return (c++ === 1) ? '' : '.';
3712
            }));
3713
        },
3714
 
3715
        win = Y.config.win,
3716
 
3717
        nav = win && win.navigator,
3718
 
3719
        o = {
3720
 
3721
        /**
3722
         * Internet Explorer version number or 0.  Example: 6
3723
         * @property ie
3724
         * @type float
3725
         * @static
3726
         */
3727
        ie: 0,
3728
 
3729
        /**
3730
         * Opera version number or 0.  Example: 9.2
3731
         * @property opera
3732
         * @type float
3733
         * @static
3734
         */
3735
        opera: 0,
3736
 
3737
        /**
3738
         * Gecko engine revision number.  Will evaluate to 1 if Gecko
3739
         * is detected but the revision could not be found. Other browsers
3740
         * will be 0.  Example: 1.8
3741
         * <pre>
3742
         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
3743
         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3744
         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3745
         * Firefox 3.0   <-- 1.9
3746
         * Firefox 3.5   <-- 1.91
3747
         * </pre>
3748
         * @property gecko
3749
         * @type float
3750
         * @static
3751
         */
3752
        gecko: 0,
3753
 
3754
        /**
3755
         * AppleWebKit version.  KHTML browsers that are not WebKit browsers
3756
         * will evaluate to 1, other browsers 0.  Example: 418.9
3757
         * <pre>
3758
         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3759
         *                                   latest available for Mac OSX 10.3.
3760
         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
3761
         * Safari 2.0.4:         418     <-- preventDefault fixed
3762
         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3763
         *                                   different versions of webkit
3764
         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
3765
         *                                   updated, but not updated
3766
         *                                   to the latest patch.
3767
         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
3768
         * SVG and many major issues fixed).
3769
         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
3770
         * update from 2.x via the 10.4.11 OS patch.
3771
         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
3772
         *                                   yahoo.com user agent hack removed.
3773
         * </pre>
3774
         * http://en.wikipedia.org/wiki/Safari_version_history
3775
         * @property webkit
3776
         * @type float
3777
         * @static
3778
         */
3779
        webkit: 0,
3780
 
3781
        /**
3782
         * Safari will be detected as webkit, but this property will also
3783
         * be populated with the Safari version number
3784
         * @property safari
3785
         * @type float
3786
         * @static
3787
         */
3788
        safari: 0,
3789
 
3790
        /**
3791
         * Chrome will be detected as webkit, but this property will also
3792
         * be populated with the Chrome version number
3793
         * @property chrome
3794
         * @type float
3795
         * @static
3796
         */
3797
        chrome: 0,
3798
 
3799
        /**
3800
         * The mobile property will be set to a string containing any relevant
3801
         * user agent information when a modern mobile browser is detected.
3802
         * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3803
         * devices with the WebKit-based browser, and Opera Mini.
3804
         * @property mobile
3805
         * @type string
3806
         * @default null
3807
         * @static
3808
         */
3809
        mobile: null,
3810
 
3811
        /**
3812
         * Adobe AIR version number or 0.  Only populated if webkit is detected.
3813
         * Example: 1.0
3814
         * @property air
3815
         * @type float
3816
         */
3817
        air: 0,
3818
        /**
3819
         * PhantomJS version number or 0.  Only populated if webkit is detected.
3820
         * Example: 1.0
3821
         * @property phantomjs
3822
         * @type float
3823
         */
3824
        phantomjs: 0,
3825
        /**
3826
         * Detects Apple iPad's OS version
3827
         * @property ipad
3828
         * @type float
3829
         * @static
3830
         */
3831
        ipad: 0,
3832
        /**
3833
         * Detects Apple iPhone's OS version
3834
         * @property iphone
3835
         * @type float
3836
         * @static
3837
         */
3838
        iphone: 0,
3839
        /**
3840
         * Detects Apples iPod's OS version
3841
         * @property ipod
3842
         * @type float
3843
         * @static
3844
         */
3845
        ipod: 0,
3846
        /**
3847
         * General truthy check for iPad, iPhone or iPod
3848
         * @property ios
3849
         * @type Boolean
3850
         * @default null
3851
         * @static
3852
         */
3853
        ios: null,
3854
        /**
3855
         * Detects Googles Android OS version
3856
         * @property android
3857
         * @type float
3858
         * @static
3859
         */
3860
        android: 0,
3861
        /**
3862
         * Detects Kindle Silk
3863
         * @property silk
3864
         * @type float
3865
         * @static
3866
         */
3867
        silk: 0,
3868
        /**
3869
         * Detects Ubuntu version
3870
         * @property ubuntu
3871
         * @type float
3872
         * @static
3873
         */
3874
        ubuntu: 0,
3875
        /**
3876
         * Detects Kindle Silk Acceleration
3877
         * @property accel
3878
         * @type Boolean
3879
         * @static
3880
         */
3881
        accel: false,
3882
        /**
3883
         * Detects Palms WebOS version
3884
         * @property webos
3885
         * @type float
3886
         * @static
3887
         */
3888
        webos: 0,
3889
 
3890
        /**
3891
         * Google Caja version number or 0.
3892
         * @property caja
3893
         * @type float
3894
         */
3895
        caja: nav && nav.cajaVersion,
3896
 
3897
        /**
3898
         * Set to true if the page appears to be in SSL
3899
         * @property secure
3900
         * @type boolean
3901
         * @static
3902
         */
3903
        secure: false,
3904
 
3905
        /**
3906
         * The operating system.
3907
         *
3908
         * Possible values are `windows`, `macintosh`, `android`, `symbos`, `linux`, `rhino` and `ios`.
3909
         *
3910
         * @property os
3911
         * @type string
3912
         * @default null
3913
         * @static
3914
         */
3915
        os: null,
3916
 
3917
        /**
3918
         * The Nodejs Version
3919
         * @property nodejs
3920
         * @type float
3921
         * @default 0
3922
         * @static
3923
         */
3924
        nodejs: 0,
3925
        /**
3926
        * Window8/IE10 Application host environment
3927
        * @property winjs
3928
        * @type Boolean
3929
        * @static
3930
        */
3931
        winjs: !!((typeof Windows !== "undefined") && Windows.System),
3932
        /**
3933
        * Are touch/msPointer events available on this device
3934
        * @property touchEnabled
3935
        * @type Boolean
3936
        * @static
3937
        */
3938
        touchEnabled: false
3939
    },
3940
 
3941
    ua = subUA || nav && nav.userAgent,
3942
 
3943
    loc = win && win.location,
3944
 
3945
    href = loc && loc.href,
3946
 
3947
    m;
3948
 
3949
    /**
3950
    * The User Agent string that was parsed
3951
    * @property userAgent
3952
    * @type String
3953
    * @static
3954
    */
3955
    o.userAgent = ua;
3956
 
3957
 
3958
    o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3959
 
3960
    if (ua) {
3961
 
3962
        if ((/windows|win32/i).test(ua)) {
3963
            o.os = 'windows';
3964
        } else if ((/macintosh|mac_powerpc/i).test(ua)) {
3965
            o.os = 'macintosh';
3966
        } else if ((/android/i).test(ua)) {
3967
            o.os = 'android';
3968
        } else if ((/symbos/i).test(ua)) {
3969
            o.os = 'symbos';
3970
        } else if ((/linux/i).test(ua)) {
3971
            o.os = 'linux';
3972
        } else if ((/rhino/i).test(ua)) {
3973
            o.os = 'rhino';
3974
        }
3975
 
3976
        // Modern KHTML browsers should qualify as Safari X-Grade
3977
        if ((/KHTML/).test(ua)) {
3978
            o.webkit = 1;
3979
        }
3980
        if ((/IEMobile|XBLWP7/).test(ua)) {
3981
            o.mobile = 'windows';
3982
        }
3983
        if ((/Fennec/).test(ua)) {
3984
            o.mobile = 'gecko';
3985
        }
3986
        // Modern WebKit browsers are at least X-Grade
3987
        m = ua.match(/AppleWebKit\/([^\s]*)/);
3988
        if (m && m[1]) {
3989
            o.webkit = numberify(m[1]);
3990
            o.safari = o.webkit;
3991
 
3992
            if (/PhantomJS/.test(ua)) {
3993
                m = ua.match(/PhantomJS\/([^\s]*)/);
3994
                if (m && m[1]) {
3995
                    o.phantomjs = numberify(m[1]);
3996
                }
3997
            }
3998
 
3999
            // Mobile browser check
4000
            if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
4001
                o.mobile = 'Apple'; // iPhone or iPod Touch
4002
 
4003
                m = ua.match(/OS ([^\s]*)/);
4004
                if (m && m[1]) {
4005
                    m = numberify(m[1].replace('_', '.'));
4006
                }
4007
                o.ios = m;
4008
                o.os = 'ios';
4009
                o.ipad = o.ipod = o.iphone = 0;
4010
 
4011
                m = ua.match(/iPad|iPod|iPhone/);
4012
                if (m && m[0]) {
4013
                    o[m[0].toLowerCase()] = o.ios;
4014
                }
4015
            } else {
4016
                m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
4017
                if (m) {
4018
                    // Nokia N-series, webOS, ex: NokiaN95
4019
                    o.mobile = m[0];
4020
                }
4021
                if (/webOS/.test(ua)) {
4022
                    o.mobile = 'WebOS';
4023
                    m = ua.match(/webOS\/([^\s]*);/);
4024
                    if (m && m[1]) {
4025
                        o.webos = numberify(m[1]);
4026
                    }
4027
                }
4028
                if (/ Android/.test(ua)) {
4029
                    o.mobile = 'Android';
4030
                    m = ua.match(/Android ([^\s]*);/);
4031
                    if (m && m[1]) {
4032
                        o.android = numberify(m[1]);
4033
                    }
4034
 
4035
                }
4036
                if (/Silk/.test(ua)) {
4037
                    m = ua.match(/Silk\/([^\s]*)/);
4038
                    if (m && m[1]) {
4039
                        o.silk = numberify(m[1]);
4040
                    }
4041
                    if (!o.android) {
4042
                        o.android = 2.34; //Hack for desktop mode in Kindle
4043
                        o.os = 'Android';
4044
                    }
4045
                    if (/Accelerated=true/.test(ua)) {
4046
                        o.accel = true;
4047
                    }
4048
                }
4049
            }
4050
 
4051
            m = ua.match(/OPR\/(\d+\.\d+)/);
4052
 
4053
            if (m && m[1]) {
4054
                // Opera 15+ with Blink (pretends to be both Chrome and Safari)
4055
                o.opera = numberify(m[1]);
4056
            } else {
4057
                m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
4058
 
4059
                if (m && m[1] && m[2]) {
4060
                    o.chrome = numberify(m[2]); // Chrome
4061
                    o.safari = 0; //Reset safari back to 0
4062
                    if (m[1] === 'CrMo') {
4063
                        o.mobile = 'chrome';
4064
                    }
4065
                } else {
4066
                    m = ua.match(/AdobeAIR\/([^\s]*)/);
4067
                    if (m) {
4068
                        o.air = m[0]; // Adobe AIR 1.0 or better
4069
                    }
4070
                }
4071
            }
4072
        }
4073
 
4074
        m = ua.match(/Ubuntu\ (\d+\.\d+)/);
4075
        if (m && m[1]) {
4076
 
4077
            o.os = 'linux';
4078
            o.ubuntu = numberify(m[1]);
4079
 
4080
            m = ua.match(/\ WebKit\/([^\s]*)/);
4081
            if (m && m[1]) {
4082
                o.webkit = numberify(m[1]);
4083
            }
4084
            m = ua.match(/\ Chromium\/([^\s]*)/);
4085
            if (m && m[1]) {
4086
                o.chrome = numberify(m[1]);
4087
            }
4088
            if (/ Mobile$/.test(ua)) {
4089
                o.mobile = 'Ubuntu';
4090
            }
4091
        }
4092
 
4093
        if (!o.webkit) { // not webkit
4094
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
4095
            if (/Opera/.test(ua)) {
4096
                m = ua.match(/Opera[\s\/]([^\s]*)/);
4097
                if (m && m[1]) {
4098
                    o.opera = numberify(m[1]);
4099
                }
4100
                m = ua.match(/Version\/([^\s]*)/);
4101
                if (m && m[1]) {
4102
                    o.opera = numberify(m[1]); // opera 10+
4103
                }
4104
 
4105
                if (/Opera Mobi/.test(ua)) {
4106
                    o.mobile = 'opera';
4107
                    m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
4108
                    if (m && m[1]) {
4109
                        o.opera = numberify(m[1]);
4110
                    }
4111
                }
4112
                m = ua.match(/Opera Mini[^;]*/);
4113
 
4114
                if (m) {
4115
                    o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
4116
                }
4117
            } else { // not opera or webkit
4118
                m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/);
4119
 
4120
                if (m && (m[1] || m[2])) {
4121
                    o.ie = numberify(m[1] || m[2]);
4122
                } else { // not opera, webkit, or ie
4123
                    m = ua.match(/Gecko\/([^\s]*)/);
4124
 
4125
                    if (m) {
4126
                        o.gecko = 1; // Gecko detected, look for revision
4127
                        m = ua.match(/rv:([^\s\)]*)/);
4128
                        if (m && m[1]) {
4129
                            o.gecko = numberify(m[1]);
4130
                            if (/Mobile|Tablet/.test(ua)) {
4131
                                o.mobile = "ffos";
4132
                            }
4133
                        }
4134
                    }
4135
                }
4136
            }
4137
        }
4138
    }
4139
 
4140
    //Check for known properties to tell if touch events are enabled on this device or if
4141
    //the number of MSPointer touchpoints on this device is greater than 0.
4142
    if (win && nav && !(o.chrome && o.chrome < 6)) {
4143
        o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
4144
    }
4145
 
4146
    //It was a parsed UA, do not assign the global value.
4147
    if (!subUA) {
4148
 
4149
        if (typeof process === 'object') {
4150
 
4151
            if (process.versions && process.versions.node) {
4152
                //NodeJS
4153
                o.os = process.platform;
4154
                o.nodejs = numberify(process.versions.node);
4155
            }
4156
        }
4157
 
4158
        YUI.Env.UA = o;
4159
 
4160
    }
4161
 
4162
    return o;
4163
};
4164
 
4165
 
4166
Y.UA = YUI.Env.UA || YUI.Env.parseUA();
4167
 
4168
/**
4169
Performs a simple comparison between two version numbers, accounting for
4170
standard versioning logic such as the fact that "535.8" is a lower version than
4171
"535.24", even though a simple numerical comparison would indicate that it's
4172
greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
4173
considered equivalent.
4174
 
4175
Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
4176
1 if _a_ is higher than _b_.
4177
 
4178
Versions may be numbers or strings containing numbers and dots. For example,
4179
both `535` and `"535.8.10"` are acceptable. A version string containing
4180
non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
4181
 
4182
@method compareVersions
4183
@param {Number|String} a First version number to compare.
4184
@param {Number|String} b Second version number to compare.
4185
@return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
4186
    higher than _b_.
4187
**/
4188
Y.UA.compareVersions = function (a, b) {
4189
    var aPart, aParts, bPart, bParts, i, len;
4190
 
4191
    if (a === b) {
4192
        return 0;
4193
    }
4194
 
4195
    aParts = (a + '').split('.');
4196
    bParts = (b + '').split('.');
4197
 
4198
    for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
4199
        aPart = parseInt(aParts[i], 10);
4200
        bPart = parseInt(bParts[i], 10);
4201
 
4202
        /*jshint expr: true*/
4203
        isNaN(aPart) && (aPart = 0);
4204
        isNaN(bPart) && (bPart = 0);
4205
 
4206
        if (aPart < bPart) {
4207
            return -1;
4208
        }
4209
 
4210
        if (aPart > bPart) {
4211
            return 1;
4212
        }
4213
    }
4214
 
4215
    return 0;
4216
};
4217
YUI.Env.aliases = {
4218
    "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
4219
    "anim-shape-transform": ["anim-shape"],
4220
    "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"],
4221
    "attribute": ["attribute-base","attribute-complex"],
4222
    "attribute-events": ["attribute-observable"],
4223
    "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
4224
    "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
4225
    "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
4226
    "base": ["base-base","base-pluginhost","base-build"],
4227
    "cache": ["cache-base","cache-offline","cache-plugin"],
4228
    "charts": ["charts-base"],
4229
    "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
4230
    "color": ["color-base","color-hsl","color-harmony"],
4231
    "controller": ["router"],
4232
    "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
4233
    "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
4234
    "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
4235
    "datatype": ["datatype-date","datatype-number","datatype-xml"],
4236
    "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
4237
    "datatype-number": ["datatype-number-parse","datatype-number-format"],
4238
    "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
4239
    "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
4240
    "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
4241
    "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
4242
    "event": ["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],
4243
    "event-custom": ["event-custom-base","event-custom-complex"],
4244
    "event-gestures": ["event-flick","event-move"],
4245
    "handlebars": ["handlebars-compiler"],
4246
    "highlight": ["highlight-base","highlight-accentfold"],
4247
    "history": ["history-base","history-hash","history-html5"],
4248
    "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
4249
    "json": ["json-parse","json-stringify"],
4250
    "loader": ["loader-base","loader-rollup","loader-yui3"],
4251
    "loader-pathogen-encoder": ["loader-base","loader-rollup","loader-yui3","loader-pathogen-combohandler"],
4252
    "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
4253
    "pluginhost": ["pluginhost-base","pluginhost-config"],
4254
    "querystring": ["querystring-parse","querystring-stringify"],
4255
    "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
4256
    "resize": ["resize-base","resize-proxy","resize-constrain"],
4257
    "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
4258
    "template": ["template-base","template-micro"],
4259
    "text": ["text-accentfold","text-wordbreak"],
4260
    "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
4261
};
4262
 
4263
 
4264
}, '3.18.1');