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: ['get', 'features', 'intl-base', 'yui-log', 'yui-later'],
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', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
4265
YUI.add('get', function (Y, NAME) {
4266
 
4267
/*jslint boss:true, expr:true, laxbreak: true */
4268
 
4269
/**
4270
Provides dynamic loading of remote JavaScript and CSS resources.
4271
 
4272
@module get
4273
@class Get
4274
@static
4275
**/
4276
 
4277
var Lang = Y.Lang,
4278
 
4279
    CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode()
4280
 
4281
    Get, Transaction;
4282
 
4283
Y.Get = Get = {
4284
    // -- Public Properties ----------------------------------------------------
4285
 
4286
    /**
4287
    Default options for CSS requests. Options specified here will override
4288
    global defaults for CSS requests.
4289
 
4290
    See the `options` property for all available options.
4291
 
4292
    @property cssOptions
4293
    @type Object
4294
    @static
4295
    @since 3.5.0
4296
    **/
4297
    cssOptions: {
4298
        attributes: {
4299
            rel: 'stylesheet'
4300
        },
4301
 
4302
        doc         : Y.config.linkDoc || Y.config.doc,
4303
        pollInterval: 50
4304
    },
4305
 
4306
    /**
4307
    Default options for JS requests. Options specified here will override global
4308
    defaults for JS requests.
4309
 
4310
    See the `options` property for all available options.
4311
 
4312
    @property jsOptions
4313
    @type Object
4314
    @static
4315
    @since 3.5.0
4316
    **/
4317
    jsOptions: {
4318
        autopurge: true,
4319
        doc      : Y.config.scriptDoc || Y.config.doc
4320
    },
4321
 
4322
    /**
4323
    Default options to use for all requests.
4324
 
4325
    Note that while all available options are documented here for ease of
4326
    discovery, some options (like callback functions) only make sense at the
4327
    transaction level.
4328
 
4329
    Callback functions specified via the options object or the `options`
4330
    parameter of the `css()`, `js()`, or `load()` methods will receive the
4331
    transaction object as a parameter. See `Y.Get.Transaction` for details on
4332
    the properties and methods available on transactions.
4333
 
4334
    @static
4335
    @since 3.5.0
4336
    @property {Object} options
4337
 
4338
    @property {Boolean} [options.async=false] Whether or not to load scripts
4339
        asynchronously, meaning they're requested in parallel and execution
4340
        order is not guaranteed. Has no effect on CSS, since CSS is always
4341
        loaded asynchronously.
4342
 
4343
    @property {Object} [options.attributes] HTML attribute name/value pairs that
4344
        should be added to inserted nodes. By default, the `charset` attribute
4345
        will be set to "utf-8" and nodes will be given an auto-generated `id`
4346
        attribute, but you can override these with your own values if desired.
4347
 
4348
    @property {Boolean} [options.autopurge] Whether or not to automatically
4349
        purge inserted nodes after the purge threshold is reached. This is
4350
        `true` by default for JavaScript, but `false` for CSS since purging a
4351
        CSS node will also remove any styling applied by the referenced file.
4352
 
4353
    @property {Object} [options.context] `this` object to use when calling
4354
        callback functions. Defaults to the transaction object.
4355
 
4356
    @property {Mixed} [options.data] Arbitrary data object to pass to "on*"
4357
        callbacks.
4358
 
4359
    @property {Document} [options.doc] Document into which nodes should be
4360
        inserted. By default, the current document is used.
4361
 
4362
    @property {HTMLElement|String} [options.insertBefore] HTML element or id
4363
        string of an element before which all generated nodes should be
4364
        inserted. If not specified, Get will automatically determine the best
4365
        place to insert nodes for maximum compatibility.
4366
 
4367
    @property {Function} [options.onEnd] Callback to execute after a transaction
4368
        is complete, regardless of whether it succeeded or failed.
4369
 
4370
    @property {Function} [options.onFailure] Callback to execute after a
4371
        transaction fails, times out, or is aborted.
4372
 
4373
    @property {Function} [options.onProgress] Callback to execute after each
4374
        individual request in a transaction either succeeds or fails.
4375
 
4376
    @property {Function} [options.onSuccess] Callback to execute after a
4377
        transaction completes successfully with no errors. Note that in browsers
4378
        that don't support the `error` event on CSS `<link>` nodes, a failed CSS
4379
        request may still be reported as a success because in these browsers
4380
        it can be difficult or impossible to distinguish between success and
4381
        failure for CSS resources.
4382
 
4383
    @property {Function} [options.onTimeout] Callback to execute after a
4384
        transaction times out.
4385
 
4386
    @property {Number} [options.pollInterval=50] Polling interval (in
4387
        milliseconds) for detecting CSS load completion in browsers that don't
4388
        support the `load` event on `<link>` nodes. This isn't used for
4389
        JavaScript.
4390
 
4391
    @property {Number} [options.purgethreshold=20] Number of nodes to insert
4392
        before triggering an automatic purge when `autopurge` is `true`.
4393
 
4394
    @property {Number} [options.timeout] Number of milliseconds to wait before
4395
        aborting a transaction. When a timeout occurs, the `onTimeout` callback
4396
        is called, followed by `onFailure` and finally `onEnd`. By default,
4397
        there is no timeout.
4398
 
4399
    @property {String} [options.type] Resource type ("css" or "js"). This option
4400
        is set automatically by the `css()` and `js()` functions and will be
4401
        ignored there, but may be useful when using the `load()` function. If
4402
        not specified, the type will be inferred from the URL, defaulting to
4403
        "js" if the URL doesn't contain a recognizable file extension.
4404
    **/
4405
    options: {
4406
        attributes: {
4407
            charset: 'utf-8'
4408
        },
4409
 
4410
        purgethreshold: 20
4411
    },
4412
 
4413
    // -- Protected Properties -------------------------------------------------
4414
 
4415
    /**
4416
    Regex that matches a CSS URL. Used to guess the file type when it's not
4417
    specified.
4418
 
4419
    @property REGEX_CSS
4420
    @type RegExp
4421
    @final
4422
    @protected
4423
    @static
4424
    @since 3.5.0
4425
    **/
4426
    REGEX_CSS: /\.css(?:[?;].*)?$/i,
4427
 
4428
    /**
4429
    Regex that matches a JS URL. Used to guess the file type when it's not
4430
    specified.
4431
 
4432
    @property REGEX_JS
4433
    @type RegExp
4434
    @final
4435
    @protected
4436
    @static
4437
    @since 3.5.0
4438
    **/
4439
    REGEX_JS : /\.js(?:[?;].*)?$/i,
4440
 
4441
    /**
4442
    Contains information about the current environment, such as what script and
4443
    link injection features it supports.
4444
 
4445
    This object is created and populated the first time the `_getEnv()` method
4446
    is called.
4447
 
4448
    @property _env
4449
    @type Object
4450
    @protected
4451
    @static
4452
    @since 3.5.0
4453
    **/
4454
 
4455
    /**
4456
    Mapping of document _yuid strings to <head> or <base> node references so we
4457
    don't have to look the node up each time we want to insert a request node.
4458
 
4459
    @property _insertCache
4460
    @type Object
4461
    @protected
4462
    @static
4463
    @since 3.5.0
4464
    **/
4465
    _insertCache: {},
4466
 
4467
    /**
4468
    Information about the currently pending transaction, if any.
4469
 
4470
    This is actually an object with two properties: `callback`, containing the
4471
    optional callback passed to `css()`, `load()`, or `js()`; and `transaction`,
4472
    containing the actual transaction instance.
4473
 
4474
    @property _pending
4475
    @type Object
4476
    @protected
4477
    @static
4478
    @since 3.5.0
4479
    **/
4480
    _pending: null,
4481
 
4482
    /**
4483
    HTML nodes eligible to be purged next time autopurge is triggered.
4484
 
4485
    @property _purgeNodes
4486
    @type HTMLElement[]
4487
    @protected
4488
    @static
4489
    @since 3.5.0
4490
    **/
4491
    _purgeNodes: [],
4492
 
4493
    /**
4494
    Queued transactions and associated callbacks.
4495
 
4496
    @property _queue
4497
    @type Object[]
4498
    @protected
4499
    @static
4500
    @since 3.5.0
4501
    **/
4502
    _queue: [],
4503
 
4504
    // -- Public Methods -------------------------------------------------------
4505
 
4506
    /**
4507
    Aborts the specified transaction.
4508
 
4509
    This will cause the transaction's `onFailure` callback to be called and
4510
    will prevent any new script and link nodes from being added to the document,
4511
    but any resources that have already been requested will continue loading
4512
    (there's no safe way to prevent this, unfortunately).
4513
 
4514
    *Note:* This method is deprecated as of 3.5.0, and will be removed in a
4515
    future version of YUI. Use the transaction-level `abort()` method instead.
4516
 
4517
    @method abort
4518
    @param {Get.Transaction} transaction Transaction to abort.
4519
    @deprecated Use the `abort()` method on the transaction instead.
4520
    @static
4521
    **/
4522
    abort: function (transaction) {
4523
        var i, id, item, len, pending;
4524
 
4525
        Y.log('`Y.Get.abort()` is deprecated as of 3.5.0. Use the `abort()` method on the transaction instead.', 'warn', 'get');
4526
 
4527
        if (!transaction.abort) {
4528
            id          = transaction;
4529
            pending     = this._pending;
4530
            transaction = null;
4531
 
4532
            if (pending && pending.transaction.id === id) {
4533
                transaction   = pending.transaction;
4534
                this._pending = null;
4535
            } else {
4536
                for (i = 0, len = this._queue.length; i < len; ++i) {
4537
                    item = this._queue[i].transaction;
4538
 
4539
                    if (item.id === id) {
4540
                        transaction = item;
4541
                        this._queue.splice(i, 1);
4542
                        break;
4543
                    }
4544
                }
4545
            }
4546
        }
4547
 
4548
        transaction && transaction.abort();
4549
    },
4550
 
4551
    /**
4552
    Loads one or more CSS files.
4553
 
4554
    The _urls_ parameter may be provided as a URL string, a request object,
4555
    or an array of URL strings and/or request objects.
4556
 
4557
    A request object is just an object that contains a `url` property and zero
4558
    or more options that should apply specifically to that request.
4559
    Request-specific options take priority over transaction-level options and
4560
    default options.
4561
 
4562
    URLs may be relative or absolute, and do not have to have the same origin
4563
    as the current page.
4564
 
4565
    The `options` parameter may be omitted completely and a callback passed in
4566
    its place, if desired.
4567
 
4568
    @example
4569
 
4570
        // Load a single CSS file and log a message on completion.
4571
        Y.Get.css('foo.css', function (err) {
4572
            if (err) {
4573
                Y.log('foo.css failed to load!');
4574
            } else {
4575
                Y.log('foo.css was loaded successfully');
4576
            }
4577
        });
4578
 
4579
        // Load multiple CSS files and log a message when all have finished
4580
        // loading.
4581
        var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css'];
4582
 
4583
        Y.Get.css(urls, function (err) {
4584
            if (err) {
4585
                Y.log('one or more files failed to load!');
4586
            } else {
4587
                Y.log('all files loaded successfully');
4588
            }
4589
        });
4590
 
4591
        // Specify transaction-level options, which will apply to all requests
4592
        // within the transaction.
4593
        Y.Get.css(urls, {
4594
            attributes: {'class': 'my-css'},
4595
            timeout   : 5000
4596
        });
4597
 
4598
        // Specify per-request options, which override transaction-level and
4599
        // default options.
4600
        Y.Get.css([
4601
            {url: 'foo.css', attributes: {id: 'foo'}},
4602
            {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}}
4603
        ]);
4604
 
4605
    @method css
4606
    @param {String|Object|Array} urls URL string, request object, or array
4607
        of URLs and/or request objects to load.
4608
    @param {Object} [options] Options for this transaction. See the
4609
        `Y.Get.options` property for a complete list of available options.
4610
    @param {Function} [callback] Callback function to be called on completion.
4611
        This is a general callback and will be called before any more granular
4612
        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4613
        object.
4614
 
4615
        @param {Array|null} callback.err Array of errors that occurred during
4616
            the transaction, or `null` on success.
4617
        @param {Get.Transaction} callback.transaction Transaction object.
4618
 
4619
    @return {Get.Transaction} Transaction object.
4620
    @static
4621
    **/
4622
    css: function (urls, options, callback) {
4623
        return this._load('css', urls, options, callback);
4624
    },
4625
 
4626
    /**
4627
    Loads one or more JavaScript resources.
4628
 
4629
    The _urls_ parameter may be provided as a URL string, a request object,
4630
    or an array of URL strings and/or request objects.
4631
 
4632
    A request object is just an object that contains a `url` property and zero
4633
    or more options that should apply specifically to that request.
4634
    Request-specific options take priority over transaction-level options and
4635
    default options.
4636
 
4637
    URLs may be relative or absolute, and do not have to have the same origin
4638
    as the current page.
4639
 
4640
    The `options` parameter may be omitted completely and a callback passed in
4641
    its place, if desired.
4642
 
4643
    Scripts will be executed in the order they're specified unless the `async`
4644
    option is `true`, in which case they'll be loaded in parallel and executed
4645
    in whatever order they finish loading.
4646
 
4647
    @example
4648
 
4649
        // Load a single JS file and log a message on completion.
4650
        Y.Get.js('foo.js', function (err) {
4651
            if (err) {
4652
                Y.log('foo.js failed to load!');
4653
            } else {
4654
                Y.log('foo.js was loaded successfully');
4655
            }
4656
        });
4657
 
4658
        // Load multiple JS files, execute them in order, and log a message when
4659
        // all have finished loading.
4660
        var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js'];
4661
 
4662
        Y.Get.js(urls, function (err) {
4663
            if (err) {
4664
                Y.log('one or more files failed to load!');
4665
            } else {
4666
                Y.log('all files loaded successfully');
4667
            }
4668
        });
4669
 
4670
        // Specify transaction-level options, which will apply to all requests
4671
        // within the transaction.
4672
        Y.Get.js(urls, {
4673
            attributes: {'class': 'my-js'},
4674
            timeout   : 5000
4675
        });
4676
 
4677
        // Specify per-request options, which override transaction-level and
4678
        // default options.
4679
        Y.Get.js([
4680
            {url: 'foo.js', attributes: {id: 'foo'}},
4681
            {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}}
4682
        ]);
4683
 
4684
    @method js
4685
    @param {String|Object|Array} urls URL string, request object, or array
4686
        of URLs and/or request objects to load.
4687
    @param {Object} [options] Options for this transaction. See the
4688
        `Y.Get.options` property for a complete list of available options.
4689
    @param {Function} [callback] Callback function to be called on completion.
4690
        This is a general callback and will be called before any more granular
4691
        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4692
        object.
4693
 
4694
        @param {Array|null} callback.err Array of errors that occurred during
4695
            the transaction, or `null` on success.
4696
        @param {Get.Transaction} callback.transaction Transaction object.
4697
 
4698
    @return {Get.Transaction} Transaction object.
4699
    @since 3.5.0
4700
    @static
4701
    **/
4702
    js: function (urls, options, callback) {
4703
        return this._load('js', urls, options, callback);
4704
    },
4705
 
4706
    /**
4707
    Loads one or more CSS and/or JavaScript resources in the same transaction.
4708
 
4709
    Use this method when you want to load both CSS and JavaScript in a single
4710
    transaction and be notified when all requested URLs have finished loading,
4711
    regardless of type.
4712
 
4713
    Behavior and options are the same as for the `css()` and `js()` methods. If
4714
    a resource type isn't specified in per-request options or transaction-level
4715
    options, Get will guess the file type based on the URL's extension (`.css`
4716
    or `.js`, with or without a following query string). If the file type can't
4717
    be guessed from the URL, a warning will be logged and Get will assume the
4718
    URL is a JavaScript resource.
4719
 
4720
    @example
4721
 
4722
        // Load both CSS and JS files in a single transaction, and log a message
4723
        // when all files have finished loading.
4724
        Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) {
4725
            if (err) {
4726
                Y.log('one or more files failed to load!');
4727
            } else {
4728
                Y.log('all files loaded successfully');
4729
            }
4730
        });
4731
 
4732
    @method load
4733
    @param {String|Object|Array} urls URL string, request object, or array
4734
        of URLs and/or request objects to load.
4735
    @param {Object} [options] Options for this transaction. See the
4736
        `Y.Get.options` property for a complete list of available options.
4737
    @param {Function} [callback] Callback function to be called on completion.
4738
        This is a general callback and will be called before any more granular
4739
        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4740
        object.
4741
 
4742
        @param {Array|null} err Array of errors that occurred during the
4743
            transaction, or `null` on success.
4744
        @param {Get.Transaction} Transaction object.
4745
 
4746
    @return {Get.Transaction} Transaction object.
4747
    @since 3.5.0
4748
    @static
4749
    **/
4750
    load: function (urls, options, callback) {
4751
        return this._load(null, urls, options, callback);
4752
    },
4753
 
4754
    // -- Protected Methods ----------------------------------------------------
4755
 
4756
    /**
4757
    Triggers an automatic purge if the purge threshold has been reached.
4758
 
4759
    @method _autoPurge
4760
    @param {Number} threshold Purge threshold to use, in milliseconds.
4761
    @protected
4762
    @since 3.5.0
4763
    @static
4764
    **/
4765
    _autoPurge: function (threshold) {
4766
        if (threshold && this._purgeNodes.length >= threshold) {
4767
            Y.log('autopurge triggered after ' + this._purgeNodes.length + ' nodes', 'info', 'get');
4768
            this._purge(this._purgeNodes);
4769
        }
4770
    },
4771
 
4772
    /**
4773
    Populates the `_env` property with information about the current
4774
    environment.
4775
 
4776
    @method _getEnv
4777
    @return {Object} Environment information.
4778
    @protected
4779
    @since 3.5.0
4780
    @static
4781
    **/
4782
    _getEnv: function () {
4783
        var doc = Y.config.doc,
4784
            ua  = Y.UA;
4785
 
4786
        // Note: some of these checks require browser sniffs since it's not
4787
        // feasible to load test files on every pageview just to perform a
4788
        // feature test. I'm sorry if this makes you sad.
4789
        return (this._env = {
4790
 
4791
            // True if this is a browser that supports disabling async mode on
4792
            // dynamically created script nodes. See
4793
            // https://developer.mozilla.org/En/HTML/Element/Script#Attributes
4794
 
4795
            // IE10 doesn't return true for the MDN feature test, so setting it explicitly,
4796
            // because it is async by default, and allows you to disable async by setting it to false
4797
            async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10),
4798
 
4799
            // True if this browser fires an event when a dynamically injected
4800
            // link node fails to load. This is currently true for Firefox 9+
4801
            // and WebKit 535.24+
4802
            cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0,
4803
 
4804
            // True if this browser fires an event when a dynamically injected
4805
            // link node finishes loading. This is currently true for IE, Opera,
4806
            // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the
4807
            // DOM 0 "onload" event, but not "load". All versions of IE fire
4808
            // "onload".
4809
            // davglass: Seems that Chrome on Android needs this to be false.
4810
            cssLoad: (
4811
                    (!ua.gecko && !ua.webkit) || ua.gecko >= 9 ||
4812
                    ua.compareVersions(ua.webkit, 535.24) >= 0
4813
                ) && !(ua.chrome && ua.chrome <= 18),
4814
 
4815
            // True if this browser preserves script execution order while
4816
            // loading scripts in parallel as long as the script node's `async`
4817
            // attribute is set to false to explicitly disable async execution.
4818
            preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10))
4819
        });
4820
    },
4821
 
4822
    _getTransaction: function (urls, options) {
4823
        var requests = [],
4824
            i, len, req, url;
4825
 
4826
        if (!Lang.isArray(urls)) {
4827
            urls = [urls];
4828
        }
4829
 
4830
        options = Y.merge(this.options, options);
4831
 
4832
        // Clone the attributes object so we don't end up modifying it by ref.
4833
        options.attributes = Y.merge(this.options.attributes,
4834
                options.attributes);
4835
 
4836
        for (i = 0, len = urls.length; i < len; ++i) {
4837
            url = urls[i];
4838
            req = {attributes: {}};
4839
 
4840
            // If `url` is a string, we create a URL object for it, then mix in
4841
            // global options and request-specific options. If it's an object
4842
            // with a "url" property, we assume it's a request object containing
4843
            // URL-specific options.
4844
            if (typeof url === 'string') {
4845
                req.url = url;
4846
            } else if (url.url) {
4847
                // URL-specific options override both global defaults and
4848
                // request-specific options.
4849
                Y.mix(req, url, false, null, 0, true);
4850
                url = url.url; // Make url a string so we can use it later.
4851
            } else {
4852
                Y.log('URL must be a string or an object with a `url` property.', 'error', 'get');
4853
                continue;
4854
            }
4855
 
4856
            Y.mix(req, options, false, null, 0, true);
4857
 
4858
            // If we didn't get an explicit type for this URL either in the
4859
            // request options or the URL-specific options, try to determine
4860
            // one from the file extension.
4861
            if (!req.type) {
4862
                if (this.REGEX_CSS.test(url)) {
4863
                    req.type = 'css';
4864
                } else {
4865
                    if (!this.REGEX_JS.test(url)) {
4866
                        Y.log("Can't guess file type from URL. Assuming JS: " + url, 'warn', 'get');
4867
                    }
4868
 
4869
                    req.type = 'js';
4870
                }
4871
            }
4872
 
4873
            // Mix in type-specific default options, but don't overwrite any
4874
            // options that have already been set.
4875
            Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions,
4876
                false, null, 0, true);
4877
 
4878
            // Give the node an id attribute if it doesn't already have one.
4879
            req.attributes.id || (req.attributes.id = Y.guid());
4880
 
4881
            // Backcompat for <3.5.0 behavior.
4882
            if (req.win) {
4883
                Y.log('The `win` option is deprecated as of 3.5.0. Use `doc` instead.', 'warn', 'get');
4884
                req.doc = req.win.document;
4885
            } else {
4886
                req.win = req.doc.defaultView || req.doc.parentWindow;
4887
            }
4888
 
4889
            if (req.charset) {
4890
                Y.log('The `charset` option is deprecated as of 3.5.0. Set `attributes.charset` instead.', 'warn', 'get');
4891
                req.attributes.charset = req.charset;
4892
            }
4893
 
4894
            requests.push(req);
4895
        }
4896
 
4897
        return new Transaction(requests, options);
4898
    },
4899
 
4900
    _load: function (type, urls, options, callback) {
4901
        var transaction;
4902
 
4903
        // Allow callback as third param.
4904
        if (typeof options === 'function') {
4905
            callback = options;
4906
            options  = {};
4907
        }
4908
 
4909
        options || (options = {});
4910
        options.type = type;
4911
 
4912
        options._onFinish = Get._onTransactionFinish;
4913
 
4914
        if (!this._env) {
4915
            this._getEnv();
4916
        }
4917
 
4918
        transaction = this._getTransaction(urls, options);
4919
 
4920
        this._queue.push({
4921
            callback   : callback,
4922
            transaction: transaction
4923
        });
4924
 
4925
        this._next();
4926
 
4927
        return transaction;
4928
    },
4929
 
4930
    _onTransactionFinish : function() {
4931
        Get._pending = null;
4932
        Get._next();
4933
    },
4934
 
4935
    _next: function () {
4936
        var item;
4937
 
4938
        if (this._pending) {
4939
            return;
4940
        }
4941
 
4942
        item = this._queue.shift();
4943
 
4944
        if (item) {
4945
            this._pending = item;
4946
            item.transaction.execute(item.callback);
4947
        }
4948
    },
4949
 
4950
    _purge: function (nodes) {
4951
        var purgeNodes    = this._purgeNodes,
4952
            isTransaction = nodes !== purgeNodes,
4953
            index, node;
4954
 
4955
        while (node = nodes.pop()) { // assignment
4956
            // Don't purge nodes that haven't finished loading (or errored out),
4957
            // since this can hang the transaction.
4958
            if (!node._yuiget_finished) {
4959
                continue;
4960
            }
4961
 
4962
            node.parentNode && node.parentNode.removeChild(node);
4963
 
4964
            // If this is a transaction-level purge and this node also exists in
4965
            // the Get-level _purgeNodes array, we need to remove it from
4966
            // _purgeNodes to avoid creating a memory leak. The indexOf lookup
4967
            // sucks, but until we get WeakMaps, this is the least troublesome
4968
            // way to do this (we can't just hold onto node ids because they may
4969
            // not be in the same document).
4970
            if (isTransaction) {
4971
                index = Y.Array.indexOf(purgeNodes, node);
4972
 
4973
                if (index > -1) {
4974
                    purgeNodes.splice(index, 1);
4975
                }
4976
            }
4977
        }
4978
    }
4979
};
4980
 
4981
/**
4982
Alias for `js()`.
4983
 
4984
@method script
4985
@static
4986
**/
4987
Get.script = Get.js;
4988
 
4989
/**
4990
Represents a Get transaction, which may contain requests for one or more JS or
4991
CSS files.
4992
 
4993
This class should not be instantiated manually. Instances will be created and
4994
returned as needed by Y.Get's `css()`, `js()`, and `load()` methods.
4995
 
4996
@class Get.Transaction
4997
@constructor
4998
@since 3.5.0
4999
**/
5000
Get.Transaction = Transaction = function (requests, options) {
5001
    var self = this;
5002
 
5003
    self.id       = Transaction._lastId += 1;
5004
    self.data     = options.data;
5005
    self.errors   = [];
5006
    self.nodes    = [];
5007
    self.options  = options;
5008
    self.requests = requests;
5009
 
5010
    self._callbacks = []; // callbacks to call after execution finishes
5011
    self._queue     = [];
5012
    self._reqsWaiting   = 0;
5013
 
5014
    // Deprecated pre-3.5.0 properties.
5015
    self.tId = self.id; // Use `id` instead.
5016
    self.win = options.win || Y.config.win;
5017
};
5018
 
5019
/**
5020
Arbitrary data object associated with this transaction.
5021
 
5022
This object comes from the options passed to `Get.css()`, `Get.js()`, or
5023
`Get.load()`, and will be `undefined` if no data object was specified.
5024
 
5025
@property {Object} data
5026
**/
5027
 
5028
/**
5029
Array of errors that have occurred during this transaction, if any. Each error
5030
object has the following properties:
5031
`errors.error`: Error message.
5032
`errors.request`: Request object related to the error.
5033
 
5034
@since 3.5.0
5035
@property {Object[]} errors
5036
**/
5037
 
5038
/**
5039
Numeric id for this transaction, unique among all transactions within the same
5040
YUI sandbox in the current pageview.
5041
 
5042
@property {Number} id
5043
@since 3.5.0
5044
**/
5045
 
5046
/**
5047
HTMLElement nodes (native ones, not YUI Node instances) that have been inserted
5048
during the current transaction.
5049
 
5050
@property {HTMLElement[]} nodes
5051
**/
5052
 
5053
/**
5054
Options associated with this transaction.
5055
 
5056
See `Get.options` for the full list of available options.
5057
 
5058
@property {Object} options
5059
@since 3.5.0
5060
**/
5061
 
5062
/**
5063
Request objects contained in this transaction. Each request object represents
5064
one CSS or JS URL that will be (or has been) requested and loaded into the page.
5065
 
5066
@property {Object} requests
5067
@since 3.5.0
5068
**/
5069
 
5070
/**
5071
Id of the most recent transaction.
5072
 
5073
@property _lastId
5074
@type Number
5075
@protected
5076
@static
5077
**/
5078
Transaction._lastId = 0;
5079
 
5080
Transaction.prototype = {
5081
    // -- Public Properties ----------------------------------------------------
5082
 
5083
    /**
5084
    Current state of this transaction. One of "new", "executing", or "done".
5085
 
5086
    @property _state
5087
    @type String
5088
    @protected
5089
    **/
5090
    _state: 'new', // "new", "executing", or "done"
5091
 
5092
    // -- Public Methods -------------------------------------------------------
5093
 
5094
    /**
5095
    Aborts this transaction.
5096
 
5097
    This will cause the transaction's `onFailure` callback to be called and
5098
    will prevent any new script and link nodes from being added to the document,
5099
    but any resources that have already been requested will continue loading
5100
    (there's no safe way to prevent this, unfortunately).
5101
 
5102
    @method abort
5103
    @param {String} [msg="Aborted."] Optional message to use in the `errors`
5104
        array describing why the transaction was aborted.
5105
    **/
5106
    abort: function (msg) {
5107
        this._pending    = null;
5108
        this._pendingCSS = null;
5109
        this._pollTimer  = clearTimeout(this._pollTimer);
5110
        this._queue      = [];
5111
        this._reqsWaiting    = 0;
5112
 
5113
        this.errors.push({error: msg || 'Aborted'});
5114
        this._finish();
5115
    },
5116
 
5117
    /**
5118
    Begins execting the transaction.
5119
 
5120
    There's usually no reason to call this manually, since Get will call it
5121
    automatically when other pending transactions have finished. If you really
5122
    want to execute your transaction before Get does, you can, but be aware that
5123
    this transaction's scripts may end up executing before the scripts in other
5124
    pending transactions.
5125
 
5126
    If the transaction is already executing, the specified callback (if any)
5127
    will be queued and called after execution finishes. If the transaction has
5128
    already finished, the callback will be called immediately (the transaction
5129
    will not be executed again).
5130
 
5131
    @method execute
5132
    @param {Function} callback Callback function to execute after all requests
5133
        in the transaction are complete, or after the transaction is aborted.
5134
    **/
5135
    execute: function (callback) {
5136
        var self     = this,
5137
            requests = self.requests,
5138
            state    = self._state,
5139
            i, len, queue, req;
5140
 
5141
        if (state === 'done') {
5142
            callback && callback(self.errors.length ? self.errors : null, self);
5143
            return;
5144
        } else {
5145
            callback && self._callbacks.push(callback);
5146
 
5147
            if (state === 'executing') {
5148
                return;
5149
            }
5150
        }
5151
 
5152
        self._state = 'executing';
5153
        self._queue = queue = [];
5154
 
5155
        if (self.options.timeout) {
5156
            self._timeout = setTimeout(function () {
5157
                self.abort('Timeout');
5158
            }, self.options.timeout);
5159
        }
5160
 
5161
        self._reqsWaiting = requests.length;
5162
 
5163
        for (i = 0, len = requests.length; i < len; ++i) {
5164
            req = requests[i];
5165
 
5166
            if (req.async || req.type === 'css') {
5167
                // No need to queue CSS or fully async JS.
5168
                self._insert(req);
5169
            } else {
5170
                queue.push(req);
5171
            }
5172
        }
5173
 
5174
        self._next();
5175
    },
5176
 
5177
    /**
5178
    Manually purges any `<script>` or `<link>` nodes this transaction has
5179
    created.
5180
 
5181
    Be careful when purging a transaction that contains CSS requests, since
5182
    removing `<link>` nodes will also remove any styles they applied.
5183
 
5184
    @method purge
5185
    **/
5186
    purge: function () {
5187
        Get._purge(this.nodes);
5188
    },
5189
 
5190
    // -- Protected Methods ----------------------------------------------------
5191
    _createNode: function (name, attrs, doc) {
5192
        var node = doc.createElement(name),
5193
            attr, testEl;
5194
 
5195
        if (!CUSTOM_ATTRS) {
5196
            // IE6 and IE7 expect property names rather than attribute names for
5197
            // certain attributes. Rather than sniffing, we do a quick feature
5198
            // test the first time _createNode() runs to determine whether we
5199
            // need to provide a workaround.
5200
            testEl = doc.createElement('div');
5201
            testEl.setAttribute('class', 'a');
5202
 
5203
            CUSTOM_ATTRS = testEl.className === 'a' ? {} : {
5204
                'for'  : 'htmlFor',
5205
                'class': 'className'
5206
            };
5207
        }
5208
 
5209
        for (attr in attrs) {
5210
            if (attrs.hasOwnProperty(attr)) {
5211
                node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]);
5212
            }
5213
        }
5214
 
5215
        return node;
5216
    },
5217
 
5218
    _finish: function () {
5219
        var errors  = this.errors.length ? this.errors : null,
5220
            options = this.options,
5221
            thisObj = options.context || this,
5222
            data, i, len;
5223
 
5224
        if (this._state === 'done') {
5225
            return;
5226
        }
5227
 
5228
        this._state = 'done';
5229
 
5230
        for (i = 0, len = this._callbacks.length; i < len; ++i) {
5231
            this._callbacks[i].call(thisObj, errors, this);
5232
        }
5233
 
5234
        data = this._getEventData();
5235
 
5236
        if (errors) {
5237
            if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') {
5238
                options.onTimeout.call(thisObj, data);
5239
            }
5240
 
5241
            if (options.onFailure) {
5242
                options.onFailure.call(thisObj, data);
5243
            }
5244
        } else if (options.onSuccess) {
5245
            options.onSuccess.call(thisObj, data);
5246
        }
5247
 
5248
        if (options.onEnd) {
5249
            options.onEnd.call(thisObj, data);
5250
        }
5251
 
5252
        if (options._onFinish) {
5253
            options._onFinish();
5254
        }
5255
    },
5256
 
5257
    _getEventData: function (req) {
5258
        if (req) {
5259
            // This merge is necessary for backcompat. I hate it.
5260
            return Y.merge(this, {
5261
                abort  : this.abort, // have to copy these because the prototype isn't preserved
5262
                purge  : this.purge,
5263
                request: req,
5264
                url    : req.url,
5265
                win    : req.win
5266
            });
5267
        } else {
5268
            return this;
5269
        }
5270
    },
5271
 
5272
    _getInsertBefore: function (req) {
5273
        var doc = req.doc,
5274
            el  = req.insertBefore,
5275
            cache, docStamp;
5276
 
5277
        if (el) {
5278
            return typeof el === 'string' ? doc.getElementById(el) : el;
5279
        }
5280
 
5281
        cache    = Get._insertCache;
5282
        docStamp = Y.stamp(doc);
5283
 
5284
        if ((el = cache[docStamp])) { // assignment
5285
            return el;
5286
        }
5287
 
5288
        // Inserting before a <base> tag apparently works around an IE bug
5289
        // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what
5290
        // bug that is, exactly. Better safe than sorry?
5291
        if ((el = doc.getElementsByTagName('base')[0])) { // assignment
5292
            return (cache[docStamp] = el);
5293
        }
5294
 
5295
        // Look for a <head> element.
5296
        el = doc.head || doc.getElementsByTagName('head')[0];
5297
 
5298
        if (el) {
5299
            // Create a marker node at the end of <head> to use as an insertion
5300
            // point. Inserting before this node will ensure that all our CSS
5301
            // gets inserted in the correct order, to maintain style precedence.
5302
            el.appendChild(doc.createTextNode(''));
5303
            return (cache[docStamp] = el.lastChild);
5304
        }
5305
 
5306
        // If all else fails, just insert before the first script node on the
5307
        // page, which is virtually guaranteed to exist.
5308
        return (cache[docStamp] = doc.getElementsByTagName('script')[0]);
5309
    },
5310
 
5311
    _insert: function (req) {
5312
        var env          = Get._env,
5313
            insertBefore = this._getInsertBefore(req),
5314
            isScript     = req.type === 'js',
5315
            node         = req.node,
5316
            self         = this,
5317
            ua           = Y.UA,
5318
            cssTimeout, nodeType;
5319
 
5320
        if (!node) {
5321
            if (isScript) {
5322
                nodeType = 'script';
5323
            } else if (!env.cssLoad && ua.gecko) {
5324
                nodeType = 'style';
5325
            } else {
5326
                nodeType = 'link';
5327
            }
5328
 
5329
            node = req.node = this._createNode(nodeType, req.attributes,
5330
                req.doc);
5331
        }
5332
 
5333
        function onError() {
5334
            self._progress('Failed to load ' + req.url, req);
5335
        }
5336
 
5337
        function onLoad() {
5338
            if (cssTimeout) {
5339
                clearTimeout(cssTimeout);
5340
            }
5341
 
5342
            self._progress(null, req);
5343
        }
5344
 
5345
        // Deal with script asynchronicity.
5346
        if (isScript) {
5347
            node.setAttribute('src', req.url);
5348
 
5349
            if (req.async) {
5350
                // Explicitly indicate that we want the browser to execute this
5351
                // script asynchronously. This is necessary for older browsers
5352
                // like Firefox <4.
5353
                node.async = true;
5354
            } else {
5355
                if (env.async) {
5356
                    // This browser treats injected scripts as async by default
5357
                    // (standard HTML5 behavior) but asynchronous loading isn't
5358
                    // desired, so tell the browser not to mark this script as
5359
                    // async.
5360
                    node.async = false;
5361
                }
5362
 
5363
                // If this browser doesn't preserve script execution order based
5364
                // on insertion order, we'll need to avoid inserting other
5365
                // scripts until this one finishes loading.
5366
                if (!env.preservesScriptOrder) {
5367
                    this._pending = req;
5368
                }
5369
            }
5370
        } else {
5371
            if (!env.cssLoad && ua.gecko) {
5372
                // In Firefox <9, we can import the requested URL into a <style>
5373
                // node and poll for the existence of node.sheet.cssRules. This
5374
                // gives us a reliable way to determine CSS load completion that
5375
                // also works for cross-domain stylesheets.
5376
                //
5377
                // Props to Zach Leatherman for calling my attention to this
5378
                // technique.
5379
                node.innerHTML = (req.attributes.charset ?
5380
                    '@charset "' + req.attributes.charset + '";' : '') +
5381
                    '@import "' + req.url + '";';
5382
            } else {
5383
                node.setAttribute('href', req.url);
5384
            }
5385
        }
5386
 
5387
        // Inject the node.
5388
        if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) {
5389
            // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode.
5390
            node.onreadystatechange = function () {
5391
                if (/loaded|complete/.test(node.readyState)) {
5392
                    node.onreadystatechange = null;
5393
                    onLoad();
5394
                }
5395
            };
5396
        } else if (!isScript && !env.cssLoad) {
5397
            // CSS on Firefox <9 or WebKit.
5398
            this._poll(req);
5399
        } else {
5400
            // Script or CSS on everything else. Using DOM 0 events because that
5401
            // evens the playing field with older IEs.
5402
 
5403
            if (ua.ie >= 10) {
5404
 
5405
                // We currently need to introduce a timeout for IE10, since it
5406
                // calls onerror/onload synchronously for 304s - messing up existing
5407
                // program flow.
5408
 
5409
                // Remove this block if the following bug gets fixed by GA
5410
                /*jshint maxlen: 1500 */
5411
                // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload
5412
                node.onerror = function() { setTimeout(onError, 0); };
5413
                node.onload  = function() { setTimeout(onLoad, 0); };
5414
            } else {
5415
                node.onerror = onError;
5416
                node.onload  = onLoad;
5417
            }
5418
 
5419
            // If this browser doesn't fire an event when CSS fails to load,
5420
            // fail after a timeout to avoid blocking the transaction queue.
5421
            if (!env.cssFail && !isScript) {
5422
                cssTimeout = setTimeout(onError, req.timeout || 3000);
5423
            }
5424
        }
5425
 
5426
        this.nodes.push(node);
5427
        insertBefore.parentNode.insertBefore(node, insertBefore);
5428
    },
5429
 
5430
    _next: function () {
5431
        if (this._pending) {
5432
            return;
5433
        }
5434
 
5435
        // If there are requests in the queue, insert the next queued request.
5436
        // Otherwise, if we're waiting on already-inserted requests to finish,
5437
        // wait longer. If there are no queued requests and we're not waiting
5438
        // for anything to load, then we're done!
5439
        if (this._queue.length) {
5440
            this._insert(this._queue.shift());
5441
        } else if (!this._reqsWaiting) {
5442
            this._finish();
5443
        }
5444
    },
5445
 
5446
    _poll: function (newReq) {
5447
        var self       = this,
5448
            pendingCSS = self._pendingCSS,
5449
            isWebKit   = Y.UA.webkit,
5450
            i, hasRules, j, nodeHref, req, sheets;
5451
 
5452
        if (newReq) {
5453
            pendingCSS || (pendingCSS = self._pendingCSS = []);
5454
            pendingCSS.push(newReq);
5455
 
5456
            if (self._pollTimer) {
5457
                // A poll timeout is already pending, so no need to create a
5458
                // new one.
5459
                return;
5460
            }
5461
        }
5462
 
5463
        self._pollTimer = null;
5464
 
5465
        // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s
5466
        // will still be treated as a success. There's no good workaround for
5467
        // this.
5468
 
5469
        for (i = 0; i < pendingCSS.length; ++i) {
5470
            req = pendingCSS[i];
5471
 
5472
            if (isWebKit) {
5473
                // Look for a stylesheet matching the pending URL.
5474
                sheets   = req.doc.styleSheets;
5475
                j        = sheets.length;
5476
                nodeHref = req.node.href;
5477
 
5478
                while (--j >= 0) {
5479
                    if (sheets[j].href === nodeHref) {
5480
                        pendingCSS.splice(i, 1);
5481
                        i -= 1;
5482
                        self._progress(null, req);
5483
                        break;
5484
                    }
5485
                }
5486
            } else {
5487
                // Many thanks to Zach Leatherman for calling my attention to
5488
                // the @import-based cross-domain technique used here, and to
5489
                // Oleg Slobodskoi for an earlier same-domain implementation.
5490
                //
5491
                // See Zach's blog for more details:
5492
                // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
5493
                try {
5494
                    // We don't really need to store this value since we never
5495
                    // use it again, but if we don't store it, Closure Compiler
5496
                    // assumes the code is useless and removes it.
5497
                    hasRules = !!req.node.sheet.cssRules;
5498
 
5499
                    // If we get here, the stylesheet has loaded.
5500
                    pendingCSS.splice(i, 1);
5501
                    i -= 1;
5502
                    self._progress(null, req);
5503
                } catch (ex) {
5504
                    // An exception means the stylesheet is still loading.
5505
                }
5506
            }
5507
        }
5508
 
5509
        if (pendingCSS.length) {
5510
            self._pollTimer = setTimeout(function () {
5511
                self._poll.call(self);
5512
            }, self.options.pollInterval);
5513
        }
5514
    },
5515
 
5516
    _progress: function (err, req) {
5517
        var options = this.options;
5518
 
5519
        if (err) {
5520
            req.error = err;
5521
 
5522
            this.errors.push({
5523
                error  : err,
5524
                request: req
5525
            });
5526
 
5527
            Y.log(err, 'error', 'get');
5528
        }
5529
 
5530
        req.node._yuiget_finished = req.finished = true;
5531
 
5532
        if (options.onProgress) {
5533
            options.onProgress.call(options.context || this,
5534
                this._getEventData(req));
5535
        }
5536
 
5537
        if (req.autopurge) {
5538
            // Pre-3.5.0 Get always excludes the most recent node from an
5539
            // autopurge. I find this odd, but I'm keeping that behavior for
5540
            // the sake of backcompat.
5541
            Get._autoPurge(this.options.purgethreshold);
5542
            Get._purgeNodes.push(req.node);
5543
        }
5544
 
5545
        if (this._pending === req) {
5546
            this._pending = null;
5547
        }
5548
 
5549
        this._reqsWaiting -= 1;
5550
 
5551
        this._next();
5552
    }
5553
};
5554
 
5555
 
5556
}, '3.18.1', {"requires": ["yui-base"]});
5557
YUI.add('features', function (Y, NAME) {
5558
 
5559
var feature_tests = {};
5560
 
5561
/**
5562
Contains the core of YUI's feature test architecture.
5563
@module features
5564
*/
5565
 
5566
/**
5567
* Feature detection
5568
* @class Features
5569
* @static
5570
*/
5571
 
5572
Y.mix(Y.namespace('Features'), {
5573
 
5574
    /**
5575
    * Object hash of all registered feature tests
5576
    * @property tests
5577
    * @type Object
5578
    */
5579
    tests: feature_tests,
5580
 
5581
    /**
5582
    * Add a test to the system
5583
    *
5584
    *   ```
5585
    *   Y.Features.add("load", "1", {});
5586
    *   ```
5587
    *
5588
    * @method add
5589
    * @param {String} cat The category, right now only 'load' is supported
5590
    * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
5591
    * @param {Object} o Object containing test properties
5592
    * @param {String} o.name The name of the test
5593
    * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
5594
    * @param {String} o.trigger The module that triggers this test.
5595
    */
5596
    add: function(cat, name, o) {
5597
        feature_tests[cat] = feature_tests[cat] || {};
5598
        feature_tests[cat][name] = o;
5599
    },
5600
    /**
5601
    * Execute all tests of a given category and return the serialized results
5602
    *
5603
    *   ```
5604
    *   caps=1:1;2:1;3:0
5605
    *   ```
5606
    * @method all
5607
    * @param {String} cat The category to execute
5608
    * @param {Array} args The arguments to pass to the test function
5609
    * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
5610
    */
5611
    all: function(cat, args) {
5612
        var cat_o = feature_tests[cat],
5613
            // results = {};
5614
            result = [];
5615
        if (cat_o) {
5616
            Y.Object.each(cat_o, function(v, k) {
5617
                result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
5618
            });
5619
        }
5620
 
5621
        return (result.length) ? result.join(';') : '';
5622
    },
5623
    /**
5624
    * Run a specific test and return a Boolean response.
5625
    *
5626
    *   ```
5627
    *   Y.Features.test("load", "1");
5628
    *   ```
5629
    *
5630
    * @method test
5631
    * @param {String} cat The category of the test to run
5632
    * @param {String} name The name of the test to run
5633
    * @param {Array} args The arguments to pass to the test function
5634
    * @return {Boolean} True or false if the test passed/failed.
5635
    */
5636
    test: function(cat, name, args) {
5637
        args = args || [];
5638
        var result, ua, test,
5639
            cat_o = feature_tests[cat],
5640
            feature = cat_o && cat_o[name];
5641
 
5642
        if (!feature) {
5643
            Y.log('Feature test ' + cat + ', ' + name + ' not found');
5644
        } else {
5645
 
5646
            result = feature.result;
5647
 
5648
            if (Y.Lang.isUndefined(result)) {
5649
 
5650
                ua = feature.ua;
5651
                if (ua) {
5652
                    result = (Y.UA[ua]);
5653
                }
5654
 
5655
                test = feature.test;
5656
                if (test && ((!ua) || result)) {
5657
                    result = test.apply(Y, args);
5658
                }
5659
 
5660
                feature.result = result;
5661
            }
5662
        }
5663
 
5664
        return result;
5665
    }
5666
});
5667
 
5668
// Y.Features.add("load", "1", {});
5669
// Y.Features.test("load", "1");
5670
// caps=1:1;2:0;3:1;
5671
 
5672
/* This file is auto-generated by (yogi loader --yes --mix --start ../) */
5673
/*jshint maxlen:900, eqeqeq: false */
5674
var add = Y.Features.add;
5675
// app-transitions-native
5676
add('load', '0', {
5677
    "name": "app-transitions-native",
5678
    "test": function (Y) {
5679
    var doc  = Y.config.doc,
5680
        node = doc ? doc.documentElement : null;
5681
 
5682
    if (node && node.style) {
5683
        return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
5684
    }
5685
 
5686
    return false;
5687
},
5688
    "trigger": "app-transitions"
5689
});
5690
// autocomplete-list-keys
5691
add('load', '1', {
5692
    "name": "autocomplete-list-keys",
5693
    "test": function (Y) {
5694
    // Only add keyboard support to autocomplete-list if this doesn't appear to
5695
    // be an iOS or Android-based mobile device.
5696
    //
5697
    // There's currently no feasible way to actually detect whether a device has
5698
    // a hardware keyboard, so this sniff will have to do. It can easily be
5699
    // overridden by manually loading the autocomplete-list-keys module.
5700
    //
5701
    // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
5702
    // doesn't fire the keyboard events used by AutoCompleteList, so there's
5703
    // no point loading the -keys module even when a bluetooth keyboard may be
5704
    // available.
5705
    return !(Y.UA.ios || Y.UA.android);
5706
},
5707
    "trigger": "autocomplete-list"
5708
});
5709
// dd-gestures
5710
add('load', '2', {
5711
    "name": "dd-gestures",
5712
    "trigger": "dd-drag",
5713
    "ua": "touchEnabled"
5714
});
5715
// dom-style-ie
5716
add('load', '3', {
5717
    "name": "dom-style-ie",
5718
    "test": function (Y) {
5719
 
5720
    var testFeature = Y.Features.test,
5721
        addFeature = Y.Features.add,
5722
        WINDOW = Y.config.win,
5723
        DOCUMENT = Y.config.doc,
5724
        DOCUMENT_ELEMENT = 'documentElement',
5725
        ret = false;
5726
 
5727
    addFeature('style', 'computedStyle', {
5728
        test: function() {
5729
            return WINDOW && 'getComputedStyle' in WINDOW;
5730
        }
5731
    });
5732
 
5733
    addFeature('style', 'opacity', {
5734
        test: function() {
5735
            return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
5736
        }
5737
    });
5738
 
5739
    ret =  (!testFeature('style', 'opacity') &&
5740
            !testFeature('style', 'computedStyle'));
5741
 
5742
    return ret;
5743
},
5744
    "trigger": "dom-style"
5745
});
5746
// editor-para-ie
5747
add('load', '4', {
5748
    "name": "editor-para-ie",
5749
    "trigger": "editor-para",
5750
    "ua": "ie",
5751
    "when": "instead"
5752
});
5753
// event-base-ie
5754
add('load', '5', {
5755
    "name": "event-base-ie",
5756
    "test": function(Y) {
5757
    var imp = Y.config.doc && Y.config.doc.implementation;
5758
    return (imp && (!imp.hasFeature('Events', '2.0')));
5759
},
5760
    "trigger": "node-base"
5761
});
5762
// graphics-canvas
5763
add('load', '6', {
5764
    "name": "graphics-canvas",
5765
    "test": function(Y) {
5766
    var DOCUMENT = Y.config.doc,
5767
        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
5768
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5769
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5770
    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
5771
},
5772
    "trigger": "graphics"
5773
});
5774
// graphics-canvas-default
5775
add('load', '7', {
5776
    "name": "graphics-canvas-default",
5777
    "test": function(Y) {
5778
    var DOCUMENT = Y.config.doc,
5779
        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
5780
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5781
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5782
    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
5783
},
5784
    "trigger": "graphics"
5785
});
5786
// graphics-svg
5787
add('load', '8', {
5788
    "name": "graphics-svg",
5789
    "test": function(Y) {
5790
    var DOCUMENT = Y.config.doc,
5791
        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
5792
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5793
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5794
 
5795
    return svg && (useSVG || !canvas);
5796
},
5797
    "trigger": "graphics"
5798
});
5799
// graphics-svg-default
5800
add('load', '9', {
5801
    "name": "graphics-svg-default",
5802
    "test": function(Y) {
5803
    var DOCUMENT = Y.config.doc,
5804
        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
5805
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5806
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5807
 
5808
    return svg && (useSVG || !canvas);
5809
},
5810
    "trigger": "graphics"
5811
});
5812
// graphics-vml
5813
add('load', '10', {
5814
    "name": "graphics-vml",
5815
    "test": function(Y) {
5816
    var DOCUMENT = Y.config.doc,
5817
		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5818
    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
5819
},
5820
    "trigger": "graphics"
5821
});
5822
// graphics-vml-default
5823
add('load', '11', {
5824
    "name": "graphics-vml-default",
5825
    "test": function(Y) {
5826
    var DOCUMENT = Y.config.doc,
5827
		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5828
    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
5829
},
5830
    "trigger": "graphics"
5831
});
5832
// history-hash-ie
5833
add('load', '12', {
5834
    "name": "history-hash-ie",
5835
    "test": function (Y) {
5836
    var docMode = Y.config.doc && Y.config.doc.documentMode;
5837
 
5838
    return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
5839
            !docMode || docMode < 8);
5840
},
5841
    "trigger": "history-hash"
5842
});
5843
// io-nodejs
5844
add('load', '13', {
5845
    "name": "io-nodejs",
5846
    "trigger": "io-base",
5847
    "ua": "nodejs"
5848
});
5849
// json-parse-shim
5850
add('load', '14', {
5851
    "name": "json-parse-shim",
5852
    "test": function (Y) {
5853
    var _JSON = Y.config.global.JSON,
5854
        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
5855
        nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
5856
 
5857
    function workingNative( k, v ) {
5858
        return k === "ok" ? true : v;
5859
    }
5860
 
5861
    // Double check basic functionality.  This is mainly to catch early broken
5862
    // implementations of the JSON API in Firefox 3.1 beta1 and beta2
5863
    if ( nativeSupport ) {
5864
        try {
5865
            nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
5866
        }
5867
        catch ( e ) {
5868
            nativeSupport = false;
5869
        }
5870
    }
5871
 
5872
    return !nativeSupport;
5873
},
5874
    "trigger": "json-parse"
5875
});
5876
// json-stringify-shim
5877
add('load', '15', {
5878
    "name": "json-stringify-shim",
5879
    "test": function (Y) {
5880
    var _JSON = Y.config.global.JSON,
5881
        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
5882
        nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
5883
 
5884
    // Double check basic native functionality.  This is primarily to catch broken
5885
    // early JSON API implementations in Firefox 3.1 beta1 and beta2.
5886
    if ( nativeSupport ) {
5887
        try {
5888
            nativeSupport = ( '0' === Native.stringify(0) );
5889
        } catch ( e ) {
5890
            nativeSupport = false;
5891
        }
5892
    }
5893
 
5894
 
5895
    return !nativeSupport;
5896
},
5897
    "trigger": "json-stringify"
5898
});
5899
// scrollview-base-ie
5900
add('load', '16', {
5901
    "name": "scrollview-base-ie",
5902
    "trigger": "scrollview-base",
5903
    "ua": "ie"
5904
});
5905
// selector-css2
5906
add('load', '17', {
5907
    "name": "selector-css2",
5908
    "test": function (Y) {
5909
    var DOCUMENT = Y.config.doc,
5910
        ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
5911
 
5912
    return ret;
5913
},
5914
    "trigger": "selector"
5915
});
5916
// transition-timer
5917
add('load', '18', {
5918
    "name": "transition-timer",
5919
    "test": function (Y) {
5920
    var DOCUMENT = Y.config.doc,
5921
        node = (DOCUMENT) ? DOCUMENT.documentElement: null,
5922
        ret = true;
5923
 
5924
    if (node && node.style) {
5925
        ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
5926
    }
5927
 
5928
    return ret;
5929
},
5930
    "trigger": "transition"
5931
});
5932
// widget-base-ie
5933
add('load', '19', {
5934
    "name": "widget-base-ie",
5935
    "trigger": "widget-base",
5936
    "ua": "ie"
5937
});
5938
// yql-jsonp
5939
add('load', '20', {
5940
    "name": "yql-jsonp",
5941
    "test": function (Y) {
5942
    /* Only load the JSONP module when not in nodejs or winjs
5943
    TODO Make the winjs module a CORS module
5944
    */
5945
    return (!Y.UA.nodejs && !Y.UA.winjs);
5946
},
5947
    "trigger": "yql"
5948
});
5949
// yql-nodejs
5950
add('load', '21', {
5951
    "name": "yql-nodejs",
5952
    "trigger": "yql",
5953
    "ua": "nodejs"
5954
});
5955
// yql-winjs
5956
add('load', '22', {
5957
    "name": "yql-winjs",
5958
    "trigger": "yql",
5959
    "ua": "winjs"
5960
});
5961
 
5962
}, '3.18.1', {"requires": ["yui-base"]});
5963
YUI.add('intl-base', function (Y, NAME) {
5964
 
5965
/**
5966
 * The Intl utility provides a central location for managing sets of
5967
 * localized resources (strings and formatting patterns).
5968
 *
5969
 * @class Intl
5970
 * @uses EventTarget
5971
 * @static
5972
 */
5973
 
5974
var SPLIT_REGEX = /[, ]/;
5975
 
5976
Y.mix(Y.namespace('Intl'), {
5977
 
5978
 /**
5979
    * Returns the language among those available that
5980
    * best matches the preferred language list, using the Lookup
5981
    * algorithm of BCP 47.
5982
    * If none of the available languages meets the user's preferences,
5983
    * then "" is returned.
5984
    * Extended language ranges are not supported.
5985
    *
5986
    * @method lookupBestLang
5987
    * @param {String[] | String} preferredLanguages The list of preferred
5988
    * languages in descending preference order, represented as BCP 47
5989
    * language tags. A string array or a comma-separated list.
5990
    * @param {String[]} availableLanguages The list of languages
5991
    * that the application supports, represented as BCP 47 language
5992
    * tags.
5993
    *
5994
    * @return {String} The available language that best matches the
5995
    * preferred language list, or "".
5996
    * @since 3.1.0
5997
    */
5998
    lookupBestLang: function(preferredLanguages, availableLanguages) {
5999
 
6000
        var i, language, result, index;
6001
 
6002
        // check whether the list of available languages contains language;
6003
        // if so return it
6004
        function scan(language) {
6005
            var i;
6006
            for (i = 0; i < availableLanguages.length; i += 1) {
6007
                if (language.toLowerCase() ===
6008
                            availableLanguages[i].toLowerCase()) {
6009
                    return availableLanguages[i];
6010
                }
6011
            }
6012
        }
6013
 
6014
        if (Y.Lang.isString(preferredLanguages)) {
6015
            preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
6016
        }
6017
 
6018
        for (i = 0; i < preferredLanguages.length; i += 1) {
6019
            language = preferredLanguages[i];
6020
            if (!language || language === '*') {
6021
                continue;
6022
            }
6023
            // check the fallback sequence for one language
6024
            while (language.length > 0) {
6025
                result = scan(language);
6026
                if (result) {
6027
                    return result;
6028
                } else {
6029
                    index = language.lastIndexOf('-');
6030
                    if (index >= 0) {
6031
                        language = language.substring(0, index);
6032
                        // one-character subtags get cut along with the
6033
                        // following subtag
6034
                        if (index >= 2 && language.charAt(index - 2) === '-') {
6035
                            language = language.substring(0, index - 2);
6036
                        }
6037
                    } else {
6038
                        // nothing available for this language
6039
                        break;
6040
                    }
6041
                }
6042
            }
6043
        }
6044
 
6045
        return '';
6046
    }
6047
});
6048
 
6049
 
6050
}, '3.18.1', {"requires": ["yui-base"]});
6051
YUI.add('yui-log', function (Y, NAME) {
6052
 
6053
/**
6054
 * Provides console log capability and exposes a custom event for
6055
 * console implementations. This module is a `core` YUI module,
6056
 * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
6057
 *
6058
 * @module yui
6059
 * @submodule yui-log
6060
 */
6061
 
6062
var INSTANCE = Y,
6063
    LOGEVENT = 'yui:log',
6064
    UNDEFINED = 'undefined',
6065
    LEVELS = { debug: 1,
6066
               info: 2,
6067
               warn: 4,
6068
               error: 8 };
6069
 
6070
/**
6071
 * If the 'debug' config is true, a 'yui:log' event will be
6072
 * dispatched, which the Console widget and anything else
6073
 * can consume.  If the 'useBrowserConsole' config is true, it will
6074
 * write to the browser console if available.  YUI-specific log
6075
 * messages will only be present in the -debug versions of the
6076
 * JS files.  The build system is supposed to remove log statements
6077
 * from the raw and minified versions of the files.
6078
 *
6079
 * @method log
6080
 * @for YUI
6081
 * @param  {String}  msg  The message to log.
6082
 * @param  {String}  cat  The log category for the message.  Default
6083
 *                        categories are "info", "warn", "error", "debug".
6084
 *                        Custom categories can be used as well. (opt).
6085
 * @param  {String}  src  The source of the the message (opt).
6086
 * @param  {boolean} silent If true, the log event won't fire.
6087
 * @return {YUI}      YUI instance.
6088
 */
6089
INSTANCE.log = function(msg, cat, src, silent) {
6090
    var bail, excl, incl, m, f, minlevel,
6091
        Y = INSTANCE,
6092
        c = Y.config,
6093
        publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
6094
    // suppress log message if the config is off or the event stack
6095
    // or the event call stack contains a consumer of the yui:log event
6096
    if (c.debug) {
6097
        // apply source filters
6098
        src = src || "";
6099
        if (typeof src !== "undefined") {
6100
            excl = c.logExclude;
6101
            incl = c.logInclude;
6102
            if (incl && !(src in incl)) {
6103
                bail = 1;
6104
            } else if (incl && (src in incl)) {
6105
                bail = !incl[src];
6106
            } else if (excl && (src in excl)) {
6107
                bail = excl[src];
6108
            }
6109
 
6110
            // Set a default category of info if the category was not defined.
6111
            if ((typeof cat === 'undefined')) {
6112
                cat = 'info';
6113
            }
6114
 
6115
            // Determine the current minlevel as defined in configuration
6116
            Y.config.logLevel = Y.config.logLevel || 'debug';
6117
            minlevel = LEVELS[Y.config.logLevel.toLowerCase()];
6118
 
6119
            if (cat in LEVELS && LEVELS[cat] < minlevel) {
6120
                // Skip this message if the we don't meet the defined minlevel
6121
                bail = 1;
6122
            }
6123
        }
6124
        if (!bail) {
6125
            if (c.useBrowserConsole) {
6126
                m = (src) ? src + ': ' + msg : msg;
6127
                if (Y.Lang.isFunction(c.logFn)) {
6128
                    c.logFn.call(Y, msg, cat, src);
6129
                } else if (typeof console !== UNDEFINED && console.log) {
6130
                    f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
6131
                    console[f](m);
6132
                } else if (typeof opera !== UNDEFINED) {
6133
                    opera.postError(m);
6134
                }
6135
            }
6136
 
6137
            if (publisher && !silent) {
6138
 
6139
                if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
6140
                    publisher.publish(LOGEVENT, {
6141
                        broadcast: 2
6142
                    });
6143
                }
6144
 
6145
                publisher.fire(LOGEVENT, {
6146
                    msg: msg,
6147
                    cat: cat,
6148
                    src: src
6149
                });
6150
            }
6151
        }
6152
    }
6153
 
6154
    return Y;
6155
};
6156
 
6157
/**
6158
 * Write a system message.  This message will be preserved in the
6159
 * minified and raw versions of the YUI files, unlike log statements.
6160
 * @method message
6161
 * @for YUI
6162
 * @param  {String}  msg  The message to log.
6163
 * @param  {String}  cat  The log category for the message.  Default
6164
 *                        categories are "info", "warn", "error", "debug".
6165
 *                        Custom categories can be used as well. (opt).
6166
 * @param  {String}  src  The source of the the message (opt).
6167
 * @param  {boolean} silent If true, the log event won't fire.
6168
 * @return {YUI}      YUI instance.
6169
 */
6170
INSTANCE.message = function() {
6171
    return INSTANCE.log.apply(INSTANCE, arguments);
6172
};
6173
 
6174
 
6175
}, '3.18.1', {"requires": ["yui-base"]});
6176
YUI.add('yui-later', function (Y, NAME) {
6177
 
6178
/**
6179
 * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module,
6180
 * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
6181
 *
6182
 * @module yui
6183
 * @submodule yui-later
6184
 */
6185
 
6186
var NO_ARGS = [];
6187
 
6188
/**
6189
 * Executes the supplied function in the context of the supplied
6190
 * object 'when' milliseconds later.  Executes the function a
6191
 * single time unless periodic is set to true.
6192
 * @for YUI
6193
 * @method later
6194
 * @param when {Number} the number of milliseconds to wait until the fn
6195
 * is executed.
6196
 * @param o the context object.
6197
 * @param fn {Function|String} the function to execute or the name of
6198
 * the method in the 'o' object to execute.
6199
 * @param data [Array] data that is provided to the function.  This
6200
 * accepts either a single item or an array.  If an array is provided,
6201
 * the function is executed with one parameter for each array item.
6202
 * If you need to pass a single array parameter, it needs to be wrapped
6203
 * in an array [myarray].
6204
 *
6205
 * Note: native methods in IE may not have the call and apply methods.
6206
 * In this case, it will work, but you are limited to four arguments.
6207
 *
6208
 * @param periodic {boolean} if true, executes continuously at supplied
6209
 * interval until canceled.
6210
 * @return {object} a timer object. Call the cancel() method on this
6211
 * object to stop the timer.
6212
 */
6213
Y.later = function(when, o, fn, data, periodic) {
6214
    when = when || 0;
6215
    data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS;
6216
    o = o || Y.config.win || Y;
6217
 
6218
    var cancelled = false,
6219
        method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
6220
        wrapper = function() {
6221
            // IE 8- may execute a setInterval callback one last time
6222
            // after clearInterval was called, so in order to preserve
6223
            // the cancel() === no more runny-run, we have to jump through
6224
            // an extra hoop.
6225
            if (!cancelled) {
6226
                if (!method.apply) {
6227
                    method(data[0], data[1], data[2], data[3]);
6228
                } else {
6229
                    method.apply(o, data || NO_ARGS);
6230
                }
6231
            }
6232
        },
6233
        id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
6234
 
6235
    return {
6236
        id: id,
6237
        interval: periodic,
6238
        cancel: function() {
6239
            cancelled = true;
6240
            if (this.interval) {
6241
                clearInterval(id);
6242
            } else {
6243
                clearTimeout(id);
6244
            }
6245
        }
6246
    };
6247
};
6248
 
6249
Y.Lang.later = Y.later;
6250
 
6251
 
6252
 
6253
}, '3.18.1', {"requires": ["yui-base"]});
6254
YUI.add('yui', function (Y, NAME) {}, '3.18.1', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});