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
    },
559
 
560
    /**
561
    Executes the named method on the specified YUI instance if that method is
562
    whitelisted.
563
 
564
    @method applyTo
565
    @param {String} id YUI instance id.
566
    @param {String} method Name of the method to execute. For example:
567
        'Object.keys'.
568
    @param {Array} args Arguments to apply to the method.
569
    @return {Mixed} Return value from the applied method, or `null` if the
570
        specified instance was not found or the method was not whitelisted.
571
    **/
572
    applyTo: function(id, method, args) {
573
        if (!(method in APPLY_TO_AUTH)) {
574
            this.log(method + ': applyTo not allowed', 'warn', 'yui');
575
            return null;
576
        }
577
 
578
        var instance = instances[id], nest, m, i;
579
        if (instance) {
580
            nest = method.split('.');
581
            m = instance;
582
            for (i = 0; i < nest.length; i = i + 1) {
583
                m = m[nest[i]];
584
                if (!m) {
585
                    this.log('applyTo not found: ' + method, 'warn', 'yui');
586
                }
587
            }
588
            return m && m.apply(instance, args);
589
        }
590
 
591
        return null;
592
    },
593
 
594
/**
595
Registers a YUI module and makes it available for use in a `YUI().use()` call or
596
as a dependency for other modules.
597
 
598
The easiest way to create a first-class YUI module is to use
599
<a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
600
tool.
601
 
602
Shifter will automatically wrap your module code in a `YUI.add()` call along
603
with any configuration info required for the module.
604
 
605
@example
606
 
607
    YUI.add('davglass', function (Y) {
608
        Y.davglass = function () {
609
        };
610
    }, '3.4.0', {
611
        requires: ['harley-davidson', 'mt-dew']
612
    });
613
 
614
@method add
615
@param {String} name Module name.
616
@param {Function} fn Function containing module code. This function will be
617
    executed whenever the module is attached to a specific YUI instance.
618
 
619
    @param {YUI} fn.Y The YUI instance to which this module is attached.
620
    @param {String} fn.name Name of the module
621
 
622
@param {String} version Module version number. This is currently used only for
623
    informational purposes, and is not used internally by YUI.
624
 
625
@param {Object} [details] Module config.
626
    @param {Array} [details.requires] Array of other module names that must be
627
        attached before this module can be attached.
628
    @param {Array} [details.optional] Array of optional module names that should
629
        be attached before this module is attached if they've already been
630
        loaded. If the `loadOptional` YUI option is `true`, optional modules
631
        that have not yet been loaded will be loaded just as if they were hard
632
        requirements.
633
    @param {Array} [details.use] Array of module names that are included within
634
        or otherwise provided by this module, and which should be attached
635
        automatically when this module is attached. This makes it possible to
636
        create "virtual rollup" modules that simply attach a collection of other
637
        modules or submodules.
638
 
639
@return {YUI} This YUI instance.
640
**/
641
    add: function(name, fn, version, details) {
642
        details = details || {};
643
        var env = YUI.Env,
644
            mod = {
645
                name: name,
646
                fn: fn,
647
                version: version,
648
                details: details
649
            },
650
            //Instance hash so we don't apply it to the same instance twice
651
            applied = {},
652
            loader, inst, modInfo,
653
            i, versions = env.versions;
654
 
655
        env.mods[name] = mod;
656
        versions[version] = versions[version] || {};
657
        versions[version][name] = mod;
658
 
659
        for (i in instances) {
660
            if (instances.hasOwnProperty(i)) {
661
                inst = instances[i];
662
                if (!applied[inst.id]) {
663
                    applied[inst.id] = true;
664
                    loader = inst.Env._loader;
665
                    if (loader) {
666
                        modInfo = loader.getModuleInfo(name);
667
                        if (!modInfo || modInfo.temp) {
668
                            loader.addModule(details, name);
669
                        }
670
                    }
671
                }
672
            }
673
        }
674
 
675
        return this;
676
    },
677
 
678
    /**
679
    Executes the callback function associated with each required module,
680
    attaching the module to this YUI instance.
681
 
682
    @method _attach
683
    @param {Array} r The array of modules to attach
684
    @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
685
        is not attached.
686
    @private
687
    **/
688
    _attach: function(r, moot) {
689
        var i, name, mod, details, req, use, after,
690
            mods = YUI.Env.mods,
691
            aliases = YUI.Env.aliases,
692
            Y = this, j,
693
            cache = YUI.Env._renderedMods,
694
            loader = Y.Env._loader,
695
            done = Y.Env._attached,
696
            exported = Y.Env._exported,
697
            len = r.length, loader, def, go,
698
            c = [],
699
            modArgs, esCompat, reqlen, modInfo,
700
            condition,
701
            __exports__, __imports__;
702
 
703
        //Check for conditional modules (in a second+ instance) and add their requirements
704
        //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
705
        for (i = 0; i < len; i++) {
706
            name = r[i];
707
            mod = mods[name];
708
            c.push(name);
709
            if (loader && loader.conditions[name]) {
710
                for (j in loader.conditions[name]) {
711
                    if (loader.conditions[name].hasOwnProperty(j)) {
712
                        def = loader.conditions[name][j];
713
                        go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
714
                        if (go) {
715
                            c.push(def.name);
716
                        }
717
                    }
718
                }
719
            }
720
        }
721
        r = c;
722
        len = r.length;
723
 
724
        for (i = 0; i < len; i++) {
725
            if (!done[r[i]]) {
726
                name = r[i];
727
                mod = mods[name];
728
 
729
                if (aliases && aliases[name] && !mod) {
730
                    Y._attach(aliases[name]);
731
                    continue;
732
                }
733
                if (!mod) {
734
                    modInfo = loader && loader.getModuleInfo(name);
735
                    if (modInfo) {
736
                        mod = modInfo;
737
                        moot = true;
738
                    }
739
 
740
 
741
                    //if (!loader || !loader.moduleInfo[name]) {
742
                    //if ((!loader || !loader.moduleInfo[name]) && !moot) {
743
                    if (!moot && name) {
744
                        if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
745
                            Y.Env._missed.push(name);
746
                            Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
747
                            Y.message('NOT loaded: ' + name, 'warn', 'yui');
748
                        }
749
                    }
750
                } else {
751
                    done[name] = true;
752
                    //Don't like this, but in case a mod was asked for once, then we fetch it
753
                    //We need to remove it from the missed list ^davglass
754
                    for (j = 0; j < Y.Env._missed.length; j++) {
755
                        if (Y.Env._missed[j] === name) {
756
                            Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
757
                            Y.Env._missed.splice(j, 1);
758
                        }
759
                    }
760
 
761
                    // Optional dependencies normally work by modifying the
762
                    // dependency list of a module. If the dependency's test
763
                    // passes it is added to the list. If not, it's not loaded.
764
                    // This following check ensures that optional dependencies
765
                    // are not attached when they were already loaded into the
766
                    // page (when bundling for example)
767
                    if (loader && !loader._canBeAttached(name)) {
768
                        return true;
769
                    }
770
 
771
                    /*
772
                        If it's a temp module, we need to redo it's requirements if it's already loaded
773
                        since it may have been loaded by another instance and it's dependencies might
774
                        have been redefined inside the fetched file.
775
                    */
776
                    if (loader && cache && cache[name] && cache[name].temp) {
777
                        loader.getRequires(cache[name]);
778
                        req = [];
779
                        modInfo = loader.getModuleInfo(name);
780
                        for (j in modInfo.expanded_map) {
781
                            if (modInfo.expanded_map.hasOwnProperty(j)) {
782
                                req.push(j);
783
                            }
784
                        }
785
                        Y._attach(req);
786
                    }
787
 
788
                    details = mod.details;
789
                    req = details.requires;
790
                    esCompat = details.es;
791
                    use = details.use;
792
                    after = details.after;
793
                    //Force Intl load if there is a language (Loader logic) @todo fix this shit
794
                    if (details.lang) {
795
                        req = req || [];
796
                        req.unshift('intl');
797
                    }
798
 
799
                    if (req) {
800
                        reqlen = req.length;
801
                        for (j = 0; j < reqlen; j++) {
802
                            if (!done[req[j]]) {
803
                                if (!Y._attach(req)) {
804
                                    return false;
805
                                }
806
                                break;
807
                            }
808
                        }
809
                    }
810
 
811
                    if (after) {
812
                        for (j = 0; j < after.length; j++) {
813
                            if (!done[after[j]]) {
814
                                if (!Y._attach(after, true)) {
815
                                    return false;
816
                                }
817
                                break;
818
                            }
819
                        }
820
                    }
821
 
822
                    if (mod.fn) {
823
                        modArgs = [Y, name];
824
                        if (esCompat) {
825
                            __imports__ = {};
826
                            __exports__ = {};
827
                            // passing `exports` and `imports` onto the module function
828
                            modArgs.push(__imports__, __exports__);
829
                            if (req) {
830
                                reqlen = req.length;
831
                                for (j = 0; j < reqlen; j++) {
832
                                    __imports__[req[j]] = exported.hasOwnProperty(req[j]) ? exported[req[j]] : Y;
833
                                }
834
                            }
835
                        }
836
                        if (Y.config.throwFail) {
837
                            __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs);
838
                        } else {
839
                            try {
840
                                __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs);
841
                            } catch (e) {
842
                                Y.error('Attach error: ' + name, e, name);
843
                                return false;
844
                            }
845
                        }
846
                        if (esCompat) {
847
                            // store the `exports` in case others `es` modules requires it
848
                            exported[name] = __exports__;
849
 
850
                            // If an ES module is conditionally loaded and set
851
                            // to be used "instead" another module, replace the
852
                            // trigger module's content with the conditionally
853
                            // loaded one so the values returned by require()
854
                            // still makes sense
855
                            condition = mod.details.condition;
856
                            if (condition && condition.when === 'instead') {
857
                                exported[condition.trigger] = __exports__;
858
                            }
859
                        }
860
                    }
861
 
862
                    if (use) {
863
                        for (j = 0; j < use.length; j++) {
864
                            if (!done[use[j]]) {
865
                                if (!Y._attach(use)) {
866
                                    return false;
867
                                }
868
                                break;
869
                            }
870
                        }
871
                    }
872
 
873
 
874
 
875
                }
876
            }
877
        }
878
 
879
        return true;
880
    },
881
 
882
    /**
883
    Delays the `use` callback until another event has taken place such as
884
    `window.onload`, `domready`, `contentready`, or `available`.
885
 
886
    @private
887
    @method _delayCallback
888
    @param {Function} cb The original `use` callback.
889
    @param {String|Object} until Either an event name ('load', 'domready', etc.)
890
        or an object containing event/args keys for contentready/available.
891
    @return {Function}
892
    **/
893
    _delayCallback: function(cb, until) {
894
 
895
        var Y = this,
896
            mod = ['event-base'];
897
 
898
        until = (Y.Lang.isObject(until) ? until : { event: until });
899
 
900
        if (until.event === 'load') {
901
            mod.push('event-synthetic');
902
        }
903
 
904
        return function() {
905
            var args = arguments;
906
            Y._use(mod, function() {
907
                Y.on(until.event, function() {
908
                    args[1].delayUntil = until.event;
909
                    cb.apply(Y, args);
910
                }, until.args);
911
            });
912
        };
913
    },
914
 
915
    /**
916
    Attaches one or more modules to this YUI instance. When this is executed,
917
    the requirements of the desired modules are analyzed, and one of several
918
    things can happen:
919
 
920
 
921
      * All required modules have already been loaded, and just need to be
922
        attached to this YUI instance. In this case, the `use()` callback will
923
        be executed synchronously after the modules are attached.
924
 
925
      * One or more modules have not yet been loaded, or the Get utility is not
926
        available, or the `bootstrap` config option is `false`. In this case,
927
        a warning is issued indicating that modules are missing, but all
928
        available modules will still be attached and the `use()` callback will
929
        be executed synchronously.
930
 
931
      * One or more modules are missing and the Loader is not available but the
932
        Get utility is, and `bootstrap` is not `false`. In this case, the Get
933
        utility will be used to load the Loader, and we will then proceed to
934
        the following state:
935
 
936
      * One or more modules are missing and the Loader is available. In this
937
        case, the Loader will be used to resolve the dependency tree for the
938
        missing modules and load them and their dependencies. When the Loader is
939
        finished loading modules, the `use()` callback will be executed
940
        asynchronously.
941
 
942
    @example
943
 
944
        // Loads and attaches dd and its dependencies.
945
        YUI().use('dd', function (Y) {
946
            // ...
947
        });
948
 
949
        // Loads and attaches dd and node as well as all of their dependencies.
950
        YUI().use(['dd', 'node'], function (Y) {
951
            // ...
952
        });
953
 
954
        // Attaches all modules that have already been loaded.
955
        YUI().use('*', function (Y) {
956
            // ...
957
        });
958
 
959
        // Attaches a gallery module.
960
        YUI().use('gallery-yql', function (Y) {
961
            // ...
962
        });
963
 
964
        // Attaches a YUI 2in3 module.
965
        YUI().use('yui2-datatable', function (Y) {
966
            // ...
967
        });
968
 
969
    @method use
970
    @param {String|Array} modules* One or more module names to attach.
971
    @param {Function} [callback] Callback function to be executed once all
972
        specified modules and their dependencies have been attached.
973
    @param {YUI} callback.Y The YUI instance created for this sandbox.
974
    @param {Object} callback.status Object containing `success`, `msg` and
975
        `data` properties.
976
    @chainable
977
    **/
978
    use: function() {
979
        var args = SLICE.call(arguments, 0),
980
            callback = args[args.length - 1],
981
            Y = this,
982
            i = 0,
983
            name,
984
            Env = Y.Env,
985
            provisioned = true;
986
 
987
        // The last argument supplied to use can be a load complete callback
988
        if (Y.Lang.isFunction(callback)) {
989
            args.pop();
990
            if (Y.config.delayUntil) {
991
                callback = Y._delayCallback(callback, Y.config.delayUntil);
992
            }
993
        } else {
994
            callback = null;
995
        }
996
        if (Y.Lang.isArray(args[0])) {
997
            args = args[0];
998
        }
999
 
1000
        if (Y.config.cacheUse) {
1001
            while ((name = args[i++])) {
1002
                if (!Env._attached[name]) {
1003
                    provisioned = false;
1004
                    break;
1005
                }
1006
            }
1007
 
1008
            if (provisioned) {
1009
                if (args.length) {
1010
                }
1011
                Y._notify(callback, ALREADY_DONE, args);
1012
                return Y;
1013
            }
1014
        }
1015
 
1016
        if (Y._loading) {
1017
            Y._useQueue = Y._useQueue || new Y.Queue();
1018
            Y._useQueue.add([args, callback]);
1019
        } else {
1020
            Y._use(args, function(Y, response) {
1021
                Y._notify(callback, response, args);
1022
            });
1023
        }
1024
 
1025
        return Y;
1026
    },
1027
 
1028
    /**
1029
    Sugar for loading both legacy and ES6-based YUI modules.
1030
 
1031
    @method require
1032
    @param {String} [modules*] List of module names to import or a single
1033
        module name.
1034
    @param {Function} callback Callback that gets called once all the modules
1035
        were loaded. Each parameter of the callback is the export value of the
1036
        corresponding module in the list. If the module is a legacy YUI module,
1037
        the YUI instance is used instead of the module exports.
1038
    @example
1039
    ```
1040
    YUI().require(['es6-set'], function (Y, imports) {
1041
        var Set = imports.Set,
1042
            set = new Set();
1043
    });
1044
    ```
1045
    **/
1046
    require: function () {
1047
        var args = SLICE.call(arguments),
1048
            callback;
1049
 
1050
        if (typeof args[args.length - 1] === 'function') {
1051
            callback = args.pop();
1052
 
1053
            // only add the callback if one was provided
1054
            // YUI().require('foo'); is valid
1055
            args.push(function (Y) {
1056
                var i, length = args.length,
1057
                    exported = Y.Env._exported,
1058
                    __imports__ = {};
1059
 
1060
                // Get only the imports requested as arguments
1061
                for (i = 0; i < length; i++) {
1062
                    if (exported.hasOwnProperty(args[i])) {
1063
                        __imports__[args[i]] = exported[args[i]];
1064
                    }
1065
                }
1066
 
1067
                // Using `undefined` because:
1068
                // - Using `Y.config.global` would force the value of `this` to be
1069
                //   the global object even in strict mode
1070
                // - Using `Y` goes against the goal of moving away from a shared
1071
                //   object and start thinking in terms of imported and exported
1072
                //   objects
1073
                callback.call(undefined, Y, __imports__);
1074
            });
1075
        }
1076
        // Do not return the Y object. This makes it hard to follow this
1077
        // traditional pattern:
1078
        //   var Y = YUI().use(...);
1079
        // This is a good idea in the light of ES6 modules, to avoid working
1080
        // in the global scope.
1081
        // This also leaves the door open for returning a promise, once the
1082
        // YUI loader is based on the ES6 loader which uses
1083
        // loader.import(...).then(...)
1084
        this.use.apply(this, args);
1085
    },
1086
 
1087
    /**
1088
    Handles Loader notifications about attachment/load errors.
1089
 
1090
    @method _notify
1091
    @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
1092
    @param {Object} response Response returned from Loader.
1093
    @param {Array} args Arguments passed from Loader.
1094
    @private
1095
    **/
1096
    _notify: function(callback, response, args) {
1097
        if (!response.success && this.config.loadErrorFn) {
1098
            this.config.loadErrorFn.call(this, this, callback, response, args);
1099
        } else if (callback) {
1100
            if (this.Env._missed && this.Env._missed.length) {
1101
                response.msg = 'Missing modules: ' + this.Env._missed.join();
1102
                response.success = false;
1103
            }
1104
            if (this.config.throwFail) {
1105
                callback(this, response);
1106
            } else {
1107
                try {
1108
                    callback(this, response);
1109
                } catch (e) {
1110
                    this.error('use callback error', e, args);
1111
                }
1112
            }
1113
        }
1114
    },
1115
 
1116
    /**
1117
    Called from the `use` method queue to ensure that only one set of loading
1118
    logic is performed at a time.
1119
 
1120
    @method _use
1121
    @param {String} args* One or more modules to attach.
1122
    @param {Function} [callback] Function to call once all required modules have
1123
        been attached.
1124
    @private
1125
    **/
1126
    _use: function(args, callback) {
1127
 
1128
        if (!this.Array) {
1129
            this._attach(['yui-base']);
1130
        }
1131
 
1132
        var len, loader, handleBoot,
1133
            Y = this,
1134
            G_ENV = YUI.Env,
1135
            mods = G_ENV.mods,
1136
            Env = Y.Env,
1137
            used = Env._used,
1138
            aliases = G_ENV.aliases,
1139
            queue = G_ENV._loaderQueue,
1140
            firstArg = args[0],
1141
            YArray = Y.Array,
1142
            config = Y.config,
1143
            boot = config.bootstrap,
1144
            missing = [],
1145
            i,
1146
            r = [],
1147
            ret = true,
1148
            fetchCSS = config.fetchCSS,
1149
            process = function(names, skip) {
1150
 
1151
                var i = 0, a = [], name, len, m, req, use;
1152
 
1153
                if (!names.length) {
1154
                    return;
1155
                }
1156
 
1157
                if (aliases) {
1158
                    len = names.length;
1159
                    for (i = 0; i < len; i++) {
1160
                        if (aliases[names[i]] && !mods[names[i]]) {
1161
                            a = [].concat(a, aliases[names[i]]);
1162
                        } else {
1163
                            a.push(names[i]);
1164
                        }
1165
                    }
1166
                    names = a;
1167
                }
1168
 
1169
                len = names.length;
1170
 
1171
                for (i = 0; i < len; i++) {
1172
                    name = names[i];
1173
                    if (!skip) {
1174
                        r.push(name);
1175
                    }
1176
 
1177
                    // only attach a module once
1178
                    if (used[name]) {
1179
                        continue;
1180
                    }
1181
 
1182
                    m = mods[name];
1183
                    req = null;
1184
                    use = null;
1185
 
1186
                    if (m) {
1187
                        used[name] = true;
1188
                        req = m.details.requires;
1189
                        use = m.details.use;
1190
                    } else {
1191
                        // CSS files don't register themselves, see if it has
1192
                        // been loaded
1193
                        if (!G_ENV._loaded[VERSION][name]) {
1194
                            missing.push(name);
1195
                        } else {
1196
                            used[name] = true; // probably css
1197
                        }
1198
                    }
1199
 
1200
                    // make sure requirements are attached
1201
                    if (req && req.length) {
1202
                        process(req);
1203
                    }
1204
 
1205
                    // make sure we grab the submodule dependencies too
1206
                    if (use && use.length) {
1207
                        process(use, 1);
1208
                    }
1209
                }
1210
 
1211
            },
1212
 
1213
            handleLoader = function(fromLoader) {
1214
                var response = fromLoader || {
1215
                        success: true,
1216
                        msg: 'not dynamic'
1217
                    },
1218
                    redo, origMissing,
1219
                    ret = true,
1220
                    data = response.data;
1221
 
1222
                Y._loading = false;
1223
 
1224
                if (data) {
1225
                    origMissing = missing;
1226
                    missing = [];
1227
                    r = [];
1228
                    process(data);
1229
                    redo = missing.length;
1230
                    if (redo) {
1231
                        if ([].concat(missing).sort().join() ==
1232
                                origMissing.sort().join()) {
1233
                            redo = false;
1234
                        }
1235
                    }
1236
                }
1237
 
1238
                if (redo && data) {
1239
                    Y._loading = true;
1240
                    Y._use(missing, function() {
1241
                        if (Y._attach(data)) {
1242
                            Y._notify(callback, response, data);
1243
                        }
1244
                    });
1245
                } else {
1246
                    if (data) {
1247
                        ret = Y._attach(data);
1248
                    }
1249
                    if (ret) {
1250
                        Y._notify(callback, response, args);
1251
                    }
1252
                }
1253
 
1254
                if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
1255
                    Y._use.apply(Y, Y._useQueue.next());
1256
                }
1257
 
1258
            };
1259
 
1260
 
1261
        // YUI().use('*'); // bind everything available
1262
        if (firstArg === '*') {
1263
            args = [];
1264
            for (i in mods) {
1265
                if (mods.hasOwnProperty(i)) {
1266
                    args.push(i);
1267
                }
1268
            }
1269
            ret = Y._attach(args);
1270
            if (ret) {
1271
                handleLoader();
1272
            }
1273
            return Y;
1274
        }
1275
 
1276
        if ((mods.loader || mods['loader-base']) && !Y.Loader) {
1277
            Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
1278
        }
1279
 
1280
 
1281
        // use loader to expand dependencies and sort the
1282
        // requirements if it is available.
1283
        if (boot && Y.Loader && args.length) {
1284
            loader = getLoader(Y);
1285
            loader.require(args);
1286
            loader.ignoreRegistered = true;
1287
            loader._boot = true;
1288
            loader.calculate(null, (fetchCSS) ? null : 'js');
1289
            args = loader.sorted;
1290
            loader._boot = false;
1291
        }
1292
 
1293
        process(args);
1294
 
1295
        len = missing.length;
1296
 
1297
 
1298
        if (len) {
1299
            missing = YArray.dedupe(missing);
1300
            len = missing.length;
1301
        }
1302
 
1303
 
1304
        // dynamic load
1305
        if (boot && len && Y.Loader) {
1306
            Y._loading = true;
1307
            loader = getLoader(Y);
1308
            loader.onEnd = handleLoader;
1309
            loader.context = Y;
1310
            loader.data = args;
1311
            loader.ignoreRegistered = false;
1312
            loader.require(missing);
1313
            loader.insert(null, (fetchCSS) ? null : 'js');
1314
 
1315
        } else if (boot && len && Y.Get && !Env.bootstrapped) {
1316
 
1317
            Y._loading = true;
1318
 
1319
            handleBoot = function() {
1320
                Y._loading = false;
1321
                queue.running = false;
1322
                Env.bootstrapped = true;
1323
                G_ENV._bootstrapping = false;
1324
                if (Y._attach(['loader'])) {
1325
                    Y._use(args, callback);
1326
                }
1327
            };
1328
 
1329
            if (G_ENV._bootstrapping) {
1330
                queue.add(handleBoot);
1331
            } else {
1332
                G_ENV._bootstrapping = true;
1333
                Y.Get.script(config.base + config.loaderPath, {
1334
                    onEnd: handleBoot
1335
                });
1336
            }
1337
 
1338
        } else {
1339
            ret = Y._attach(args);
1340
            if (ret) {
1341
                handleLoader();
1342
            }
1343
        }
1344
 
1345
        return Y;
1346
    },
1347
 
1348
 
1349
    /**
1350
    Utility method for safely creating namespaces if they don't already exist.
1351
    May be called statically on the YUI global object or as a method on a YUI
1352
    instance.
1353
 
1354
    When called statically, a namespace will be created on the YUI global
1355
    object:
1356
 
1357
        // Create `YUI.your.namespace.here` as nested objects, preserving any
1358
        // objects that already exist instead of overwriting them.
1359
        YUI.namespace('your.namespace.here');
1360
 
1361
    When called as a method on a YUI instance, a namespace will be created on
1362
    that instance:
1363
 
1364
        // Creates `Y.property.package`.
1365
        Y.namespace('property.package');
1366
 
1367
    Dots in the input string cause `namespace` to create nested objects for each
1368
    token. If any part of the requested namespace already exists, the current
1369
    object will be left in place and will not be overwritten. This allows
1370
    multiple calls to `namespace` to preserve existing namespaced properties.
1371
 
1372
    If the first token in the namespace string is "YAHOO", that token is
1373
    discarded. This is legacy behavior for backwards compatibility with YUI 2.
1374
 
1375
    Be careful with namespace tokens. Reserved words may work in some browsers
1376
    and not others. For instance, the following will fail in some browsers
1377
    because the supported version of JavaScript reserves the word "long":
1378
 
1379
        Y.namespace('really.long.nested.namespace');
1380
 
1381
    Note: If you pass multiple arguments to create multiple namespaces, only the
1382
    last one created is returned from this function.
1383
 
1384
    @method namespace
1385
    @param {String} namespace* One or more namespaces to create.
1386
    @return {Object} Reference to the last namespace object created.
1387
    **/
1388
    namespace: function() {
1389
        var a = arguments, o, i = 0, j, d, arg;
1390
 
1391
        for (; i < a.length; i++) {
1392
            o = this; //Reset base object per argument or it will get reused from the last
1393
            arg = a[i];
1394
            if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1395
                d = arg.split(PERIOD);
1396
                for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1397
                    o[d[j]] = o[d[j]] || {};
1398
                    o = o[d[j]];
1399
                }
1400
            } else {
1401
                o[arg] = o[arg] || {};
1402
                o = o[arg]; //Reset base object to the new object so it's returned
1403
            }
1404
        }
1405
        return o;
1406
    },
1407
 
1408
    // this is replaced if the log module is included
1409
    log: NOOP,
1410
    message: NOOP,
1411
    // this is replaced if the dump module is included
1412
    dump: function (o) { return ''+o; },
1413
 
1414
    /**
1415
    Reports an error.
1416
 
1417
    The reporting mechanism is controlled by the `throwFail` configuration
1418
    attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
1419
    truthy, a JS exception is thrown.
1420
 
1421
    If an `errorFn` is specified in the config it must return `true` to indicate
1422
    that the exception was handled and keep it from being thrown.
1423
 
1424
    @method error
1425
    @param {String} msg Error message.
1426
    @param {Error|String} [e] JavaScript error object or an error string.
1427
    @param {String} [src] Source of the error (such as the name of the module in
1428
        which the error occurred).
1429
    @chainable
1430
    **/
1431
    error: function(msg, e, src) {
1432
        //TODO Add check for window.onerror here
1433
 
1434
        var Y = this, ret;
1435
 
1436
        if (Y.config.errorFn) {
1437
            ret = Y.config.errorFn.apply(Y, arguments);
1438
        }
1439
 
1440
        if (!ret) {
1441
            throw (e || new Error(msg));
1442
        } else {
1443
            Y.message(msg, 'error', ''+src); // don't scrub this one
1444
        }
1445
 
1446
        return Y;
1447
    },
1448
 
1449
    /**
1450
    Generates an id string that is unique among all YUI instances in this
1451
    execution context.
1452
 
1453
    @method guid
1454
    @param {String} [pre] Prefix.
1455
    @return {String} Unique id.
1456
    **/
1457
    guid: function(pre) {
1458
        var id = this.Env._guidp + '_' + (++this.Env._uidx);
1459
        return (pre) ? (pre + id) : id;
1460
    },
1461
 
1462
    /**
1463
    Returns a unique id associated with the given object and (if *readOnly* is
1464
    falsy) stamps the object with that id so it can be identified in the future.
1465
 
1466
    Stamping an object involves adding a `_yuid` property to it that contains
1467
    the object's id. One exception to this is that in Internet Explorer, DOM
1468
    nodes have a `uniqueID` property that contains a browser-generated unique
1469
    id, which will be used instead of a YUI-generated id when available.
1470
 
1471
    @method stamp
1472
    @param {Object} o Object to stamp.
1473
    @param {Boolean} readOnly If truthy and the given object has not already
1474
        been stamped, the object will not be modified and `null` will be
1475
        returned.
1476
    @return {String} Object's unique id, or `null` if *readOnly* was truthy and
1477
        the given object was not already stamped.
1478
    **/
1479
    stamp: function(o, readOnly) {
1480
        var uid;
1481
        if (!o) {
1482
            return o;
1483
        }
1484
 
1485
        // IE generates its own unique ID for dom nodes
1486
        // The uniqueID property of a document node returns a new ID
1487
        if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1488
            uid = o.uniqueID;
1489
        } else {
1490
            uid = (typeof o === 'string') ? o : o._yuid;
1491
        }
1492
 
1493
        if (!uid) {
1494
            uid = this.guid();
1495
            if (!readOnly) {
1496
                try {
1497
                    o._yuid = uid;
1498
                } catch (e) {
1499
                    uid = null;
1500
                }
1501
            }
1502
        }
1503
        return uid;
1504
    },
1505
 
1506
    /**
1507
    Destroys this YUI instance.
1508
 
1509
    @method destroy
1510
    @since 3.3.0
1511
    **/
1512
    destroy: function() {
1513
        var Y = this;
1514
        if (Y.Event) {
1515
            Y.Event._unload();
1516
        }
1517
        delete instances[Y.id];
1518
        delete Y.Env;
1519
        delete Y.config;
1520
    }
1521
 
1522
    /**
1523
    Safe `instanceof` wrapper that works around a memory leak in IE when the
1524
    object being tested is `window` or `document`.
1525
 
1526
    Unless you are testing objects that may be `window` or `document`, you
1527
    should use the native `instanceof` operator instead of this method.
1528
 
1529
    @method instanceOf
1530
    @param {Object} o Object to check.
1531
    @param {Object} type Class to check against.
1532
    @since 3.3.0
1533
    **/
1534
};
1535
 
1536
    YUI.prototype = proto;
1537
 
1538
    // inheritance utilities are not available yet
1539
    for (prop in proto) {
1540
        if (proto.hasOwnProperty(prop)) {
1541
            YUI[prop] = proto[prop];
1542
        }
1543
    }
1544
 
1545
    /**
1546
    Applies a configuration to all YUI instances in this execution context.
1547
 
1548
    The main use case for this method is in "mashups" where several third-party
1549
    scripts need to write to a global YUI config, but cannot share a single
1550
    centrally-managed config object. This way they can all call
1551
    `YUI.applyConfig({})` instead of overwriting the single global config.
1552
 
1553
    @example
1554
 
1555
        YUI.applyConfig({
1556
            modules: {
1557
                davglass: {
1558
                    fullpath: './davglass.js'
1559
                }
1560
            }
1561
        });
1562
 
1563
        YUI.applyConfig({
1564
            modules: {
1565
                foo: {
1566
                    fullpath: './foo.js'
1567
                }
1568
            }
1569
        });
1570
 
1571
        YUI().use('davglass', function (Y) {
1572
            // Module davglass will be available here.
1573
        });
1574
 
1575
    @method applyConfig
1576
    @param {Object} o Configuration object to apply.
1577
    @static
1578
    @since 3.5.0
1579
    **/
1580
    YUI.applyConfig = function(o) {
1581
        if (!o) {
1582
            return;
1583
        }
1584
        //If there is a GlobalConfig, apply it first to set the defaults
1585
        if (YUI.GlobalConfig) {
1586
            this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1587
        }
1588
        //Apply this config to it
1589
        this.prototype.applyConfig.call(this, o);
1590
        //Reset GlobalConfig to the combined config
1591
        YUI.GlobalConfig = this.config;
1592
    };
1593
 
1594
    // set up the environment
1595
    YUI._init();
1596
 
1597
    if (hasWin) {
1598
        add(doc, 'DOMContentLoaded', handleReady);
1599
 
1600
        // add a window load event at load time so we can capture
1601
        // the case where it fires before dynamic loading is
1602
        // complete.
1603
        add(window, 'load', handleLoad);
1604
    } else {
1605
        handleReady();
1606
        handleLoad();
1607
    }
1608
 
1609
    YUI.Env.add = add;
1610
    YUI.Env.remove = remove;
1611
 
1612
    /*global exports*/
1613
    // Support the CommonJS method for exporting our single global
1614
    if (typeof exports == 'object') {
1615
        exports.YUI = YUI;
1616
        /**
1617
        * Set a method to be called when `Get.script` is called in Node.js
1618
        * `Get` will open the file, then pass it's content and it's path
1619
        * to this method before attaching it. Commonly used for code coverage
1620
        * instrumentation. <strong>Calling this multiple times will only
1621
        * attach the last hook method</strong>. This method is only
1622
        * available in Node.js.
1623
        * @method setLoadHook
1624
        * @static
1625
        * @param {Function} fn The function to set
1626
        * @param {String} fn.data The content of the file
1627
        * @param {String} fn.path The file path of the file
1628
        */
1629
        YUI.setLoadHook = function(fn) {
1630
            YUI._getLoadHook = fn;
1631
        };
1632
        /**
1633
        * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
1634
        * @method _getLoadHook
1635
        * @private
1636
        * @param {String} data The content of the file
1637
        * @param {String} path The file path of the file
1638
        */
1639
        YUI._getLoadHook = null;
1640
    }
1641
 
1642
    YUI.Env[VERSION] = {};
1643
}());
1644
 
1645
 
1646
/**
1647
Config object that contains all of the configuration options for
1648
this `YUI` instance.
1649
 
1650
This object is supplied by the implementer when instantiating YUI. Some
1651
properties have default values if they are not supplied by the implementer.
1652
 
1653
This object should not be updated directly because some values are cached. Use
1654
`applyConfig()` to update the config object on a YUI instance that has already
1655
been configured.
1656
 
1657
@class config
1658
@static
1659
**/
1660
 
1661
/**
1662
If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
1663
if they're needed to load additional dependencies and aren't already available.
1664
 
1665
Setting this to `false` will prevent YUI from automatically loading the Loader
1666
and module metadata, so you will need to manually ensure that they're available
1667
or handle dependency resolution yourself.
1668
 
1669
@property {Boolean} bootstrap
1670
@default true
1671
**/
1672
 
1673
/**
1674
 
1675
@property {Object} filters
1676
**/
1677
 
1678
/**
1679
If `true`, YUI will use a combo handler to load multiple modules in as few
1680
requests as possible.
1681
 
1682
The YUI CDN (which YUI uses by default) supports combo handling, but other
1683
servers may not. If the server from which you're loading YUI does not support
1684
combo handling, set this to `false`.
1685
 
1686
Providing a value for the `base` config property will cause `combine` to default
1687
to `false` instead of `true`.
1688
 
1689
@property {Boolean} combine
1690
@default true
1691
*/
1692
 
1693
/**
1694
Array of module names that should never be dynamically loaded.
1695
 
1696
@property {String[]} ignore
1697
**/
1698
 
1699
/**
1700
Array of module names that should always be loaded when required, even if
1701
already present on the page.
1702
 
1703
@property {String[]} force
1704
**/
1705
 
1706
/**
1707
DOM element or id that should be used as the insertion point for dynamically
1708
added `<script>` and `<link>` nodes.
1709
 
1710
@property {HTMLElement|String} insertBefore
1711
**/
1712
 
1713
/**
1714
Object hash containing attributes to add to dynamically added `<script>` nodes.
1715
 
1716
@property {Object} jsAttributes
1717
**/
1718
 
1719
/**
1720
Object hash containing attributes to add to dynamically added `<link>` nodes.
1721
 
1722
@property {Object} cssAttributes
1723
**/
1724
 
1725
/**
1726
Timeout in milliseconds before a dynamic JS or CSS request will be considered a
1727
failure. If not set, no timeout will be enforced.
1728
 
1729
@property {Number} timeout
1730
**/
1731
 
1732
/**
1733
A hash of module definitions to add to the list of available YUI modules. These
1734
modules can then be dynamically loaded via the `use()` method.
1735
 
1736
This is a hash in which keys are module names and values are objects containing
1737
module metadata.
1738
 
1739
See `Loader.addModule()` for the supported module metadata fields. Also see
1740
`groups`, which provides a way to configure the base and combo spec for a set of
1741
modules.
1742
 
1743
@example
1744
 
1745
    modules: {
1746
        mymod1: {
1747
            requires: ['node'],
1748
            fullpath: '/mymod1/mymod1.js'
1749
        },
1750
 
1751
        mymod2: {
1752
            requires: ['mymod1'],
1753
            fullpath: '/mymod2/mymod2.js'
1754
        },
1755
 
1756
        mymod3: '/js/mymod3.js',
1757
        mycssmod: '/css/mycssmod.css'
1758
    }
1759
 
1760
@property {Object} modules
1761
**/
1762
 
1763
/**
1764
Aliases are dynamic groups of modules that can be used as shortcuts.
1765
 
1766
@example
1767
 
1768
    YUI({
1769
        aliases: {
1770
            davglass: [ 'node', 'yql', 'dd' ],
1771
            mine: [ 'davglass', 'autocomplete']
1772
        }
1773
    }).use('mine', function (Y) {
1774
        // Node, YQL, DD & AutoComplete available here.
1775
    });
1776
 
1777
@property {Object} aliases
1778
**/
1779
 
1780
/**
1781
A hash of module group definitions.
1782
 
1783
For each group you can specify a list of modules and the base path and
1784
combo spec to use when dynamically loading the modules.
1785
 
1786
@example
1787
 
1788
    groups: {
1789
        yui2: {
1790
            // specify whether or not this group has a combo service
1791
            combine: true,
1792
 
1793
            // The comboSeperator to use with this group's combo handler
1794
            comboSep: ';',
1795
 
1796
            // The maxURLLength for this server
1797
            maxURLLength: 500,
1798
 
1799
            // the base path for non-combo paths
1800
            base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1801
 
1802
            // the path to the combo service
1803
            comboBase: 'http://yui.yahooapis.com/combo?',
1804
 
1805
            // a fragment to prepend to the path attribute when
1806
            // when building combo urls
1807
            root: '2.8.0r4/build/',
1808
 
1809
            // the module definitions
1810
            modules:  {
1811
                yui2_yde: {
1812
                    path: "yahoo-dom-event/yahoo-dom-event.js"
1813
                },
1814
                yui2_anim: {
1815
                    path: "animation/animation.js",
1816
                    requires: ['yui2_yde']
1817
                }
1818
            }
1819
        }
1820
    }
1821
 
1822
@property {Object} groups
1823
**/
1824
 
1825
/**
1826
Path to the Loader JS file, relative to the `base` path.
1827
 
1828
This is used to dynamically bootstrap the Loader when it's needed and isn't yet
1829
available.
1830
 
1831
@property {String} loaderPath
1832
@default "loader/loader-min.js"
1833
**/
1834
 
1835
/**
1836
If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
1837
`false` to prevent YUI from loading any CSS, or set it to the string `"force"`
1838
to force CSS dependencies to be loaded even if their associated JS modules are
1839
already loaded.
1840
 
1841
@property {Boolean|String} fetchCSS
1842
@default true
1843
**/
1844
 
1845
/**
1846
Default gallery version used to build gallery module urls.
1847
 
1848
@property {String} gallery
1849
@since 3.1.0
1850
**/
1851
 
1852
/**
1853
Default YUI 2 version used to build YUI 2 module urls.
1854
 
1855
This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
1856
`2in3` config for pulling different revisions of the wrapped YUI 2 modules.
1857
 
1858
@property {String} yui2
1859
@default "2.9.0"
1860
@since 3.1.0
1861
**/
1862
 
1863
/**
1864
Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
1865
 
1866
@property {String} 2in3
1867
@default "4"
1868
@since 3.1.0
1869
**/
1870
 
1871
/**
1872
Alternate console log function that should be used in environments without a
1873
supported native console. This function is executed with the YUI instance as its
1874
`this` object.
1875
 
1876
@property {Function} logFn
1877
@since 3.1.0
1878
**/
1879
 
1880
/**
1881
The minimum log level to log messages for. Log levels are defined
1882
incrementally. Messages greater than or equal to the level specified will
1883
be shown. All others will be discarded. The order of log levels in
1884
increasing priority is:
1885
 
1886
    debug
1887
    info
1888
    warn
1889
    error
1890
 
1891
@property {String} logLevel
1892
@default 'debug'
1893
@since 3.10.0
1894
**/
1895
 
1896
/**
1897
Callback to execute when `Y.error()` is called. It receives the error message
1898
and a JavaScript error object if one was provided.
1899
 
1900
This function is executed with the YUI instance as its `this` object.
1901
 
1902
Returning `true` from this function will prevent an exception from being thrown.
1903
 
1904
@property {Function} errorFn
1905
@param {String} errorFn.msg Error message
1906
@param {Object} [errorFn.err] Error object (if one was provided).
1907
@since 3.2.0
1908
**/
1909
 
1910
/**
1911
A callback to execute when Loader fails to load one or more resources.
1912
 
1913
This could be because of a script load failure. It could also be because a
1914
module fails to register itself when the `requireRegistration` config is `true`.
1915
 
1916
If this function is defined, the `use()` callback will only be called when the
1917
loader succeeds. Otherwise, `use()` will always executes unless there was a
1918
JavaScript error when attaching a module.
1919
 
1920
@property {Function} loadErrorFn
1921
@since 3.3.0
1922
**/
1923
 
1924
/**
1925
If `true`, Loader will expect all loaded scripts to be first-class YUI modules
1926
that register themselves with the YUI global, and will trigger a failure if a
1927
loaded script does not register a YUI module.
1928
 
1929
@property {Boolean} requireRegistration
1930
@default false
1931
@since 3.3.0
1932
**/
1933
 
1934
/**
1935
Cache serviced use() requests.
1936
 
1937
@property {Boolean} cacheUse
1938
@default true
1939
@since 3.3.0
1940
@deprecated No longer used.
1941
**/
1942
 
1943
/**
1944
Whether or not YUI should use native ES5 functionality when available for
1945
features like `Y.Array.each()`, `Y.Object()`, etc.
1946
 
1947
When `false`, YUI will always use its own fallback implementations instead of
1948
relying on ES5 functionality, even when ES5 functionality is available.
1949
 
1950
@property {Boolean} useNativeES5
1951
@default true
1952
@since 3.5.0
1953
**/
1954
 
1955
/**
1956
 * Leverage native JSON stringify if the browser has a native
1957
 * implementation.  In general, this is a good idea.  See the Known Issues
1958
 * section in the JSON user guide for caveats.  The default value is true
1959
 * for browsers with native JSON support.
1960
 *
1961
 * @property useNativeJSONStringify
1962
 * @type Boolean
1963
 * @default true
1964
 * @since 3.8.0
1965
 */
1966
 
1967
 /**
1968
 * Leverage native JSON parse if the browser has a native implementation.
1969
 * In general, this is a good idea.  See the Known Issues section in the
1970
 * JSON user guide for caveats.  The default value is true for browsers with
1971
 * native JSON support.
1972
 *
1973
 * @property useNativeJSONParse
1974
 * @type Boolean
1975
 * @default true
1976
 * @since 3.8.0
1977
 */
1978
 
1979
/**
1980
Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
1981
 
1982
@property {Object|String} delayUntil
1983
@since 3.6.0
1984
@example
1985
 
1986
You can use `load` or `domready` strings by default:
1987
 
1988
    YUI({
1989
        delayUntil: 'domready'
1990
    }, function (Y) {
1991
        // This will not execute until 'domeready' occurs.
1992
    });
1993
 
1994
Or you can delay until a node is available (with `available` or `contentready`):
1995
 
1996
    YUI({
1997
        delayUntil: {
1998
            event: 'available',
1999
            args : '#foo'
2000
        }
2001
    }, function (Y) {
2002
        // This will not execute until a node matching the selector "#foo" is
2003
        // available in the DOM.
2004
    });
2005
 
2006
**/
2007
YUI.add('yui-base', function (Y, NAME) {
2008
 
2009
/*
2010
 * YUI stub
2011
 * @module yui
2012
 * @submodule yui-base
2013
 */
2014
/**
2015
 * The YUI module contains the components required for building the YUI
2016
 * seed file.  This includes the script loading mechanism, a simple queue,
2017
 * and the core utilities for the library.
2018
 * @module yui
2019
 * @submodule yui-base
2020
 */
2021
 
2022
/**
2023
 * Provides core language utilites and extensions used throughout YUI.
2024
 *
2025
 * @class Lang
2026
 * @static
2027
 */
2028
 
2029
var L = Y.Lang || (Y.Lang = {}),
2030
 
2031
STRING_PROTO = String.prototype,
2032
TOSTRING     = Object.prototype.toString,
2033
 
2034
TYPES = {
2035
    'undefined'        : 'undefined',
2036
    'number'           : 'number',
2037
    'boolean'          : 'boolean',
2038
    'string'           : 'string',
2039
    '[object Function]': 'function',
2040
    '[object RegExp]'  : 'regexp',
2041
    '[object Array]'   : 'array',
2042
    '[object Date]'    : 'date',
2043
    '[object Error]'   : 'error'
2044
},
2045
 
2046
SUBREGEX         = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
2047
 
2048
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",
2049
WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+",
2050
TRIM_LEFT_REGEX  = new RegExp("^" + WHITESPACE_CLASS),
2051
TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"),
2052
TRIMREGEX        = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"),
2053
 
2054
NATIVE_FN_REGEX  = /\{\s*\[(?:native code|function)\]\s*\}/i;
2055
 
2056
// -- Protected Methods --------------------------------------------------------
2057
 
2058
/**
2059
Returns `true` if the given function appears to be implemented in native code,
2060
`false` otherwise. Will always return `false` -- even in ES5-capable browsers --
2061
if the `useNativeES5` YUI config option is set to `false`.
2062
 
2063
This isn't guaranteed to be 100% accurate and won't work for anything other than
2064
functions, but it can be useful for determining whether a function like
2065
`Array.prototype.forEach` is native or a JS shim provided by another library.
2066
 
2067
There's a great article by @kangax discussing certain flaws with this technique:
2068
<http://perfectionkills.com/detecting-built-in-host-methods/>
2069
 
2070
While his points are valid, it's still possible to benefit from this function
2071
as long as it's used carefully and sparingly, and in such a way that false
2072
negatives have minimal consequences. It's used internally to avoid using
2073
potentially broken non-native ES5 shims that have been added to the page by
2074
other libraries.
2075
 
2076
@method _isNative
2077
@param {Function} fn Function to test.
2078
@return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
2079
@static
2080
@protected
2081
@since 3.5.0
2082
**/
2083
L._isNative = function (fn) {
2084
    return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
2085
};
2086
 
2087
// -- Public Methods -----------------------------------------------------------
2088
 
2089
/**
2090
 * Determines whether or not the provided item is an array.
2091
 *
2092
 * Returns `false` for array-like collections such as the function `arguments`
2093
 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
2094
 * test for an array-like collection.
2095
 *
2096
 * @method isArray
2097
 * @param o The object to test.
2098
 * @return {boolean} true if o is an array.
2099
 * @static
2100
 */
2101
L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
2102
    return L.type(o) === 'array';
2103
};
2104
 
2105
/**
2106
 * Determines whether or not the provided item is a boolean.
2107
 * @method isBoolean
2108
 * @static
2109
 * @param o The object to test.
2110
 * @return {boolean} true if o is a boolean.
2111
 */
2112
L.isBoolean = function(o) {
2113
    return typeof o === 'boolean';
2114
};
2115
 
2116
/**
2117
 * Determines whether or not the supplied item is a date instance.
2118
 * @method isDate
2119
 * @static
2120
 * @param o The object to test.
2121
 * @return {boolean} true if o is a date.
2122
 */
2123
L.isDate = function(o) {
2124
    return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
2125
};
2126
 
2127
/**
2128
 * <p>
2129
 * Determines whether or not the provided item is a function.
2130
 * Note: Internet Explorer thinks certain functions are objects:
2131
 * </p>
2132
 *
2133
 * <pre>
2134
 * var obj = document.createElement("object");
2135
 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
2136
 * &nbsp;
2137
 * var input = document.createElement("input"); // append to body
2138
 * Y.Lang.isFunction(input.focus) // reports false in IE
2139
 * </pre>
2140
 *
2141
 * <p>
2142
 * You will have to implement additional tests if these functions
2143
 * matter to you.
2144
 * </p>
2145
 *
2146
 * @method isFunction
2147
 * @static
2148
 * @param o The object to test.
2149
 * @return {boolean} true if o is a function.
2150
 */
2151
L.isFunction = function(o) {
2152
    return L.type(o) === 'function';
2153
};
2154
 
2155
/**
2156
 * Determines whether or not the provided item is null.
2157
 * @method isNull
2158
 * @static
2159
 * @param o The object to test.
2160
 * @return {boolean} true if o is null.
2161
 */
2162
L.isNull = function(o) {
2163
    return o === null;
2164
};
2165
 
2166
/**
2167
 * Determines whether or not the provided item is a legal number.
2168
 * @method isNumber
2169
 * @static
2170
 * @param o The object to test.
2171
 * @return {boolean} true if o is a number.
2172
 */
2173
L.isNumber = function(o) {
2174
    return typeof o === 'number' && isFinite(o);
2175
};
2176
 
2177
/**
2178
 * Determines whether or not the provided item is of type object
2179
 * or function. Note that arrays are also objects, so
2180
 * <code>Y.Lang.isObject([]) === true</code>.
2181
 * @method isObject
2182
 * @static
2183
 * @param o The object to test.
2184
 * @param failfn {boolean} fail if the input is a function.
2185
 * @return {boolean} true if o is an object.
2186
 * @see isPlainObject
2187
 */
2188
L.isObject = function(o, failfn) {
2189
    var t = typeof o;
2190
    return (o && (t === 'object' ||
2191
        (!failfn && (t === 'function' || L.isFunction(o))))) || false;
2192
};
2193
 
2194
/**
2195
 * Determines whether or not the provided value is a regexp.
2196
 * @method isRegExp
2197
 * @static
2198
 * @param value The value or object to test.
2199
 * @return {boolean} true if value is a regexp.
2200
 */
2201
L.isRegExp = function(value) {
2202
    return L.type(value) === 'regexp';
2203
};
2204
 
2205
/**
2206
 * Determines whether or not the provided item is a string.
2207
 * @method isString
2208
 * @static
2209
 * @param o The object to test.
2210
 * @return {boolean} true if o is a string.
2211
 */
2212
L.isString = function(o) {
2213
    return typeof o === 'string';
2214
};
2215
 
2216
/**
2217
 * Determines whether or not the provided item is undefined.
2218
 * @method isUndefined
2219
 * @static
2220
 * @param o The object to test.
2221
 * @return {boolean} true if o is undefined.
2222
 */
2223
L.isUndefined = function(o) {
2224
    return typeof o === 'undefined';
2225
};
2226
 
2227
/**
2228
 * A convenience method for detecting a legitimate non-null value.
2229
 * Returns false for null/undefined/NaN, true for other values,
2230
 * including 0/false/''
2231
 * @method isValue
2232
 * @static
2233
 * @param o The item to test.
2234
 * @return {boolean} true if it is not null/undefined/NaN || false.
2235
 */
2236
L.isValue = function(o) {
2237
    var t = L.type(o);
2238
 
2239
    switch (t) {
2240
        case 'number':
2241
            return isFinite(o);
2242
 
2243
        case 'null': // fallthru
2244
        case 'undefined':
2245
            return false;
2246
 
2247
        default:
2248
            return !!t;
2249
    }
2250
};
2251
 
2252
/**
2253
 * Returns the current time in milliseconds.
2254
 *
2255
 * @method now
2256
 * @return {Number} Current time in milliseconds.
2257
 * @static
2258
 * @since 3.3.0
2259
 */
2260
L.now = Date.now || function () {
2261
    return new Date().getTime();
2262
};
2263
 
2264
/**
2265
 * Performs `{placeholder}` substitution on a string. The object passed as the
2266
 * second parameter provides values to replace the `{placeholder}`s.
2267
 * `{placeholder}` token names must match property names of the object. For example,
2268
 *
2269
 *`var greeting = Y.Lang.sub("Hello, {who}!", { who: "World" });`
2270
 *
2271
 * `{placeholder}` tokens that are undefined on the object map will be left
2272
 * in tact (leaving unsightly `{placeholder}`'s in the output string).
2273
 *
2274
 * @method sub
2275
 * @param {string} s String to be modified.
2276
 * @param {object} o Object containing replacement values.
2277
 * @return {string} the substitute result.
2278
 * @static
2279
 * @since 3.2.0
2280
 */
2281
L.sub = function(s, o) {
2282
 
2283
    /**
2284
    Finds the value of `key` in given object.
2285
    If the key has a 'dot' notation e.g. 'foo.bar.baz', the function will
2286
    try to resolve this path if it doesn't exist as a property
2287
    @example
2288
        value({ 'a.b': 1, a: { b: 2 } }, 'a.b'); // 1
2289
        value({ a: { b: 2 } }          , 'a.b'); // 2
2290
    @param {Object} obj A key/value pairs object
2291
    @param {String} key
2292
    @return {Any}
2293
    @private
2294
    **/
2295
    function value(obj, key) {
2296
 
2297
        var subkey;
2298
 
2299
        if ( typeof obj[key] !== 'undefined' ) {
2300
            return obj[key];
2301
        }
2302
 
2303
        key    = key.split('.');         // given 'a.b.c'
2304
        subkey = key.slice(1).join('.'); // 'b.c'
2305
        key    = key[0];                 // 'a'
2306
 
2307
        // special case for null as typeof returns object and we don't want that.
2308
        if ( subkey && typeof obj[key] === 'object' && obj[key] !== null ) {
2309
            return value(obj[key], subkey);
2310
        }
2311
    }
2312
 
2313
    return s.replace ? s.replace(SUBREGEX, function (match, key) {
2314
        var val = key.indexOf('.')>-1 ? value(o, key) : o[key];
2315
        return typeof val === 'undefined' ? match : val;
2316
    }) : s;
2317
};
2318
 
2319
/**
2320
 * Returns a string without any leading or trailing whitespace.  If
2321
 * the input is not a string, the input will be returned untouched.
2322
 * @method trim
2323
 * @static
2324
 * @param s {string} the string to trim.
2325
 * @return {string} the trimmed string.
2326
 */
2327
L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) {
2328
    return s && s.trim ? s.trim() : s;
2329
} : function (s) {
2330
    try {
2331
        return s.replace(TRIMREGEX, '');
2332
    } catch (e) {
2333
        return s;
2334
    }
2335
};
2336
 
2337
/**
2338
 * Returns a string without any leading whitespace.
2339
 * @method trimLeft
2340
 * @static
2341
 * @param s {string} the string to trim.
2342
 * @return {string} the trimmed string.
2343
 */
2344
L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) {
2345
    return s.trimLeft();
2346
} : function (s) {
2347
    return s.replace(TRIM_LEFT_REGEX, '');
2348
};
2349
 
2350
/**
2351
 * Returns a string without any trailing whitespace.
2352
 * @method trimRight
2353
 * @static
2354
 * @param s {string} the string to trim.
2355
 * @return {string} the trimmed string.
2356
 */
2357
L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) {
2358
    return s.trimRight();
2359
} : function (s) {
2360
    return s.replace(TRIM_RIGHT_REGEX, '');
2361
};
2362
 
2363
/**
2364
Returns one of the following strings, representing the type of the item passed
2365
in:
2366
 
2367
 * "array"
2368
 * "boolean"
2369
 * "date"
2370
 * "error"
2371
 * "function"
2372
 * "null"
2373
 * "number"
2374
 * "object"
2375
 * "regexp"
2376
 * "string"
2377
 * "undefined"
2378
 
2379
Known issues:
2380
 
2381
 * `typeof HTMLElementCollection` returns function in Safari, but
2382
    `Y.Lang.type()` reports "object", which could be a good thing --
2383
    but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2384
 
2385
@method type
2386
@param o the item to test.
2387
@return {string} the detected type.
2388
@static
2389
**/
2390
L.type = function(o) {
2391
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2392
};
2393
/**
2394
@module yui
2395
@submodule yui-base
2396
*/
2397
 
2398
var Lang   = Y.Lang,
2399
    Native = Array.prototype,
2400
 
2401
    hasOwn = Object.prototype.hasOwnProperty;
2402
 
2403
/**
2404
Provides utility methods for working with arrays. Additional array helpers can
2405
be found in the `collection` and `array-extras` modules.
2406
 
2407
`Y.Array(thing)` returns a native array created from _thing_. Depending on
2408
_thing_'s type, one of the following will happen:
2409
 
2410
  * Arrays are returned unmodified unless a non-zero _startIndex_ is
2411
    specified.
2412
  * Array-like collections (see `Array.test()`) are converted to arrays.
2413
  * For everything else, a new array is created with _thing_ as the sole
2414
    item.
2415
 
2416
Note: elements that are also collections, such as `<form>` and `<select>`
2417
elements, are not automatically converted to arrays. To force a conversion,
2418
pass `true` as the value of the _force_ parameter.
2419
 
2420
@class Array
2421
@constructor
2422
@param {Any} thing The thing to arrayify.
2423
@param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2424
  collection, a subset of items starting at the specified index will be
2425
  returned.
2426
@param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2427
  array-like collection no matter what.
2428
@return {Array} A native array created from _thing_, according to the rules
2429
  described above.
2430
**/
2431
function YArray(thing, startIndex, force) {
2432
    var len, result;
2433
 
2434
    /*jshint expr: true*/
2435
    startIndex || (startIndex = 0);
2436
 
2437
    if (force || YArray.test(thing)) {
2438
        // IE throws when trying to slice HTMLElement collections.
2439
        try {
2440
            return Native.slice.call(thing, startIndex);
2441
        } catch (ex) {
2442
            result = [];
2443
 
2444
            for (len = thing.length; startIndex < len; ++startIndex) {
2445
                result.push(thing[startIndex]);
2446
            }
2447
 
2448
            return result;
2449
        }
2450
    }
2451
 
2452
    return [thing];
2453
}
2454
 
2455
Y.Array = YArray;
2456
 
2457
/**
2458
Dedupes an array of strings, returning an array that's guaranteed to contain
2459
only one copy of a given string.
2460
 
2461
This method differs from `Array.unique()` in that it's optimized for use only
2462
with arrays consisting entirely of strings or entirely of numbers, whereas
2463
`unique` may be used with other value types (but is slower).
2464
 
2465
Using `dedupe()` with values other than strings or numbers, or with arrays
2466
containing a mix of strings and numbers, may result in unexpected behavior.
2467
 
2468
@method dedupe
2469
@param {String[]|Number[]} array Array of strings or numbers to dedupe.
2470
@return {Array} Copy of _array_ containing no duplicate values.
2471
@static
2472
@since 3.4.0
2473
**/
2474
YArray.dedupe = Lang._isNative(Object.create) ? function (array) {
2475
    var hash    = Object.create(null),
2476
        results = [],
2477
        i, item, len;
2478
 
2479
    for (i = 0, len = array.length; i < len; ++i) {
2480
        item = array[i];
2481
 
2482
        if (!hash[item]) {
2483
            hash[item] = 1;
2484
            results.push(item);
2485
        }
2486
    }
2487
 
2488
    return results;
2489
} : function (array) {
2490
    var hash    = {},
2491
        results = [],
2492
        i, item, len;
2493
 
2494
    for (i = 0, len = array.length; i < len; ++i) {
2495
        item = array[i];
2496
 
2497
        if (!hasOwn.call(hash, item)) {
2498
            hash[item] = 1;
2499
            results.push(item);
2500
        }
2501
    }
2502
 
2503
    return results;
2504
};
2505
 
2506
/**
2507
Executes the supplied function on each item in the array. This method wraps
2508
the native ES5 `Array.forEach()` method if available.
2509
 
2510
@method each
2511
@param {Array} array Array to iterate.
2512
@param {Function} fn Function to execute on each item in the array. The function
2513
  will receive the following arguments:
2514
    @param {Any} fn.item Current array item.
2515
    @param {Number} fn.index Current array index.
2516
    @param {Array} fn.array Array being iterated.
2517
@param {Object} [thisObj] `this` object to use when calling _fn_.
2518
@return {YUI} The YUI instance.
2519
@static
2520
**/
2521
YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2522
    Native.forEach.call(array || [], fn, thisObj || Y);
2523
    return Y;
2524
} : function (array, fn, thisObj) {
2525
    for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2526
        if (i in array) {
2527
            fn.call(thisObj || Y, array[i], i, array);
2528
        }
2529
    }
2530
 
2531
    return Y;
2532
};
2533
 
2534
/**
2535
Alias for `each()`.
2536
 
2537
@method forEach
2538
@static
2539
**/
2540
 
2541
/**
2542
Returns an object using the first array as keys and the second as values. If
2543
the second array is not provided, or if it doesn't contain the same number of
2544
values as the first array, then `true` will be used in place of the missing
2545
values.
2546
 
2547
@example
2548
 
2549
    Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2550
    // => {a: 'foo', b: 'bar', c: true}
2551
 
2552
@method hash
2553
@param {String[]} keys Array of strings to use as keys.
2554
@param {Array} [values] Array to use as values.
2555
@return {Object} Hash using the first array as keys and the second as values.
2556
@static
2557
**/
2558
YArray.hash = function (keys, values) {
2559
    var hash = {},
2560
        vlen = (values && values.length) || 0,
2561
        i, len;
2562
 
2563
    for (i = 0, len = keys.length; i < len; ++i) {
2564
        if (i in keys) {
2565
            hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2566
        }
2567
    }
2568
 
2569
    return hash;
2570
};
2571
 
2572
/**
2573
Returns the index of the first item in the array that's equal (using a strict
2574
equality check) to the specified _value_, or `-1` if the value isn't found.
2575
 
2576
This method wraps the native ES5 `Array.indexOf()` method if available.
2577
 
2578
@method indexOf
2579
@param {Array} array Array to search.
2580
@param {Any} value Value to search for.
2581
@param {Number} [from=0] The index at which to begin the search.
2582
@return {Number} Index of the item strictly equal to _value_, or `-1` if not
2583
    found.
2584
@static
2585
**/
2586
YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2587
    return Native.indexOf.call(array, value, from);
2588
} : function (array, value, from) {
2589
    // http://es5.github.com/#x15.4.4.14
2590
    var len = array.length;
2591
 
2592
    from = +from || 0;
2593
    from = (from > 0 || -1) * Math.floor(Math.abs(from));
2594
 
2595
    if (from < 0) {
2596
        from += len;
2597
 
2598
        if (from < 0) {
2599
            from = 0;
2600
        }
2601
    }
2602
 
2603
    for (; from < len; ++from) {
2604
        if (from in array && array[from] === value) {
2605
            return from;
2606
        }
2607
    }
2608
 
2609
    return -1;
2610
};
2611
 
2612
/**
2613
Numeric sort convenience function.
2614
 
2615
The native `Array.prototype.sort()` function converts values to strings and
2616
sorts them in lexicographic order, which is unsuitable for sorting numeric
2617
values. Provide `Array.numericSort` as a custom sort function when you want
2618
to sort values in numeric order.
2619
 
2620
@example
2621
 
2622
    [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2623
    // => [4, 8, 15, 16, 23, 42]
2624
 
2625
@method numericSort
2626
@param {Number} a First value to compare.
2627
@param {Number} b Second value to compare.
2628
@return {Number} Difference between _a_ and _b_.
2629
@static
2630
**/
2631
YArray.numericSort = function (a, b) {
2632
    return a - b;
2633
};
2634
 
2635
/**
2636
Executes the supplied function on each item in the array. Returning a truthy
2637
value from the function will stop the processing of remaining items.
2638
 
2639
@method some
2640
@param {Array} array Array to iterate over.
2641
@param {Function} fn Function to execute on each item. The function will receive
2642
  the following arguments:
2643
    @param {Any} fn.value Current array item.
2644
    @param {Number} fn.index Current array index.
2645
    @param {Array} fn.array Array being iterated over.
2646
@param {Object} [thisObj] `this` object to use when calling _fn_.
2647
@return {Boolean} `true` if the function returns a truthy value on any of the
2648
  items in the array; `false` otherwise.
2649
@static
2650
**/
2651
YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2652
    return Native.some.call(array, fn, thisObj);
2653
} : function (array, fn, thisObj) {
2654
    for (var i = 0, len = array.length; i < len; ++i) {
2655
        if (i in array && fn.call(thisObj, array[i], i, array)) {
2656
            return true;
2657
        }
2658
    }
2659
 
2660
    return false;
2661
};
2662
 
2663
/**
2664
Evaluates _obj_ to determine if it's an array, an array-like collection, or
2665
something else. This is useful when working with the function `arguments`
2666
collection and `HTMLElement` collections.
2667
 
2668
Note: This implementation doesn't consider elements that are also
2669
collections, such as `<form>` and `<select>`, to be array-like.
2670
 
2671
@method test
2672
@param {Object} obj Object to test.
2673
@return {Number} A number indicating the results of the test:
2674
 
2675
  * 0: Neither an array nor an array-like collection.
2676
  * 1: Real array.
2677
  * 2: Array-like collection.
2678
 
2679
@static
2680
**/
2681
YArray.test = function (obj) {
2682
    var result = 0;
2683
 
2684
    if (Lang.isArray(obj)) {
2685
        result = 1;
2686
    } else if (Lang.isObject(obj)) {
2687
        try {
2688
            // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
2689
            // or functions without apply/call (Safari
2690
            // HTMLElementCollection bug).
2691
            if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
2692
                result = 2;
2693
            }
2694
        } catch (ex) {}
2695
    }
2696
 
2697
    return result;
2698
};
2699
/**
2700
 * The YUI module contains the components required for building the YUI
2701
 * seed file.  This includes the script loading mechanism, a simple queue,
2702
 * and the core utilities for the library.
2703
 * @module yui
2704
 * @submodule yui-base
2705
 */
2706
 
2707
/**
2708
 * A simple FIFO queue.  Items are added to the Queue with add(1..n items) and
2709
 * removed using next().
2710
 *
2711
 * @class Queue
2712
 * @constructor
2713
 * @param {MIXED} item* 0..n items to seed the queue.
2714
 */
2715
function Queue() {
2716
    this._init();
2717
    this.add.apply(this, arguments);
2718
}
2719
 
2720
Queue.prototype = {
2721
    /**
2722
     * Initialize the queue
2723
     *
2724
     * @method _init
2725
     * @protected
2726
     */
2727
    _init: function() {
2728
        /**
2729
         * The collection of enqueued items
2730
         *
2731
         * @property _q
2732
         * @type Array
2733
         * @protected
2734
         */
2735
        this._q = [];
2736
    },
2737
 
2738
    /**
2739
     * Get the next item in the queue. FIFO support
2740
     *
2741
     * @method next
2742
     * @return {MIXED} the next item in the queue.
2743
     */
2744
    next: function() {
2745
        return this._q.shift();
2746
    },
2747
 
2748
    /**
2749
     * Get the last in the queue. LIFO support.
2750
     *
2751
     * @method last
2752
     * @return {MIXED} the last item in the queue.
2753
     */
2754
    last: function() {
2755
        return this._q.pop();
2756
    },
2757
 
2758
    /**
2759
     * Add 0..n items to the end of the queue.
2760
     *
2761
     * @method add
2762
     * @param {MIXED} item* 0..n items.
2763
     * @return {object} this queue.
2764
     */
2765
    add: function() {
2766
        this._q.push.apply(this._q, arguments);
2767
 
2768
        return this;
2769
    },
2770
 
2771
    /**
2772
     * Returns the current number of queued items.
2773
     *
2774
     * @method size
2775
     * @return {Number} The size.
2776
     */
2777
    size: function() {
2778
        return this._q.length;
2779
    }
2780
};
2781
 
2782
Y.Queue = Queue;
2783
 
2784
YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2785
 
2786
/**
2787
The YUI module contains the components required for building the YUI seed file.
2788
This includes the script loading mechanism, a simple queue, and the core
2789
utilities for the library.
2790
 
2791
@module yui
2792
@submodule yui-base
2793
**/
2794
 
2795
var CACHED_DELIMITER = '__',
2796
 
2797
    hasOwn   = Object.prototype.hasOwnProperty,
2798
    isObject = Y.Lang.isObject;
2799
 
2800
/**
2801
Returns a wrapper for a function which caches the return value of that function,
2802
keyed off of the combined string representation of the argument values provided
2803
when the wrapper is called.
2804
 
2805
Calling this function again with the same arguments will return the cached value
2806
rather than executing the wrapped function.
2807
 
2808
Note that since the cache is keyed off of the string representation of arguments
2809
passed to the wrapper function, arguments that aren't strings and don't provide
2810
a meaningful `toString()` method may result in unexpected caching behavior. For
2811
example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2812
string `[object Object]` when used as a cache key.
2813
 
2814
@method cached
2815
@param {Function} source The function to memoize.
2816
@param {Object} [cache={}] Object in which to store cached values. You may seed
2817
  this object with pre-existing cached values if desired.
2818
@param {any} [refetch] If supplied, this value is compared with the cached value
2819
  using a `==` comparison. If the values are equal, the wrapped function is
2820
  executed again even though a cached value exists.
2821
@return {Function} Wrapped function.
2822
@for YUI
2823
**/
2824
Y.cached = function (source, cache, refetch) {
2825
    /*jshint expr: true*/
2826
    cache || (cache = {});
2827
 
2828
    return function (arg) {
2829
        var key = arguments.length > 1 ?
2830
                Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2831
                String(arg);
2832
 
2833
        /*jshint eqeqeq: false*/
2834
        if (!(key in cache) || (refetch && cache[key] == refetch)) {
2835
            cache[key] = source.apply(source, arguments);
2836
        }
2837
 
2838
        return cache[key];
2839
    };
2840
};
2841
 
2842
/**
2843
Returns the `location` object from the window/frame in which this YUI instance
2844
operates, or `undefined` when executing in a non-browser environment
2845
(e.g. Node.js).
2846
 
2847
It is _not_ recommended to hold references to the `window.location` object
2848
outside of the scope of a function in which its properties are being accessed or
2849
its methods are being called. This is because of a nasty bug/issue that exists
2850
in both Safari and MobileSafari browsers:
2851
[WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
2852
 
2853
@method getLocation
2854
@return {location} The `location` object from the window/frame in which this YUI
2855
    instance operates.
2856
@since 3.5.0
2857
**/
2858
Y.getLocation = function () {
2859
    // It is safer to look this up every time because yui-base is attached to a
2860
    // YUI instance before a user's config is applied; i.e. `Y.config.win` does
2861
    // not point the correct window object when this file is loaded.
2862
    var win = Y.config.win;
2863
 
2864
    // It is not safe to hold a reference to the `location` object outside the
2865
    // scope in which it is being used. The WebKit engine used in Safari and
2866
    // MobileSafari will "disconnect" the `location` object from the `window`
2867
    // when a page is restored from back/forward history cache.
2868
    return win && win.location;
2869
};
2870
 
2871
/**
2872
Returns a new object containing all of the properties of all the supplied
2873
objects. The properties from later objects will overwrite those in earlier
2874
objects.
2875
 
2876
Passing in a single object will create a shallow copy of it. For a deep copy,
2877
use `clone()`.
2878
 
2879
@method merge
2880
@param {Object} objects* One or more objects to merge.
2881
@return {Object} A new merged object.
2882
**/
2883
Y.merge = function () {
2884
    var i      = 0,
2885
        len    = arguments.length,
2886
        result = {},
2887
        key,
2888
        obj;
2889
 
2890
    for (; i < len; ++i) {
2891
        obj = arguments[i];
2892
 
2893
        for (key in obj) {
2894
            if (hasOwn.call(obj, key)) {
2895
                result[key] = obj[key];
2896
            }
2897
        }
2898
    }
2899
 
2900
    return result;
2901
};
2902
 
2903
/**
2904
Mixes _supplier_'s properties into _receiver_.
2905
 
2906
Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
2907
shadowed unless the _overwrite_ parameter is `true`, and will not be merged
2908
unless the _merge_ parameter is `true`.
2909
 
2910
In the default mode (0), only properties the supplier owns are copied (prototype
2911
properties are not copied). The following copying modes are available:
2912
 
2913
  * `0`: _Default_. Object to object.
2914
  * `1`: Prototype to prototype.
2915
  * `2`: Prototype to prototype and object to object.
2916
  * `3`: Prototype to object.
2917
  * `4`: Object to prototype.
2918
 
2919
@method mix
2920
@param {Function|Object} receiver The object or function to receive the mixed
2921
  properties.
2922
@param {Function|Object} supplier The object or function supplying the
2923
  properties to be mixed.
2924
@param {Boolean} [overwrite=false] If `true`, properties that already exist
2925
  on the receiver will be overwritten with properties from the supplier.
2926
@param {String[]} [whitelist] An array of property names to copy. If
2927
  specified, only the whitelisted properties will be copied, and all others
2928
  will be ignored.
2929
@param {Number} [mode=0] Mix mode to use. See above for available modes.
2930
@param {Boolean} [merge=false] If `true`, objects and arrays that already
2931
  exist on the receiver will have the corresponding object/array from the
2932
  supplier merged into them, rather than being skipped or overwritten. When
2933
  both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
2934
@return {Function|Object|YUI} The receiver, or the YUI instance if the
2935
  specified receiver is falsy.
2936
**/
2937
Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
2938
    var alwaysOverwrite, exists, from, i, key, len, to;
2939
 
2940
    // If no supplier is given, we return the receiver. If no receiver is given,
2941
    // we return Y. Returning Y doesn't make much sense to me, but it's
2942
    // grandfathered in for backcompat reasons.
2943
    if (!receiver || !supplier) {
2944
        return receiver || Y;
2945
    }
2946
 
2947
    if (mode) {
2948
        // In mode 2 (prototype to prototype and object to object), we recurse
2949
        // once to do the proto to proto mix. The object to object mix will be
2950
        // handled later on.
2951
        if (mode === 2) {
2952
            Y.mix(receiver.prototype, supplier.prototype, overwrite,
2953
                    whitelist, 0, merge);
2954
        }
2955
 
2956
        // Depending on which mode is specified, we may be copying from or to
2957
        // the prototypes of the supplier and receiver.
2958
        from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
2959
        to   = mode === 1 || mode === 4 ? receiver.prototype : receiver;
2960
 
2961
        // If either the supplier or receiver doesn't actually have a
2962
        // prototype property, then we could end up with an undefined `from`
2963
        // or `to`. If that happens, we abort and return the receiver.
2964
        if (!from || !to) {
2965
            return receiver;
2966
        }
2967
    } else {
2968
        from = supplier;
2969
        to   = receiver;
2970
    }
2971
 
2972
    // If `overwrite` is truthy and `merge` is falsy, then we can skip a
2973
    // property existence check on each iteration and save some time.
2974
    alwaysOverwrite = overwrite && !merge;
2975
 
2976
    if (whitelist) {
2977
        for (i = 0, len = whitelist.length; i < len; ++i) {
2978
            key = whitelist[i];
2979
 
2980
            // We call `Object.prototype.hasOwnProperty` instead of calling
2981
            // `hasOwnProperty` on the object itself, since the object's
2982
            // `hasOwnProperty` method may have been overridden or removed.
2983
            // Also, some native objects don't implement a `hasOwnProperty`
2984
            // method.
2985
            if (!hasOwn.call(from, key)) {
2986
                continue;
2987
            }
2988
 
2989
            // The `key in to` check here is (sadly) intentional for backwards
2990
            // compatibility reasons. It prevents undesired shadowing of
2991
            // prototype members on `to`.
2992
            exists = alwaysOverwrite ? false : key in to;
2993
 
2994
            if (merge && exists && isObject(to[key], true)
2995
                    && isObject(from[key], true)) {
2996
                // If we're in merge mode, and the key is present on both
2997
                // objects, and the value on both objects is either an object or
2998
                // an array (but not a function), then we recurse to merge the
2999
                // `from` value into the `to` value instead of overwriting it.
3000
                //
3001
                // Note: It's intentional that the whitelist isn't passed to the
3002
                // recursive call here. This is legacy behavior that lots of
3003
                // code still depends on.
3004
                Y.mix(to[key], from[key], overwrite, null, 0, merge);
3005
            } else if (overwrite || !exists) {
3006
                // We're not in merge mode, so we'll only copy the `from` value
3007
                // to the `to` value if we're in overwrite mode or if the
3008
                // current key doesn't exist on the `to` object.
3009
                to[key] = from[key];
3010
            }
3011
        }
3012
    } else {
3013
        for (key in from) {
3014
            // The code duplication here is for runtime performance reasons.
3015
            // Combining whitelist and non-whitelist operations into a single
3016
            // loop or breaking the shared logic out into a function both result
3017
            // in worse performance, and Y.mix is critical enough that the byte
3018
            // tradeoff is worth it.
3019
            if (!hasOwn.call(from, key)) {
3020
                continue;
3021
            }
3022
 
3023
            // The `key in to` check here is (sadly) intentional for backwards
3024
            // compatibility reasons. It prevents undesired shadowing of
3025
            // prototype members on `to`.
3026
            exists = alwaysOverwrite ? false : key in to;
3027
 
3028
            if (merge && exists && isObject(to[key], true)
3029
                    && isObject(from[key], true)) {
3030
                Y.mix(to[key], from[key], overwrite, null, 0, merge);
3031
            } else if (overwrite || !exists) {
3032
                to[key] = from[key];
3033
            }
3034
        }
3035
 
3036
        // If this is an IE browser with the JScript enumeration bug, force
3037
        // enumeration of the buggy properties by making a recursive call with
3038
        // the buggy properties as the whitelist.
3039
        if (Y.Object._hasEnumBug) {
3040
            Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
3041
        }
3042
    }
3043
 
3044
    return receiver;
3045
};
3046
/**
3047
 * The YUI module contains the components required for building the YUI
3048
 * seed file.  This includes the script loading mechanism, a simple queue,
3049
 * and the core utilities for the library.
3050
 * @module yui
3051
 * @submodule yui-base
3052
 */
3053
 
3054
/**
3055
 * Adds utilities to the YUI instance for working with objects.
3056
 *
3057
 * @class Object
3058
 */
3059
 
3060
var Lang   = Y.Lang,
3061
    hasOwn = Object.prototype.hasOwnProperty,
3062
 
3063
    UNDEFINED, // <-- Note the comma. We're still declaring vars.
3064
 
3065
/**
3066
 * Returns a new object that uses _obj_ as its prototype. This method wraps the
3067
 * native ES5 `Object.create()` method if available, but doesn't currently
3068
 * pass through `Object.create()`'s second argument (properties) in order to
3069
 * ensure compatibility with older browsers.
3070
 *
3071
 * @method ()
3072
 * @param {Object} obj Prototype object.
3073
 * @return {Object} New object using _obj_ as its prototype.
3074
 * @static
3075
 */
3076
O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
3077
    // We currently wrap the native Object.create instead of simply aliasing it
3078
    // to ensure consistency with our fallback shim, which currently doesn't
3079
    // support Object.create()'s second argument (properties). Once we have a
3080
    // safe fallback for the properties arg, we can stop wrapping
3081
    // Object.create().
3082
    return Object.create(obj);
3083
} : (function () {
3084
    // Reusable constructor function for the Object.create() shim.
3085
    function F() {}
3086
 
3087
    // The actual shim.
3088
    return function (obj) {
3089
        F.prototype = obj;
3090
        return new F();
3091
    };
3092
}()),
3093
 
3094
/**
3095
 * Property names that IE doesn't enumerate in for..in loops, even when they
3096
 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
3097
 * manually enumerate these properties.
3098
 *
3099
 * @property _forceEnum
3100
 * @type String[]
3101
 * @protected
3102
 * @static
3103
 */
3104
forceEnum = O._forceEnum = [
3105
    'hasOwnProperty',
3106
    'isPrototypeOf',
3107
    'propertyIsEnumerable',
3108
    'toString',
3109
    'toLocaleString',
3110
    'valueOf'
3111
],
3112
 
3113
/**
3114
 * `true` if this browser has the JScript enumeration bug that prevents
3115
 * enumeration of the properties named in the `_forceEnum` array, `false`
3116
 * otherwise.
3117
 *
3118
 * See:
3119
 *   - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
3120
 *   - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
3121
 *
3122
 * @property _hasEnumBug
3123
 * @type Boolean
3124
 * @protected
3125
 * @static
3126
 */
3127
hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
3128
 
3129
/**
3130
 * `true` if this browser incorrectly considers the `prototype` property of
3131
 * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x.
3132
 *
3133
 * @property _hasProtoEnumBug
3134
 * @type Boolean
3135
 * @protected
3136
 * @static
3137
 */
3138
hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
3139
 
3140
/**
3141
 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
3142
 * exists only on _obj_'s prototype. This is essentially a safer version of
3143
 * `obj.hasOwnProperty()`.
3144
 *
3145
 * @method owns
3146
 * @param {Object} obj Object to test.
3147
 * @param {String} key Property name to look for.
3148
 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3149
 * @static
3150
 */
3151
owns = O.owns = function (obj, key) {
3152
    return !!obj && hasOwn.call(obj, key);
3153
}; // <-- End of var declarations.
3154
 
3155
/**
3156
 * Alias for `owns()`.
3157
 *
3158
 * @method hasKey
3159
 * @param {Object} obj Object to test.
3160
 * @param {String} key Property name to look for.
3161
 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3162
 * @static
3163
 */
3164
O.hasKey = owns;
3165
 
3166
/**
3167
 * Returns an array containing the object's enumerable keys. Does not include
3168
 * prototype keys or non-enumerable keys.
3169
 *
3170
 * Note that keys are returned in enumeration order (that is, in the same order
3171
 * that they would be enumerated by a `for-in` loop), which may not be the same
3172
 * as the order in which they were defined.
3173
 *
3174
 * This method is an alias for the native ES5 `Object.keys()` method if
3175
 * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of
3176
 * `Object.keys()` have an inconsistency as they consider `prototype` to be
3177
 * enumerable, so a non-native shim is used to rectify the difference.
3178
 *
3179
 * @example
3180
 *
3181
 *     Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
3182
 *     // => ['a', 'b', 'c']
3183
 *
3184
 * @method keys
3185
 * @param {Object} obj An object.
3186
 * @return {String[]} Array of keys.
3187
 * @static
3188
 */
3189
O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) {
3190
    if (!Lang.isObject(obj)) {
3191
        throw new TypeError('Object.keys called on a non-object');
3192
    }
3193
 
3194
    var keys = [],
3195
        i, key, len;
3196
 
3197
    if (hasProtoEnumBug && typeof obj === 'function') {
3198
        for (key in obj) {
3199
            if (owns(obj, key) && key !== 'prototype') {
3200
                keys.push(key);
3201
            }
3202
        }
3203
    } else {
3204
        for (key in obj) {
3205
            if (owns(obj, key)) {
3206
                keys.push(key);
3207
            }
3208
        }
3209
    }
3210
 
3211
    if (hasEnumBug) {
3212
        for (i = 0, len = forceEnum.length; i < len; ++i) {
3213
            key = forceEnum[i];
3214
 
3215
            if (owns(obj, key)) {
3216
                keys.push(key);
3217
            }
3218
        }
3219
    }
3220
 
3221
    return keys;
3222
};
3223
 
3224
/**
3225
 * Returns an array containing the values of the object's enumerable keys.
3226
 *
3227
 * Note that values are returned in enumeration order (that is, in the same
3228
 * order that they would be enumerated by a `for-in` loop), which may not be the
3229
 * same as the order in which they were defined.
3230
 *
3231
 * @example
3232
 *
3233
 *     Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
3234
 *     // => ['foo', 'bar', 'baz']
3235
 *
3236
 * @method values
3237
 * @param {Object} obj An object.
3238
 * @return {Array} Array of values.
3239
 * @static
3240
 */
3241
O.values = function (obj) {
3242
    var keys   = O.keys(obj),
3243
        i      = 0,
3244
        len    = keys.length,
3245
        values = [];
3246
 
3247
    for (; i < len; ++i) {
3248
        values.push(obj[keys[i]]);
3249
    }
3250
 
3251
    return values;
3252
};
3253
 
3254
/**
3255
 * Returns the number of enumerable keys owned by an object.
3256
 *
3257
 * @method size
3258
 * @param {Object} obj An object.
3259
 * @return {Number} The object's size.
3260
 * @static
3261
 */
3262
O.size = function (obj) {
3263
    try {
3264
        return O.keys(obj).length;
3265
    } catch (ex) {
3266
        return 0; // Legacy behavior for non-objects.
3267
    }
3268
};
3269
 
3270
/**
3271
 * Returns `true` if the object owns an enumerable property with the specified
3272
 * value.
3273
 *
3274
 * @method hasValue
3275
 * @param {Object} obj An object.
3276
 * @param {any} value The value to search for.
3277
 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3278
 * @static
3279
 */
3280
O.hasValue = function (obj, value) {
3281
    return Y.Array.indexOf(O.values(obj), value) > -1;
3282
};
3283
 
3284
/**
3285
 * Executes a function on each enumerable property in _obj_. The function
3286
 * receives the value, the key, and the object itself as parameters (in that
3287
 * order).
3288
 *
3289
 * By default, only properties owned by _obj_ are enumerated. To include
3290
 * prototype properties, set the _proto_ parameter to `true`.
3291
 *
3292
 * @method each
3293
 * @param {Object} obj Object to enumerate.
3294
 * @param {Function} fn Function to execute on each enumerable property.
3295
 *   @param {mixed} fn.value Value of the current property.
3296
 *   @param {String} fn.key Key of the current property.
3297
 *   @param {Object} fn.obj Object being enumerated.
3298
 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3299
 * @param {Boolean} [proto=false] Include prototype properties.
3300
 * @return {YUI} the YUI instance.
3301
 * @chainable
3302
 * @static
3303
 */
3304
O.each = function (obj, fn, thisObj, proto) {
3305
    var key;
3306
 
3307
    for (key in obj) {
3308
        if (proto || owns(obj, key)) {
3309
            fn.call(thisObj || Y, obj[key], key, obj);
3310
        }
3311
    }
3312
 
3313
    return Y;
3314
};
3315
 
3316
/**
3317
 * Executes a function on each enumerable property in _obj_, but halts if the
3318
 * function returns a truthy value. The function receives the value, the key,
3319
 * and the object itself as paramters (in that order).
3320
 *
3321
 * By default, only properties owned by _obj_ are enumerated. To include
3322
 * prototype properties, set the _proto_ parameter to `true`.
3323
 *
3324
 * @method some
3325
 * @param {Object} obj Object to enumerate.
3326
 * @param {Function} fn Function to execute on each enumerable property.
3327
 *   @param {mixed} fn.value Value of the current property.
3328
 *   @param {String} fn.key Key of the current property.
3329
 *   @param {Object} fn.obj Object being enumerated.
3330
 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3331
 * @param {Boolean} [proto=false] Include prototype properties.
3332
 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3333
 *   `false` otherwise.
3334
 * @static
3335
 */
3336
O.some = function (obj, fn, thisObj, proto) {
3337
    var key;
3338
 
3339
    for (key in obj) {
3340
        if (proto || owns(obj, key)) {
3341
            if (fn.call(thisObj || Y, obj[key], key, obj)) {
3342
                return true;
3343
            }
3344
        }
3345
    }
3346
 
3347
    return false;
3348
};
3349
 
3350
/**
3351
 * Retrieves the sub value at the provided path,
3352
 * from the value object provided.
3353
 *
3354
 * @method getValue
3355
 * @static
3356
 * @param o The object from which to extract the property value.
3357
 * @param path {Array} A path array, specifying the object traversal path
3358
 * from which to obtain the sub value.
3359
 * @return {Any} The value stored in the path, undefined if not found,
3360
 * undefined if the source is not an object.  Returns the source object
3361
 * if an empty path is provided.
3362
 */
3363
O.getValue = function(o, path) {
3364
    if (!Lang.isObject(o)) {
3365
        return UNDEFINED;
3366
    }
3367
 
3368
    var i,
3369
        p = Y.Array(path),
3370
        l = p.length;
3371
 
3372
    for (i = 0; o !== UNDEFINED && i < l; i++) {
3373
        o = o[p[i]];
3374
    }
3375
 
3376
    return o;
3377
};
3378
 
3379
/**
3380
 * Sets the sub-attribute value at the provided path on the
3381
 * value object.  Returns the modified value object, or
3382
 * undefined if the path is invalid.
3383
 *
3384
 * @method setValue
3385
 * @static
3386
 * @param o             The object on which to set the sub value.
3387
 * @param path {Array}  A path array, specifying the object traversal path
3388
 *                      at which to set the sub value.
3389
 * @param val {Any}     The new value for the sub-attribute.
3390
 * @return {Object}     The modified object, with the new sub value set, or
3391
 *                      undefined, if the path was invalid.
3392
 */
3393
O.setValue = function(o, path, val) {
3394
    var i,
3395
        p = Y.Array(path),
3396
        leafIdx = p.length - 1,
3397
        ref = o;
3398
 
3399
    if (leafIdx >= 0) {
3400
        for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3401
            ref = ref[p[i]];
3402
        }
3403
 
3404
        if (ref !== UNDEFINED) {
3405
            ref[p[i]] = val;
3406
        } else {
3407
            return UNDEFINED;
3408
        }
3409
    }
3410
 
3411
    return o;
3412
};
3413
 
3414
/**
3415
 * Returns `true` if the object has no enumerable properties of its own.
3416
 *
3417
 * @method isEmpty
3418
 * @param {Object} obj An object.
3419
 * @return {Boolean} `true` if the object is empty.
3420
 * @static
3421
 * @since 3.2.0
3422
 */
3423
O.isEmpty = function (obj) {
3424
    return !O.keys(Object(obj)).length;
3425
};
3426
/**
3427
 * The YUI module contains the components required for building the YUI seed
3428
 * file.  This includes the script loading mechanism, a simple queue, and the
3429
 * core utilities for the library.
3430
 * @module yui
3431
 * @submodule yui-base
3432
 */
3433
 
3434
/**
3435
 * YUI user agent detection.
3436
 * Do not fork for a browser if it can be avoided.  Use feature detection when
3437
 * you can.  Use the user agent as a last resort.  For all fields listed
3438
 * as @type float, UA stores a version number for the browser engine,
3439
 * 0 otherwise.  This value may or may not map to the version number of
3440
 * the browser using the engine.  The value is presented as a float so
3441
 * that it can easily be used for boolean evaluation as well as for
3442
 * looking for a particular range of versions.  Because of this,
3443
 * some of the granularity of the version info may be lost.  The fields that
3444
 * are @type string default to null.  The API docs list the values that
3445
 * these fields can have.
3446
 * @class UA
3447
 * @static
3448
 */
3449
 
3450
/**
3451
* Static method on `YUI.Env` for parsing a UA string.  Called at instantiation
3452
* to populate `Y.UA`.
3453
*
3454
* @static
3455
* @method parseUA
3456
* @param {String} [subUA=navigator.userAgent] UA string to parse
3457
* @return {Object} The Y.UA object
3458
*/
3459
YUI.Env.parseUA = function(subUA) {
3460
 
3461
    var numberify = function(s) {
3462
            var c = 0;
3463
            return parseFloat(s.replace(/\./g, function() {
3464
                return (c++ === 1) ? '' : '.';
3465
            }));
3466
        },
3467
 
3468
        win = Y.config.win,
3469
 
3470
        nav = win && win.navigator,
3471
 
3472
        o = {
3473
 
3474
        /**
3475
         * Internet Explorer version number or 0.  Example: 6
3476
         * @property ie
3477
         * @type float
3478
         * @static
3479
         */
3480
        ie: 0,
3481
 
3482
        /**
3483
         * Opera version number or 0.  Example: 9.2
3484
         * @property opera
3485
         * @type float
3486
         * @static
3487
         */
3488
        opera: 0,
3489
 
3490
        /**
3491
         * Gecko engine revision number.  Will evaluate to 1 if Gecko
3492
         * is detected but the revision could not be found. Other browsers
3493
         * will be 0.  Example: 1.8
3494
         * <pre>
3495
         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
3496
         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3497
         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3498
         * Firefox 3.0   <-- 1.9
3499
         * Firefox 3.5   <-- 1.91
3500
         * </pre>
3501
         * @property gecko
3502
         * @type float
3503
         * @static
3504
         */
3505
        gecko: 0,
3506
 
3507
        /**
3508
         * AppleWebKit version.  KHTML browsers that are not WebKit browsers
3509
         * will evaluate to 1, other browsers 0.  Example: 418.9
3510
         * <pre>
3511
         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3512
         *                                   latest available for Mac OSX 10.3.
3513
         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
3514
         * Safari 2.0.4:         418     <-- preventDefault fixed
3515
         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3516
         *                                   different versions of webkit
3517
         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
3518
         *                                   updated, but not updated
3519
         *                                   to the latest patch.
3520
         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
3521
         * SVG and many major issues fixed).
3522
         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
3523
         * update from 2.x via the 10.4.11 OS patch.
3524
         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
3525
         *                                   yahoo.com user agent hack removed.
3526
         * </pre>
3527
         * http://en.wikipedia.org/wiki/Safari_version_history
3528
         * @property webkit
3529
         * @type float
3530
         * @static
3531
         */
3532
        webkit: 0,
3533
 
3534
        /**
3535
         * Safari will be detected as webkit, but this property will also
3536
         * be populated with the Safari version number
3537
         * @property safari
3538
         * @type float
3539
         * @static
3540
         */
3541
        safari: 0,
3542
 
3543
        /**
3544
         * Chrome will be detected as webkit, but this property will also
3545
         * be populated with the Chrome version number
3546
         * @property chrome
3547
         * @type float
3548
         * @static
3549
         */
3550
        chrome: 0,
3551
 
3552
        /**
3553
         * The mobile property will be set to a string containing any relevant
3554
         * user agent information when a modern mobile browser is detected.
3555
         * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3556
         * devices with the WebKit-based browser, and Opera Mini.
3557
         * @property mobile
3558
         * @type string
3559
         * @default null
3560
         * @static
3561
         */
3562
        mobile: null,
3563
 
3564
        /**
3565
         * Adobe AIR version number or 0.  Only populated if webkit is detected.
3566
         * Example: 1.0
3567
         * @property air
3568
         * @type float
3569
         */
3570
        air: 0,
3571
        /**
3572
         * PhantomJS version number or 0.  Only populated if webkit is detected.
3573
         * Example: 1.0
3574
         * @property phantomjs
3575
         * @type float
3576
         */
3577
        phantomjs: 0,
3578
        /**
3579
         * Detects Apple iPad's OS version
3580
         * @property ipad
3581
         * @type float
3582
         * @static
3583
         */
3584
        ipad: 0,
3585
        /**
3586
         * Detects Apple iPhone's OS version
3587
         * @property iphone
3588
         * @type float
3589
         * @static
3590
         */
3591
        iphone: 0,
3592
        /**
3593
         * Detects Apples iPod's OS version
3594
         * @property ipod
3595
         * @type float
3596
         * @static
3597
         */
3598
        ipod: 0,
3599
        /**
3600
         * General truthy check for iPad, iPhone or iPod
3601
         * @property ios
3602
         * @type Boolean
3603
         * @default null
3604
         * @static
3605
         */
3606
        ios: null,
3607
        /**
3608
         * Detects Googles Android OS version
3609
         * @property android
3610
         * @type float
3611
         * @static
3612
         */
3613
        android: 0,
3614
        /**
3615
         * Detects Kindle Silk
3616
         * @property silk
3617
         * @type float
3618
         * @static
3619
         */
3620
        silk: 0,
3621
        /**
3622
         * Detects Ubuntu version
3623
         * @property ubuntu
3624
         * @type float
3625
         * @static
3626
         */
3627
        ubuntu: 0,
3628
        /**
3629
         * Detects Kindle Silk Acceleration
3630
         * @property accel
3631
         * @type Boolean
3632
         * @static
3633
         */
3634
        accel: false,
3635
        /**
3636
         * Detects Palms WebOS version
3637
         * @property webos
3638
         * @type float
3639
         * @static
3640
         */
3641
        webos: 0,
3642
 
3643
        /**
3644
         * Google Caja version number or 0.
3645
         * @property caja
3646
         * @type float
3647
         */
3648
        caja: nav && nav.cajaVersion,
3649
 
3650
        /**
3651
         * Set to true if the page appears to be in SSL
3652
         * @property secure
3653
         * @type boolean
3654
         * @static
3655
         */
3656
        secure: false,
3657
 
3658
        /**
3659
         * The operating system.
3660
         *
3661
         * Possible values are `windows`, `macintosh`, `android`, `symbos`, `linux`, `rhino` and `ios`.
3662
         *
3663
         * @property os
3664
         * @type string
3665
         * @default null
3666
         * @static
3667
         */
3668
        os: null,
3669
 
3670
        /**
3671
         * The Nodejs Version
3672
         * @property nodejs
3673
         * @type float
3674
         * @default 0
3675
         * @static
3676
         */
3677
        nodejs: 0,
3678
        /**
3679
        * Window8/IE10 Application host environment
3680
        * @property winjs
3681
        * @type Boolean
3682
        * @static
3683
        */
3684
        winjs: !!((typeof Windows !== "undefined") && Windows.System),
3685
        /**
3686
        * Are touch/msPointer events available on this device
3687
        * @property touchEnabled
3688
        * @type Boolean
3689
        * @static
3690
        */
3691
        touchEnabled: false
3692
    },
3693
 
3694
    ua = subUA || nav && nav.userAgent,
3695
 
3696
    loc = win && win.location,
3697
 
3698
    href = loc && loc.href,
3699
 
3700
    m;
3701
 
3702
    /**
3703
    * The User Agent string that was parsed
3704
    * @property userAgent
3705
    * @type String
3706
    * @static
3707
    */
3708
    o.userAgent = ua;
3709
 
3710
 
3711
    o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3712
 
3713
    if (ua) {
3714
 
3715
        if ((/windows|win32/i).test(ua)) {
3716
            o.os = 'windows';
3717
        } else if ((/macintosh|mac_powerpc/i).test(ua)) {
3718
            o.os = 'macintosh';
3719
        } else if ((/android/i).test(ua)) {
3720
            o.os = 'android';
3721
        } else if ((/symbos/i).test(ua)) {
3722
            o.os = 'symbos';
3723
        } else if ((/linux/i).test(ua)) {
3724
            o.os = 'linux';
3725
        } else if ((/rhino/i).test(ua)) {
3726
            o.os = 'rhino';
3727
        }
3728
 
3729
        // Modern KHTML browsers should qualify as Safari X-Grade
3730
        if ((/KHTML/).test(ua)) {
3731
            o.webkit = 1;
3732
        }
3733
        if ((/IEMobile|XBLWP7/).test(ua)) {
3734
            o.mobile = 'windows';
3735
        }
3736
        if ((/Fennec/).test(ua)) {
3737
            o.mobile = 'gecko';
3738
        }
3739
        // Modern WebKit browsers are at least X-Grade
3740
        m = ua.match(/AppleWebKit\/([^\s]*)/);
3741
        if (m && m[1]) {
3742
            o.webkit = numberify(m[1]);
3743
            o.safari = o.webkit;
3744
 
3745
            if (/PhantomJS/.test(ua)) {
3746
                m = ua.match(/PhantomJS\/([^\s]*)/);
3747
                if (m && m[1]) {
3748
                    o.phantomjs = numberify(m[1]);
3749
                }
3750
            }
3751
 
3752
            // Mobile browser check
3753
            if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
3754
                o.mobile = 'Apple'; // iPhone or iPod Touch
3755
 
3756
                m = ua.match(/OS ([^\s]*)/);
3757
                if (m && m[1]) {
3758
                    m = numberify(m[1].replace('_', '.'));
3759
                }
3760
                o.ios = m;
3761
                o.os = 'ios';
3762
                o.ipad = o.ipod = o.iphone = 0;
3763
 
3764
                m = ua.match(/iPad|iPod|iPhone/);
3765
                if (m && m[0]) {
3766
                    o[m[0].toLowerCase()] = o.ios;
3767
                }
3768
            } else {
3769
                m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3770
                if (m) {
3771
                    // Nokia N-series, webOS, ex: NokiaN95
3772
                    o.mobile = m[0];
3773
                }
3774
                if (/webOS/.test(ua)) {
3775
                    o.mobile = 'WebOS';
3776
                    m = ua.match(/webOS\/([^\s]*);/);
3777
                    if (m && m[1]) {
3778
                        o.webos = numberify(m[1]);
3779
                    }
3780
                }
3781
                if (/ Android/.test(ua)) {
3782
                    o.mobile = 'Android';
3783
                    m = ua.match(/Android ([^\s]*);/);
3784
                    if (m && m[1]) {
3785
                        o.android = numberify(m[1]);
3786
                    }
3787
 
3788
                }
3789
                if (/Silk/.test(ua)) {
3790
                    m = ua.match(/Silk\/([^\s]*)/);
3791
                    if (m && m[1]) {
3792
                        o.silk = numberify(m[1]);
3793
                    }
3794
                    if (!o.android) {
3795
                        o.android = 2.34; //Hack for desktop mode in Kindle
3796
                        o.os = 'Android';
3797
                    }
3798
                    if (/Accelerated=true/.test(ua)) {
3799
                        o.accel = true;
3800
                    }
3801
                }
3802
            }
3803
 
3804
            m = ua.match(/OPR\/(\d+\.\d+)/);
3805
 
3806
            if (m && m[1]) {
3807
                // Opera 15+ with Blink (pretends to be both Chrome and Safari)
3808
                o.opera = numberify(m[1]);
3809
            } else {
3810
                m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
3811
 
3812
                if (m && m[1] && m[2]) {
3813
                    o.chrome = numberify(m[2]); // Chrome
3814
                    o.safari = 0; //Reset safari back to 0
3815
                    if (m[1] === 'CrMo') {
3816
                        o.mobile = 'chrome';
3817
                    }
3818
                } else {
3819
                    m = ua.match(/AdobeAIR\/([^\s]*)/);
3820
                    if (m) {
3821
                        o.air = m[0]; // Adobe AIR 1.0 or better
3822
                    }
3823
                }
3824
            }
3825
        }
3826
 
3827
        m = ua.match(/Ubuntu\ (\d+\.\d+)/);
3828
        if (m && m[1]) {
3829
 
3830
            o.os = 'linux';
3831
            o.ubuntu = numberify(m[1]);
3832
 
3833
            m = ua.match(/\ WebKit\/([^\s]*)/);
3834
            if (m && m[1]) {
3835
                o.webkit = numberify(m[1]);
3836
            }
3837
            m = ua.match(/\ Chromium\/([^\s]*)/);
3838
            if (m && m[1]) {
3839
                o.chrome = numberify(m[1]);
3840
            }
3841
            if (/ Mobile$/.test(ua)) {
3842
                o.mobile = 'Ubuntu';
3843
            }
3844
        }
3845
 
3846
        if (!o.webkit) { // not webkit
3847
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3848
            if (/Opera/.test(ua)) {
3849
                m = ua.match(/Opera[\s\/]([^\s]*)/);
3850
                if (m && m[1]) {
3851
                    o.opera = numberify(m[1]);
3852
                }
3853
                m = ua.match(/Version\/([^\s]*)/);
3854
                if (m && m[1]) {
3855
                    o.opera = numberify(m[1]); // opera 10+
3856
                }
3857
 
3858
                if (/Opera Mobi/.test(ua)) {
3859
                    o.mobile = 'opera';
3860
                    m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
3861
                    if (m && m[1]) {
3862
                        o.opera = numberify(m[1]);
3863
                    }
3864
                }
3865
                m = ua.match(/Opera Mini[^;]*/);
3866
 
3867
                if (m) {
3868
                    o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3869
                }
3870
            } else { // not opera or webkit
3871
                m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/);
3872
 
3873
                if (m && (m[1] || m[2])) {
3874
                    o.ie = numberify(m[1] || m[2]);
3875
                } else { // not opera, webkit, or ie
3876
                    m = ua.match(/Gecko\/([^\s]*)/);
3877
 
3878
                    if (m) {
3879
                        o.gecko = 1; // Gecko detected, look for revision
3880
                        m = ua.match(/rv:([^\s\)]*)/);
3881
                        if (m && m[1]) {
3882
                            o.gecko = numberify(m[1]);
3883
                            if (/Mobile|Tablet/.test(ua)) {
3884
                                o.mobile = "ffos";
3885
                            }
3886
                        }
3887
                    }
3888
                }
3889
            }
3890
        }
3891
    }
3892
 
3893
    //Check for known properties to tell if touch events are enabled on this device or if
3894
    //the number of MSPointer touchpoints on this device is greater than 0.
3895
    if (win && nav && !(o.chrome && o.chrome < 6)) {
3896
        o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
3897
    }
3898
 
3899
    //It was a parsed UA, do not assign the global value.
3900
    if (!subUA) {
3901
 
3902
        if (typeof process === 'object') {
3903
 
3904
            if (process.versions && process.versions.node) {
3905
                //NodeJS
3906
                o.os = process.platform;
3907
                o.nodejs = numberify(process.versions.node);
3908
            }
3909
        }
3910
 
3911
        YUI.Env.UA = o;
3912
 
3913
    }
3914
 
3915
    return o;
3916
};
3917
 
3918
 
3919
Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3920
 
3921
/**
3922
Performs a simple comparison between two version numbers, accounting for
3923
standard versioning logic such as the fact that "535.8" is a lower version than
3924
"535.24", even though a simple numerical comparison would indicate that it's
3925
greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
3926
considered equivalent.
3927
 
3928
Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
3929
1 if _a_ is higher than _b_.
3930
 
3931
Versions may be numbers or strings containing numbers and dots. For example,
3932
both `535` and `"535.8.10"` are acceptable. A version string containing
3933
non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
3934
 
3935
@method compareVersions
3936
@param {Number|String} a First version number to compare.
3937
@param {Number|String} b Second version number to compare.
3938
@return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
3939
    higher than _b_.
3940
**/
3941
Y.UA.compareVersions = function (a, b) {
3942
    var aPart, aParts, bPart, bParts, i, len;
3943
 
3944
    if (a === b) {
3945
        return 0;
3946
    }
3947
 
3948
    aParts = (a + '').split('.');
3949
    bParts = (b + '').split('.');
3950
 
3951
    for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
3952
        aPart = parseInt(aParts[i], 10);
3953
        bPart = parseInt(bParts[i], 10);
3954
 
3955
        /*jshint expr: true*/
3956
        isNaN(aPart) && (aPart = 0);
3957
        isNaN(bPart) && (bPart = 0);
3958
 
3959
        if (aPart < bPart) {
3960
            return -1;
3961
        }
3962
 
3963
        if (aPart > bPart) {
3964
            return 1;
3965
        }
3966
    }
3967
 
3968
    return 0;
3969
};
3970
YUI.Env.aliases = {
3971
    "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
3972
    "anim-shape-transform": ["anim-shape"],
3973
    "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"],
3974
    "attribute": ["attribute-base","attribute-complex"],
3975
    "attribute-events": ["attribute-observable"],
3976
    "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
3977
    "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
3978
    "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
3979
    "base": ["base-base","base-pluginhost","base-build"],
3980
    "cache": ["cache-base","cache-offline","cache-plugin"],
3981
    "charts": ["charts-base"],
3982
    "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
3983
    "color": ["color-base","color-hsl","color-harmony"],
3984
    "controller": ["router"],
3985
    "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
3986
    "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
3987
    "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
3988
    "datatype": ["datatype-date","datatype-number","datatype-xml"],
3989
    "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
3990
    "datatype-number": ["datatype-number-parse","datatype-number-format"],
3991
    "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
3992
    "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
3993
    "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
3994
    "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
3995
    "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"],
3996
    "event-custom": ["event-custom-base","event-custom-complex"],
3997
    "event-gestures": ["event-flick","event-move"],
3998
    "handlebars": ["handlebars-compiler"],
3999
    "highlight": ["highlight-base","highlight-accentfold"],
4000
    "history": ["history-base","history-hash","history-html5"],
4001
    "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
4002
    "json": ["json-parse","json-stringify"],
4003
    "loader": ["loader-base","loader-rollup","loader-yui3"],
4004
    "loader-pathogen-encoder": ["loader-base","loader-rollup","loader-yui3","loader-pathogen-combohandler"],
4005
    "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
4006
    "pluginhost": ["pluginhost-base","pluginhost-config"],
4007
    "querystring": ["querystring-parse","querystring-stringify"],
4008
    "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
4009
    "resize": ["resize-base","resize-proxy","resize-constrain"],
4010
    "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
4011
    "template": ["template-base","template-micro"],
4012
    "text": ["text-accentfold","text-wordbreak"],
4013
    "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
4014
};
4015
 
4016
 
4017
}, '3.18.1', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
4018
YUI.add('get', function (Y, NAME) {
4019
 
4020
/*jslint boss:true, expr:true, laxbreak: true */
4021
 
4022
/**
4023
Provides dynamic loading of remote JavaScript and CSS resources.
4024
 
4025
@module get
4026
@class Get
4027
@static
4028
**/
4029
 
4030
var Lang = Y.Lang,
4031
 
4032
    CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode()
4033
 
4034
    Get, Transaction;
4035
 
4036
Y.Get = Get = {
4037
    // -- Public Properties ----------------------------------------------------
4038
 
4039
    /**
4040
    Default options for CSS requests. Options specified here will override
4041
    global defaults for CSS requests.
4042
 
4043
    See the `options` property for all available options.
4044
 
4045
    @property cssOptions
4046
    @type Object
4047
    @static
4048
    @since 3.5.0
4049
    **/
4050
    cssOptions: {
4051
        attributes: {
4052
            rel: 'stylesheet'
4053
        },
4054
 
4055
        doc         : Y.config.linkDoc || Y.config.doc,
4056
        pollInterval: 50
4057
    },
4058
 
4059
    /**
4060
    Default options for JS requests. Options specified here will override global
4061
    defaults for JS requests.
4062
 
4063
    See the `options` property for all available options.
4064
 
4065
    @property jsOptions
4066
    @type Object
4067
    @static
4068
    @since 3.5.0
4069
    **/
4070
    jsOptions: {
4071
        autopurge: true,
4072
        doc      : Y.config.scriptDoc || Y.config.doc
4073
    },
4074
 
4075
    /**
4076
    Default options to use for all requests.
4077
 
4078
    Note that while all available options are documented here for ease of
4079
    discovery, some options (like callback functions) only make sense at the
4080
    transaction level.
4081
 
4082
    Callback functions specified via the options object or the `options`
4083
    parameter of the `css()`, `js()`, or `load()` methods will receive the
4084
    transaction object as a parameter. See `Y.Get.Transaction` for details on
4085
    the properties and methods available on transactions.
4086
 
4087
    @static
4088
    @since 3.5.0
4089
    @property {Object} options
4090
 
4091
    @property {Boolean} [options.async=false] Whether or not to load scripts
4092
        asynchronously, meaning they're requested in parallel and execution
4093
        order is not guaranteed. Has no effect on CSS, since CSS is always
4094
        loaded asynchronously.
4095
 
4096
    @property {Object} [options.attributes] HTML attribute name/value pairs that
4097
        should be added to inserted nodes. By default, the `charset` attribute
4098
        will be set to "utf-8" and nodes will be given an auto-generated `id`
4099
        attribute, but you can override these with your own values if desired.
4100
 
4101
    @property {Boolean} [options.autopurge] Whether or not to automatically
4102
        purge inserted nodes after the purge threshold is reached. This is
4103
        `true` by default for JavaScript, but `false` for CSS since purging a
4104
        CSS node will also remove any styling applied by the referenced file.
4105
 
4106
    @property {Object} [options.context] `this` object to use when calling
4107
        callback functions. Defaults to the transaction object.
4108
 
4109
    @property {Mixed} [options.data] Arbitrary data object to pass to "on*"
4110
        callbacks.
4111
 
4112
    @property {Document} [options.doc] Document into which nodes should be
4113
        inserted. By default, the current document is used.
4114
 
4115
    @property {HTMLElement|String} [options.insertBefore] HTML element or id
4116
        string of an element before which all generated nodes should be
4117
        inserted. If not specified, Get will automatically determine the best
4118
        place to insert nodes for maximum compatibility.
4119
 
4120
    @property {Function} [options.onEnd] Callback to execute after a transaction
4121
        is complete, regardless of whether it succeeded or failed.
4122
 
4123
    @property {Function} [options.onFailure] Callback to execute after a
4124
        transaction fails, times out, or is aborted.
4125
 
4126
    @property {Function} [options.onProgress] Callback to execute after each
4127
        individual request in a transaction either succeeds or fails.
4128
 
4129
    @property {Function} [options.onSuccess] Callback to execute after a
4130
        transaction completes successfully with no errors. Note that in browsers
4131
        that don't support the `error` event on CSS `<link>` nodes, a failed CSS
4132
        request may still be reported as a success because in these browsers
4133
        it can be difficult or impossible to distinguish between success and
4134
        failure for CSS resources.
4135
 
4136
    @property {Function} [options.onTimeout] Callback to execute after a
4137
        transaction times out.
4138
 
4139
    @property {Number} [options.pollInterval=50] Polling interval (in
4140
        milliseconds) for detecting CSS load completion in browsers that don't
4141
        support the `load` event on `<link>` nodes. This isn't used for
4142
        JavaScript.
4143
 
4144
    @property {Number} [options.purgethreshold=20] Number of nodes to insert
4145
        before triggering an automatic purge when `autopurge` is `true`.
4146
 
4147
    @property {Number} [options.timeout] Number of milliseconds to wait before
4148
        aborting a transaction. When a timeout occurs, the `onTimeout` callback
4149
        is called, followed by `onFailure` and finally `onEnd`. By default,
4150
        there is no timeout.
4151
 
4152
    @property {String} [options.type] Resource type ("css" or "js"). This option
4153
        is set automatically by the `css()` and `js()` functions and will be
4154
        ignored there, but may be useful when using the `load()` function. If
4155
        not specified, the type will be inferred from the URL, defaulting to
4156
        "js" if the URL doesn't contain a recognizable file extension.
4157
    **/
4158
    options: {
4159
        attributes: {
4160
            charset: 'utf-8'
4161
        },
4162
 
4163
        purgethreshold: 20
4164
    },
4165
 
4166
    // -- Protected Properties -------------------------------------------------
4167
 
4168
    /**
4169
    Regex that matches a CSS URL. Used to guess the file type when it's not
4170
    specified.
4171
 
4172
    @property REGEX_CSS
4173
    @type RegExp
4174
    @final
4175
    @protected
4176
    @static
4177
    @since 3.5.0
4178
    **/
4179
    REGEX_CSS: /\.css(?:[?;].*)?$/i,
4180
 
4181
    /**
4182
    Regex that matches a JS URL. Used to guess the file type when it's not
4183
    specified.
4184
 
4185
    @property REGEX_JS
4186
    @type RegExp
4187
    @final
4188
    @protected
4189
    @static
4190
    @since 3.5.0
4191
    **/
4192
    REGEX_JS : /\.js(?:[?;].*)?$/i,
4193
 
4194
    /**
4195
    Contains information about the current environment, such as what script and
4196
    link injection features it supports.
4197
 
4198
    This object is created and populated the first time the `_getEnv()` method
4199
    is called.
4200
 
4201
    @property _env
4202
    @type Object
4203
    @protected
4204
    @static
4205
    @since 3.5.0
4206
    **/
4207
 
4208
    /**
4209
    Mapping of document _yuid strings to <head> or <base> node references so we
4210
    don't have to look the node up each time we want to insert a request node.
4211
 
4212
    @property _insertCache
4213
    @type Object
4214
    @protected
4215
    @static
4216
    @since 3.5.0
4217
    **/
4218
    _insertCache: {},
4219
 
4220
    /**
4221
    Information about the currently pending transaction, if any.
4222
 
4223
    This is actually an object with two properties: `callback`, containing the
4224
    optional callback passed to `css()`, `load()`, or `js()`; and `transaction`,
4225
    containing the actual transaction instance.
4226
 
4227
    @property _pending
4228
    @type Object
4229
    @protected
4230
    @static
4231
    @since 3.5.0
4232
    **/
4233
    _pending: null,
4234
 
4235
    /**
4236
    HTML nodes eligible to be purged next time autopurge is triggered.
4237
 
4238
    @property _purgeNodes
4239
    @type HTMLElement[]
4240
    @protected
4241
    @static
4242
    @since 3.5.0
4243
    **/
4244
    _purgeNodes: [],
4245
 
4246
    /**
4247
    Queued transactions and associated callbacks.
4248
 
4249
    @property _queue
4250
    @type Object[]
4251
    @protected
4252
    @static
4253
    @since 3.5.0
4254
    **/
4255
    _queue: [],
4256
 
4257
    // -- Public Methods -------------------------------------------------------
4258
 
4259
    /**
4260
    Aborts the specified transaction.
4261
 
4262
    This will cause the transaction's `onFailure` callback to be called and
4263
    will prevent any new script and link nodes from being added to the document,
4264
    but any resources that have already been requested will continue loading
4265
    (there's no safe way to prevent this, unfortunately).
4266
 
4267
    *Note:* This method is deprecated as of 3.5.0, and will be removed in a
4268
    future version of YUI. Use the transaction-level `abort()` method instead.
4269
 
4270
    @method abort
4271
    @param {Get.Transaction} transaction Transaction to abort.
4272
    @deprecated Use the `abort()` method on the transaction instead.
4273
    @static
4274
    **/
4275
    abort: function (transaction) {
4276
        var i, id, item, len, pending;
4277
 
4278
 
4279
        if (!transaction.abort) {
4280
            id          = transaction;
4281
            pending     = this._pending;
4282
            transaction = null;
4283
 
4284
            if (pending && pending.transaction.id === id) {
4285
                transaction   = pending.transaction;
4286
                this._pending = null;
4287
            } else {
4288
                for (i = 0, len = this._queue.length; i < len; ++i) {
4289
                    item = this._queue[i].transaction;
4290
 
4291
                    if (item.id === id) {
4292
                        transaction = item;
4293
                        this._queue.splice(i, 1);
4294
                        break;
4295
                    }
4296
                }
4297
            }
4298
        }
4299
 
4300
        transaction && transaction.abort();
4301
    },
4302
 
4303
    /**
4304
    Loads one or more CSS files.
4305
 
4306
    The _urls_ parameter may be provided as a URL string, a request object,
4307
    or an array of URL strings and/or request objects.
4308
 
4309
    A request object is just an object that contains a `url` property and zero
4310
    or more options that should apply specifically to that request.
4311
    Request-specific options take priority over transaction-level options and
4312
    default options.
4313
 
4314
    URLs may be relative or absolute, and do not have to have the same origin
4315
    as the current page.
4316
 
4317
    The `options` parameter may be omitted completely and a callback passed in
4318
    its place, if desired.
4319
 
4320
    @example
4321
 
4322
        // Load a single CSS file and log a message on completion.
4323
        Y.Get.css('foo.css', function (err) {
4324
            if (err) {
4325
            } else {
4326
            }
4327
        });
4328
 
4329
        // Load multiple CSS files and log a message when all have finished
4330
        // loading.
4331
        var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css'];
4332
 
4333
        Y.Get.css(urls, function (err) {
4334
            if (err) {
4335
            } else {
4336
            }
4337
        });
4338
 
4339
        // Specify transaction-level options, which will apply to all requests
4340
        // within the transaction.
4341
        Y.Get.css(urls, {
4342
            attributes: {'class': 'my-css'},
4343
            timeout   : 5000
4344
        });
4345
 
4346
        // Specify per-request options, which override transaction-level and
4347
        // default options.
4348
        Y.Get.css([
4349
            {url: 'foo.css', attributes: {id: 'foo'}},
4350
            {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}}
4351
        ]);
4352
 
4353
    @method css
4354
    @param {String|Object|Array} urls URL string, request object, or array
4355
        of URLs and/or request objects to load.
4356
    @param {Object} [options] Options for this transaction. See the
4357
        `Y.Get.options` property for a complete list of available options.
4358
    @param {Function} [callback] Callback function to be called on completion.
4359
        This is a general callback and will be called before any more granular
4360
        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4361
        object.
4362
 
4363
        @param {Array|null} callback.err Array of errors that occurred during
4364
            the transaction, or `null` on success.
4365
        @param {Get.Transaction} callback.transaction Transaction object.
4366
 
4367
    @return {Get.Transaction} Transaction object.
4368
    @static
4369
    **/
4370
    css: function (urls, options, callback) {
4371
        return this._load('css', urls, options, callback);
4372
    },
4373
 
4374
    /**
4375
    Loads one or more JavaScript resources.
4376
 
4377
    The _urls_ parameter may be provided as a URL string, a request object,
4378
    or an array of URL strings and/or request objects.
4379
 
4380
    A request object is just an object that contains a `url` property and zero
4381
    or more options that should apply specifically to that request.
4382
    Request-specific options take priority over transaction-level options and
4383
    default options.
4384
 
4385
    URLs may be relative or absolute, and do not have to have the same origin
4386
    as the current page.
4387
 
4388
    The `options` parameter may be omitted completely and a callback passed in
4389
    its place, if desired.
4390
 
4391
    Scripts will be executed in the order they're specified unless the `async`
4392
    option is `true`, in which case they'll be loaded in parallel and executed
4393
    in whatever order they finish loading.
4394
 
4395
    @example
4396
 
4397
        // Load a single JS file and log a message on completion.
4398
        Y.Get.js('foo.js', function (err) {
4399
            if (err) {
4400
            } else {
4401
            }
4402
        });
4403
 
4404
        // Load multiple JS files, execute them in order, and log a message when
4405
        // all have finished loading.
4406
        var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js'];
4407
 
4408
        Y.Get.js(urls, function (err) {
4409
            if (err) {
4410
            } else {
4411
            }
4412
        });
4413
 
4414
        // Specify transaction-level options, which will apply to all requests
4415
        // within the transaction.
4416
        Y.Get.js(urls, {
4417
            attributes: {'class': 'my-js'},
4418
            timeout   : 5000
4419
        });
4420
 
4421
        // Specify per-request options, which override transaction-level and
4422
        // default options.
4423
        Y.Get.js([
4424
            {url: 'foo.js', attributes: {id: 'foo'}},
4425
            {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}}
4426
        ]);
4427
 
4428
    @method js
4429
    @param {String|Object|Array} urls URL string, request object, or array
4430
        of URLs and/or request objects to load.
4431
    @param {Object} [options] Options for this transaction. See the
4432
        `Y.Get.options` property for a complete list of available options.
4433
    @param {Function} [callback] Callback function to be called on completion.
4434
        This is a general callback and will be called before any more granular
4435
        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4436
        object.
4437
 
4438
        @param {Array|null} callback.err Array of errors that occurred during
4439
            the transaction, or `null` on success.
4440
        @param {Get.Transaction} callback.transaction Transaction object.
4441
 
4442
    @return {Get.Transaction} Transaction object.
4443
    @since 3.5.0
4444
    @static
4445
    **/
4446
    js: function (urls, options, callback) {
4447
        return this._load('js', urls, options, callback);
4448
    },
4449
 
4450
    /**
4451
    Loads one or more CSS and/or JavaScript resources in the same transaction.
4452
 
4453
    Use this method when you want to load both CSS and JavaScript in a single
4454
    transaction and be notified when all requested URLs have finished loading,
4455
    regardless of type.
4456
 
4457
    Behavior and options are the same as for the `css()` and `js()` methods. If
4458
    a resource type isn't specified in per-request options or transaction-level
4459
    options, Get will guess the file type based on the URL's extension (`.css`
4460
    or `.js`, with or without a following query string). If the file type can't
4461
    be guessed from the URL, a warning will be logged and Get will assume the
4462
    URL is a JavaScript resource.
4463
 
4464
    @example
4465
 
4466
        // Load both CSS and JS files in a single transaction, and log a message
4467
        // when all files have finished loading.
4468
        Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) {
4469
            if (err) {
4470
            } else {
4471
            }
4472
        });
4473
 
4474
    @method load
4475
    @param {String|Object|Array} urls URL string, request object, or array
4476
        of URLs and/or request objects to load.
4477
    @param {Object} [options] Options for this transaction. See the
4478
        `Y.Get.options` property for a complete list of available options.
4479
    @param {Function} [callback] Callback function to be called on completion.
4480
        This is a general callback and will be called before any more granular
4481
        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4482
        object.
4483
 
4484
        @param {Array|null} err Array of errors that occurred during the
4485
            transaction, or `null` on success.
4486
        @param {Get.Transaction} Transaction object.
4487
 
4488
    @return {Get.Transaction} Transaction object.
4489
    @since 3.5.0
4490
    @static
4491
    **/
4492
    load: function (urls, options, callback) {
4493
        return this._load(null, urls, options, callback);
4494
    },
4495
 
4496
    // -- Protected Methods ----------------------------------------------------
4497
 
4498
    /**
4499
    Triggers an automatic purge if the purge threshold has been reached.
4500
 
4501
    @method _autoPurge
4502
    @param {Number} threshold Purge threshold to use, in milliseconds.
4503
    @protected
4504
    @since 3.5.0
4505
    @static
4506
    **/
4507
    _autoPurge: function (threshold) {
4508
        if (threshold && this._purgeNodes.length >= threshold) {
4509
            this._purge(this._purgeNodes);
4510
        }
4511
    },
4512
 
4513
    /**
4514
    Populates the `_env` property with information about the current
4515
    environment.
4516
 
4517
    @method _getEnv
4518
    @return {Object} Environment information.
4519
    @protected
4520
    @since 3.5.0
4521
    @static
4522
    **/
4523
    _getEnv: function () {
4524
        var doc = Y.config.doc,
4525
            ua  = Y.UA;
4526
 
4527
        // Note: some of these checks require browser sniffs since it's not
4528
        // feasible to load test files on every pageview just to perform a
4529
        // feature test. I'm sorry if this makes you sad.
4530
        return (this._env = {
4531
 
4532
            // True if this is a browser that supports disabling async mode on
4533
            // dynamically created script nodes. See
4534
            // https://developer.mozilla.org/En/HTML/Element/Script#Attributes
4535
 
4536
            // IE10 doesn't return true for the MDN feature test, so setting it explicitly,
4537
            // because it is async by default, and allows you to disable async by setting it to false
4538
            async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10),
4539
 
4540
            // True if this browser fires an event when a dynamically injected
4541
            // link node fails to load. This is currently true for Firefox 9+
4542
            // and WebKit 535.24+
4543
            cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0,
4544
 
4545
            // True if this browser fires an event when a dynamically injected
4546
            // link node finishes loading. This is currently true for IE, Opera,
4547
            // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the
4548
            // DOM 0 "onload" event, but not "load". All versions of IE fire
4549
            // "onload".
4550
            // davglass: Seems that Chrome on Android needs this to be false.
4551
            cssLoad: (
4552
                    (!ua.gecko && !ua.webkit) || ua.gecko >= 9 ||
4553
                    ua.compareVersions(ua.webkit, 535.24) >= 0
4554
                ) && !(ua.chrome && ua.chrome <= 18),
4555
 
4556
            // True if this browser preserves script execution order while
4557
            // loading scripts in parallel as long as the script node's `async`
4558
            // attribute is set to false to explicitly disable async execution.
4559
            preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10))
4560
        });
4561
    },
4562
 
4563
    _getTransaction: function (urls, options) {
4564
        var requests = [],
4565
            i, len, req, url;
4566
 
4567
        if (!Lang.isArray(urls)) {
4568
            urls = [urls];
4569
        }
4570
 
4571
        options = Y.merge(this.options, options);
4572
 
4573
        // Clone the attributes object so we don't end up modifying it by ref.
4574
        options.attributes = Y.merge(this.options.attributes,
4575
                options.attributes);
4576
 
4577
        for (i = 0, len = urls.length; i < len; ++i) {
4578
            url = urls[i];
4579
            req = {attributes: {}};
4580
 
4581
            // If `url` is a string, we create a URL object for it, then mix in
4582
            // global options and request-specific options. If it's an object
4583
            // with a "url" property, we assume it's a request object containing
4584
            // URL-specific options.
4585
            if (typeof url === 'string') {
4586
                req.url = url;
4587
            } else if (url.url) {
4588
                // URL-specific options override both global defaults and
4589
                // request-specific options.
4590
                Y.mix(req, url, false, null, 0, true);
4591
                url = url.url; // Make url a string so we can use it later.
4592
            } else {
4593
                continue;
4594
            }
4595
 
4596
            Y.mix(req, options, false, null, 0, true);
4597
 
4598
            // If we didn't get an explicit type for this URL either in the
4599
            // request options or the URL-specific options, try to determine
4600
            // one from the file extension.
4601
            if (!req.type) {
4602
                if (this.REGEX_CSS.test(url)) {
4603
                    req.type = 'css';
4604
                } else {
4605
                    if (!this.REGEX_JS.test(url)) {
4606
                    }
4607
 
4608
                    req.type = 'js';
4609
                }
4610
            }
4611
 
4612
            // Mix in type-specific default options, but don't overwrite any
4613
            // options that have already been set.
4614
            Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions,
4615
                false, null, 0, true);
4616
 
4617
            // Give the node an id attribute if it doesn't already have one.
4618
            req.attributes.id || (req.attributes.id = Y.guid());
4619
 
4620
            // Backcompat for <3.5.0 behavior.
4621
            if (req.win) {
4622
                req.doc = req.win.document;
4623
            } else {
4624
                req.win = req.doc.defaultView || req.doc.parentWindow;
4625
            }
4626
 
4627
            if (req.charset) {
4628
                req.attributes.charset = req.charset;
4629
            }
4630
 
4631
            requests.push(req);
4632
        }
4633
 
4634
        return new Transaction(requests, options);
4635
    },
4636
 
4637
    _load: function (type, urls, options, callback) {
4638
        var transaction;
4639
 
4640
        // Allow callback as third param.
4641
        if (typeof options === 'function') {
4642
            callback = options;
4643
            options  = {};
4644
        }
4645
 
4646
        options || (options = {});
4647
        options.type = type;
4648
 
4649
        options._onFinish = Get._onTransactionFinish;
4650
 
4651
        if (!this._env) {
4652
            this._getEnv();
4653
        }
4654
 
4655
        transaction = this._getTransaction(urls, options);
4656
 
4657
        this._queue.push({
4658
            callback   : callback,
4659
            transaction: transaction
4660
        });
4661
 
4662
        this._next();
4663
 
4664
        return transaction;
4665
    },
4666
 
4667
    _onTransactionFinish : function() {
4668
        Get._pending = null;
4669
        Get._next();
4670
    },
4671
 
4672
    _next: function () {
4673
        var item;
4674
 
4675
        if (this._pending) {
4676
            return;
4677
        }
4678
 
4679
        item = this._queue.shift();
4680
 
4681
        if (item) {
4682
            this._pending = item;
4683
            item.transaction.execute(item.callback);
4684
        }
4685
    },
4686
 
4687
    _purge: function (nodes) {
4688
        var purgeNodes    = this._purgeNodes,
4689
            isTransaction = nodes !== purgeNodes,
4690
            index, node;
4691
 
4692
        while (node = nodes.pop()) { // assignment
4693
            // Don't purge nodes that haven't finished loading (or errored out),
4694
            // since this can hang the transaction.
4695
            if (!node._yuiget_finished) {
4696
                continue;
4697
            }
4698
 
4699
            node.parentNode && node.parentNode.removeChild(node);
4700
 
4701
            // If this is a transaction-level purge and this node also exists in
4702
            // the Get-level _purgeNodes array, we need to remove it from
4703
            // _purgeNodes to avoid creating a memory leak. The indexOf lookup
4704
            // sucks, but until we get WeakMaps, this is the least troublesome
4705
            // way to do this (we can't just hold onto node ids because they may
4706
            // not be in the same document).
4707
            if (isTransaction) {
4708
                index = Y.Array.indexOf(purgeNodes, node);
4709
 
4710
                if (index > -1) {
4711
                    purgeNodes.splice(index, 1);
4712
                }
4713
            }
4714
        }
4715
    }
4716
};
4717
 
4718
/**
4719
Alias for `js()`.
4720
 
4721
@method script
4722
@static
4723
**/
4724
Get.script = Get.js;
4725
 
4726
/**
4727
Represents a Get transaction, which may contain requests for one or more JS or
4728
CSS files.
4729
 
4730
This class should not be instantiated manually. Instances will be created and
4731
returned as needed by Y.Get's `css()`, `js()`, and `load()` methods.
4732
 
4733
@class Get.Transaction
4734
@constructor
4735
@since 3.5.0
4736
**/
4737
Get.Transaction = Transaction = function (requests, options) {
4738
    var self = this;
4739
 
4740
    self.id       = Transaction._lastId += 1;
4741
    self.data     = options.data;
4742
    self.errors   = [];
4743
    self.nodes    = [];
4744
    self.options  = options;
4745
    self.requests = requests;
4746
 
4747
    self._callbacks = []; // callbacks to call after execution finishes
4748
    self._queue     = [];
4749
    self._reqsWaiting   = 0;
4750
 
4751
    // Deprecated pre-3.5.0 properties.
4752
    self.tId = self.id; // Use `id` instead.
4753
    self.win = options.win || Y.config.win;
4754
};
4755
 
4756
/**
4757
Arbitrary data object associated with this transaction.
4758
 
4759
This object comes from the options passed to `Get.css()`, `Get.js()`, or
4760
`Get.load()`, and will be `undefined` if no data object was specified.
4761
 
4762
@property {Object} data
4763
**/
4764
 
4765
/**
4766
Array of errors that have occurred during this transaction, if any. Each error
4767
object has the following properties:
4768
`errors.error`: Error message.
4769
`errors.request`: Request object related to the error.
4770
 
4771
@since 3.5.0
4772
@property {Object[]} errors
4773
**/
4774
 
4775
/**
4776
Numeric id for this transaction, unique among all transactions within the same
4777
YUI sandbox in the current pageview.
4778
 
4779
@property {Number} id
4780
@since 3.5.0
4781
**/
4782
 
4783
/**
4784
HTMLElement nodes (native ones, not YUI Node instances) that have been inserted
4785
during the current transaction.
4786
 
4787
@property {HTMLElement[]} nodes
4788
**/
4789
 
4790
/**
4791
Options associated with this transaction.
4792
 
4793
See `Get.options` for the full list of available options.
4794
 
4795
@property {Object} options
4796
@since 3.5.0
4797
**/
4798
 
4799
/**
4800
Request objects contained in this transaction. Each request object represents
4801
one CSS or JS URL that will be (or has been) requested and loaded into the page.
4802
 
4803
@property {Object} requests
4804
@since 3.5.0
4805
**/
4806
 
4807
/**
4808
Id of the most recent transaction.
4809
 
4810
@property _lastId
4811
@type Number
4812
@protected
4813
@static
4814
**/
4815
Transaction._lastId = 0;
4816
 
4817
Transaction.prototype = {
4818
    // -- Public Properties ----------------------------------------------------
4819
 
4820
    /**
4821
    Current state of this transaction. One of "new", "executing", or "done".
4822
 
4823
    @property _state
4824
    @type String
4825
    @protected
4826
    **/
4827
    _state: 'new', // "new", "executing", or "done"
4828
 
4829
    // -- Public Methods -------------------------------------------------------
4830
 
4831
    /**
4832
    Aborts this transaction.
4833
 
4834
    This will cause the transaction's `onFailure` callback to be called and
4835
    will prevent any new script and link nodes from being added to the document,
4836
    but any resources that have already been requested will continue loading
4837
    (there's no safe way to prevent this, unfortunately).
4838
 
4839
    @method abort
4840
    @param {String} [msg="Aborted."] Optional message to use in the `errors`
4841
        array describing why the transaction was aborted.
4842
    **/
4843
    abort: function (msg) {
4844
        this._pending    = null;
4845
        this._pendingCSS = null;
4846
        this._pollTimer  = clearTimeout(this._pollTimer);
4847
        this._queue      = [];
4848
        this._reqsWaiting    = 0;
4849
 
4850
        this.errors.push({error: msg || 'Aborted'});
4851
        this._finish();
4852
    },
4853
 
4854
    /**
4855
    Begins execting the transaction.
4856
 
4857
    There's usually no reason to call this manually, since Get will call it
4858
    automatically when other pending transactions have finished. If you really
4859
    want to execute your transaction before Get does, you can, but be aware that
4860
    this transaction's scripts may end up executing before the scripts in other
4861
    pending transactions.
4862
 
4863
    If the transaction is already executing, the specified callback (if any)
4864
    will be queued and called after execution finishes. If the transaction has
4865
    already finished, the callback will be called immediately (the transaction
4866
    will not be executed again).
4867
 
4868
    @method execute
4869
    @param {Function} callback Callback function to execute after all requests
4870
        in the transaction are complete, or after the transaction is aborted.
4871
    **/
4872
    execute: function (callback) {
4873
        var self     = this,
4874
            requests = self.requests,
4875
            state    = self._state,
4876
            i, len, queue, req;
4877
 
4878
        if (state === 'done') {
4879
            callback && callback(self.errors.length ? self.errors : null, self);
4880
            return;
4881
        } else {
4882
            callback && self._callbacks.push(callback);
4883
 
4884
            if (state === 'executing') {
4885
                return;
4886
            }
4887
        }
4888
 
4889
        self._state = 'executing';
4890
        self._queue = queue = [];
4891
 
4892
        if (self.options.timeout) {
4893
            self._timeout = setTimeout(function () {
4894
                self.abort('Timeout');
4895
            }, self.options.timeout);
4896
        }
4897
 
4898
        self._reqsWaiting = requests.length;
4899
 
4900
        for (i = 0, len = requests.length; i < len; ++i) {
4901
            req = requests[i];
4902
 
4903
            if (req.async || req.type === 'css') {
4904
                // No need to queue CSS or fully async JS.
4905
                self._insert(req);
4906
            } else {
4907
                queue.push(req);
4908
            }
4909
        }
4910
 
4911
        self._next();
4912
    },
4913
 
4914
    /**
4915
    Manually purges any `<script>` or `<link>` nodes this transaction has
4916
    created.
4917
 
4918
    Be careful when purging a transaction that contains CSS requests, since
4919
    removing `<link>` nodes will also remove any styles they applied.
4920
 
4921
    @method purge
4922
    **/
4923
    purge: function () {
4924
        Get._purge(this.nodes);
4925
    },
4926
 
4927
    // -- Protected Methods ----------------------------------------------------
4928
    _createNode: function (name, attrs, doc) {
4929
        var node = doc.createElement(name),
4930
            attr, testEl;
4931
 
4932
        if (!CUSTOM_ATTRS) {
4933
            // IE6 and IE7 expect property names rather than attribute names for
4934
            // certain attributes. Rather than sniffing, we do a quick feature
4935
            // test the first time _createNode() runs to determine whether we
4936
            // need to provide a workaround.
4937
            testEl = doc.createElement('div');
4938
            testEl.setAttribute('class', 'a');
4939
 
4940
            CUSTOM_ATTRS = testEl.className === 'a' ? {} : {
4941
                'for'  : 'htmlFor',
4942
                'class': 'className'
4943
            };
4944
        }
4945
 
4946
        for (attr in attrs) {
4947
            if (attrs.hasOwnProperty(attr)) {
4948
                node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]);
4949
            }
4950
        }
4951
 
4952
        return node;
4953
    },
4954
 
4955
    _finish: function () {
4956
        var errors  = this.errors.length ? this.errors : null,
4957
            options = this.options,
4958
            thisObj = options.context || this,
4959
            data, i, len;
4960
 
4961
        if (this._state === 'done') {
4962
            return;
4963
        }
4964
 
4965
        this._state = 'done';
4966
 
4967
        for (i = 0, len = this._callbacks.length; i < len; ++i) {
4968
            this._callbacks[i].call(thisObj, errors, this);
4969
        }
4970
 
4971
        data = this._getEventData();
4972
 
4973
        if (errors) {
4974
            if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') {
4975
                options.onTimeout.call(thisObj, data);
4976
            }
4977
 
4978
            if (options.onFailure) {
4979
                options.onFailure.call(thisObj, data);
4980
            }
4981
        } else if (options.onSuccess) {
4982
            options.onSuccess.call(thisObj, data);
4983
        }
4984
 
4985
        if (options.onEnd) {
4986
            options.onEnd.call(thisObj, data);
4987
        }
4988
 
4989
        if (options._onFinish) {
4990
            options._onFinish();
4991
        }
4992
    },
4993
 
4994
    _getEventData: function (req) {
4995
        if (req) {
4996
            // This merge is necessary for backcompat. I hate it.
4997
            return Y.merge(this, {
4998
                abort  : this.abort, // have to copy these because the prototype isn't preserved
4999
                purge  : this.purge,
5000
                request: req,
5001
                url    : req.url,
5002
                win    : req.win
5003
            });
5004
        } else {
5005
            return this;
5006
        }
5007
    },
5008
 
5009
    _getInsertBefore: function (req) {
5010
        var doc = req.doc,
5011
            el  = req.insertBefore,
5012
            cache, docStamp;
5013
 
5014
        if (el) {
5015
            return typeof el === 'string' ? doc.getElementById(el) : el;
5016
        }
5017
 
5018
        cache    = Get._insertCache;
5019
        docStamp = Y.stamp(doc);
5020
 
5021
        if ((el = cache[docStamp])) { // assignment
5022
            return el;
5023
        }
5024
 
5025
        // Inserting before a <base> tag apparently works around an IE bug
5026
        // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what
5027
        // bug that is, exactly. Better safe than sorry?
5028
        if ((el = doc.getElementsByTagName('base')[0])) { // assignment
5029
            return (cache[docStamp] = el);
5030
        }
5031
 
5032
        // Look for a <head> element.
5033
        el = doc.head || doc.getElementsByTagName('head')[0];
5034
 
5035
        if (el) {
5036
            // Create a marker node at the end of <head> to use as an insertion
5037
            // point. Inserting before this node will ensure that all our CSS
5038
            // gets inserted in the correct order, to maintain style precedence.
5039
            el.appendChild(doc.createTextNode(''));
5040
            return (cache[docStamp] = el.lastChild);
5041
        }
5042
 
5043
        // If all else fails, just insert before the first script node on the
5044
        // page, which is virtually guaranteed to exist.
5045
        return (cache[docStamp] = doc.getElementsByTagName('script')[0]);
5046
    },
5047
 
5048
    _insert: function (req) {
5049
        var env          = Get._env,
5050
            insertBefore = this._getInsertBefore(req),
5051
            isScript     = req.type === 'js',
5052
            node         = req.node,
5053
            self         = this,
5054
            ua           = Y.UA,
5055
            cssTimeout, nodeType;
5056
 
5057
        if (!node) {
5058
            if (isScript) {
5059
                nodeType = 'script';
5060
            } else if (!env.cssLoad && ua.gecko) {
5061
                nodeType = 'style';
5062
            } else {
5063
                nodeType = 'link';
5064
            }
5065
 
5066
            node = req.node = this._createNode(nodeType, req.attributes,
5067
                req.doc);
5068
        }
5069
 
5070
        function onError() {
5071
            self._progress('Failed to load ' + req.url, req);
5072
        }
5073
 
5074
        function onLoad() {
5075
            if (cssTimeout) {
5076
                clearTimeout(cssTimeout);
5077
            }
5078
 
5079
            self._progress(null, req);
5080
        }
5081
 
5082
        // Deal with script asynchronicity.
5083
        if (isScript) {
5084
            node.setAttribute('src', req.url);
5085
 
5086
            if (req.async) {
5087
                // Explicitly indicate that we want the browser to execute this
5088
                // script asynchronously. This is necessary for older browsers
5089
                // like Firefox <4.
5090
                node.async = true;
5091
            } else {
5092
                if (env.async) {
5093
                    // This browser treats injected scripts as async by default
5094
                    // (standard HTML5 behavior) but asynchronous loading isn't
5095
                    // desired, so tell the browser not to mark this script as
5096
                    // async.
5097
                    node.async = false;
5098
                }
5099
 
5100
                // If this browser doesn't preserve script execution order based
5101
                // on insertion order, we'll need to avoid inserting other
5102
                // scripts until this one finishes loading.
5103
                if (!env.preservesScriptOrder) {
5104
                    this._pending = req;
5105
                }
5106
            }
5107
        } else {
5108
            if (!env.cssLoad && ua.gecko) {
5109
                // In Firefox <9, we can import the requested URL into a <style>
5110
                // node and poll for the existence of node.sheet.cssRules. This
5111
                // gives us a reliable way to determine CSS load completion that
5112
                // also works for cross-domain stylesheets.
5113
                //
5114
                // Props to Zach Leatherman for calling my attention to this
5115
                // technique.
5116
                node.innerHTML = (req.attributes.charset ?
5117
                    '@charset "' + req.attributes.charset + '";' : '') +
5118
                    '@import "' + req.url + '";';
5119
            } else {
5120
                node.setAttribute('href', req.url);
5121
            }
5122
        }
5123
 
5124
        // Inject the node.
5125
        if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) {
5126
            // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode.
5127
            node.onreadystatechange = function () {
5128
                if (/loaded|complete/.test(node.readyState)) {
5129
                    node.onreadystatechange = null;
5130
                    onLoad();
5131
                }
5132
            };
5133
        } else if (!isScript && !env.cssLoad) {
5134
            // CSS on Firefox <9 or WebKit.
5135
            this._poll(req);
5136
        } else {
5137
            // Script or CSS on everything else. Using DOM 0 events because that
5138
            // evens the playing field with older IEs.
5139
 
5140
            if (ua.ie >= 10) {
5141
 
5142
                // We currently need to introduce a timeout for IE10, since it
5143
                // calls onerror/onload synchronously for 304s - messing up existing
5144
                // program flow.
5145
 
5146
                // Remove this block if the following bug gets fixed by GA
5147
                /*jshint maxlen: 1500 */
5148
                // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload
5149
                node.onerror = function() { setTimeout(onError, 0); };
5150
                node.onload  = function() { setTimeout(onLoad, 0); };
5151
            } else {
5152
                node.onerror = onError;
5153
                node.onload  = onLoad;
5154
            }
5155
 
5156
            // If this browser doesn't fire an event when CSS fails to load,
5157
            // fail after a timeout to avoid blocking the transaction queue.
5158
            if (!env.cssFail && !isScript) {
5159
                cssTimeout = setTimeout(onError, req.timeout || 3000);
5160
            }
5161
        }
5162
 
5163
        this.nodes.push(node);
5164
        insertBefore.parentNode.insertBefore(node, insertBefore);
5165
    },
5166
 
5167
    _next: function () {
5168
        if (this._pending) {
5169
            return;
5170
        }
5171
 
5172
        // If there are requests in the queue, insert the next queued request.
5173
        // Otherwise, if we're waiting on already-inserted requests to finish,
5174
        // wait longer. If there are no queued requests and we're not waiting
5175
        // for anything to load, then we're done!
5176
        if (this._queue.length) {
5177
            this._insert(this._queue.shift());
5178
        } else if (!this._reqsWaiting) {
5179
            this._finish();
5180
        }
5181
    },
5182
 
5183
    _poll: function (newReq) {
5184
        var self       = this,
5185
            pendingCSS = self._pendingCSS,
5186
            isWebKit   = Y.UA.webkit,
5187
            i, hasRules, j, nodeHref, req, sheets;
5188
 
5189
        if (newReq) {
5190
            pendingCSS || (pendingCSS = self._pendingCSS = []);
5191
            pendingCSS.push(newReq);
5192
 
5193
            if (self._pollTimer) {
5194
                // A poll timeout is already pending, so no need to create a
5195
                // new one.
5196
                return;
5197
            }
5198
        }
5199
 
5200
        self._pollTimer = null;
5201
 
5202
        // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s
5203
        // will still be treated as a success. There's no good workaround for
5204
        // this.
5205
 
5206
        for (i = 0; i < pendingCSS.length; ++i) {
5207
            req = pendingCSS[i];
5208
 
5209
            if (isWebKit) {
5210
                // Look for a stylesheet matching the pending URL.
5211
                sheets   = req.doc.styleSheets;
5212
                j        = sheets.length;
5213
                nodeHref = req.node.href;
5214
 
5215
                while (--j >= 0) {
5216
                    if (sheets[j].href === nodeHref) {
5217
                        pendingCSS.splice(i, 1);
5218
                        i -= 1;
5219
                        self._progress(null, req);
5220
                        break;
5221
                    }
5222
                }
5223
            } else {
5224
                // Many thanks to Zach Leatherman for calling my attention to
5225
                // the @import-based cross-domain technique used here, and to
5226
                // Oleg Slobodskoi for an earlier same-domain implementation.
5227
                //
5228
                // See Zach's blog for more details:
5229
                // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
5230
                try {
5231
                    // We don't really need to store this value since we never
5232
                    // use it again, but if we don't store it, Closure Compiler
5233
                    // assumes the code is useless and removes it.
5234
                    hasRules = !!req.node.sheet.cssRules;
5235
 
5236
                    // If we get here, the stylesheet has loaded.
5237
                    pendingCSS.splice(i, 1);
5238
                    i -= 1;
5239
                    self._progress(null, req);
5240
                } catch (ex) {
5241
                    // An exception means the stylesheet is still loading.
5242
                }
5243
            }
5244
        }
5245
 
5246
        if (pendingCSS.length) {
5247
            self._pollTimer = setTimeout(function () {
5248
                self._poll.call(self);
5249
            }, self.options.pollInterval);
5250
        }
5251
    },
5252
 
5253
    _progress: function (err, req) {
5254
        var options = this.options;
5255
 
5256
        if (err) {
5257
            req.error = err;
5258
 
5259
            this.errors.push({
5260
                error  : err,
5261
                request: req
5262
            });
5263
 
5264
        }
5265
 
5266
        req.node._yuiget_finished = req.finished = true;
5267
 
5268
        if (options.onProgress) {
5269
            options.onProgress.call(options.context || this,
5270
                this._getEventData(req));
5271
        }
5272
 
5273
        if (req.autopurge) {
5274
            // Pre-3.5.0 Get always excludes the most recent node from an
5275
            // autopurge. I find this odd, but I'm keeping that behavior for
5276
            // the sake of backcompat.
5277
            Get._autoPurge(this.options.purgethreshold);
5278
            Get._purgeNodes.push(req.node);
5279
        }
5280
 
5281
        if (this._pending === req) {
5282
            this._pending = null;
5283
        }
5284
 
5285
        this._reqsWaiting -= 1;
5286
 
5287
        this._next();
5288
    }
5289
};
5290
 
5291
 
5292
}, '3.18.1', {"requires": ["yui-base"]});
5293
YUI.add('features', function (Y, NAME) {
5294
 
5295
var feature_tests = {};
5296
 
5297
/**
5298
Contains the core of YUI's feature test architecture.
5299
@module features
5300
*/
5301
 
5302
/**
5303
* Feature detection
5304
* @class Features
5305
* @static
5306
*/
5307
 
5308
Y.mix(Y.namespace('Features'), {
5309
 
5310
    /**
5311
    * Object hash of all registered feature tests
5312
    * @property tests
5313
    * @type Object
5314
    */
5315
    tests: feature_tests,
5316
 
5317
    /**
5318
    * Add a test to the system
5319
    *
5320
    *   ```
5321
    *   Y.Features.add("load", "1", {});
5322
    *   ```
5323
    *
5324
    * @method add
5325
    * @param {String} cat The category, right now only 'load' is supported
5326
    * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
5327
    * @param {Object} o Object containing test properties
5328
    * @param {String} o.name The name of the test
5329
    * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
5330
    * @param {String} o.trigger The module that triggers this test.
5331
    */
5332
    add: function(cat, name, o) {
5333
        feature_tests[cat] = feature_tests[cat] || {};
5334
        feature_tests[cat][name] = o;
5335
    },
5336
    /**
5337
    * Execute all tests of a given category and return the serialized results
5338
    *
5339
    *   ```
5340
    *   caps=1:1;2:1;3:0
5341
    *   ```
5342
    * @method all
5343
    * @param {String} cat The category to execute
5344
    * @param {Array} args The arguments to pass to the test function
5345
    * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
5346
    */
5347
    all: function(cat, args) {
5348
        var cat_o = feature_tests[cat],
5349
            // results = {};
5350
            result = [];
5351
        if (cat_o) {
5352
            Y.Object.each(cat_o, function(v, k) {
5353
                result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
5354
            });
5355
        }
5356
 
5357
        return (result.length) ? result.join(';') : '';
5358
    },
5359
    /**
5360
    * Run a specific test and return a Boolean response.
5361
    *
5362
    *   ```
5363
    *   Y.Features.test("load", "1");
5364
    *   ```
5365
    *
5366
    * @method test
5367
    * @param {String} cat The category of the test to run
5368
    * @param {String} name The name of the test to run
5369
    * @param {Array} args The arguments to pass to the test function
5370
    * @return {Boolean} True or false if the test passed/failed.
5371
    */
5372
    test: function(cat, name, args) {
5373
        args = args || [];
5374
        var result, ua, test,
5375
            cat_o = feature_tests[cat],
5376
            feature = cat_o && cat_o[name];
5377
 
5378
        if (!feature) {
5379
        } else {
5380
 
5381
            result = feature.result;
5382
 
5383
            if (Y.Lang.isUndefined(result)) {
5384
 
5385
                ua = feature.ua;
5386
                if (ua) {
5387
                    result = (Y.UA[ua]);
5388
                }
5389
 
5390
                test = feature.test;
5391
                if (test && ((!ua) || result)) {
5392
                    result = test.apply(Y, args);
5393
                }
5394
 
5395
                feature.result = result;
5396
            }
5397
        }
5398
 
5399
        return result;
5400
    }
5401
});
5402
 
5403
// Y.Features.add("load", "1", {});
5404
// Y.Features.test("load", "1");
5405
// caps=1:1;2:0;3:1;
5406
 
5407
/* This file is auto-generated by (yogi loader --yes --mix --start ../) */
5408
/*jshint maxlen:900, eqeqeq: false */
5409
var add = Y.Features.add;
5410
// app-transitions-native
5411
add('load', '0', {
5412
    "name": "app-transitions-native",
5413
    "test": function (Y) {
5414
    var doc  = Y.config.doc,
5415
        node = doc ? doc.documentElement : null;
5416
 
5417
    if (node && node.style) {
5418
        return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
5419
    }
5420
 
5421
    return false;
5422
},
5423
    "trigger": "app-transitions"
5424
});
5425
// autocomplete-list-keys
5426
add('load', '1', {
5427
    "name": "autocomplete-list-keys",
5428
    "test": function (Y) {
5429
    // Only add keyboard support to autocomplete-list if this doesn't appear to
5430
    // be an iOS or Android-based mobile device.
5431
    //
5432
    // There's currently no feasible way to actually detect whether a device has
5433
    // a hardware keyboard, so this sniff will have to do. It can easily be
5434
    // overridden by manually loading the autocomplete-list-keys module.
5435
    //
5436
    // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
5437
    // doesn't fire the keyboard events used by AutoCompleteList, so there's
5438
    // no point loading the -keys module even when a bluetooth keyboard may be
5439
    // available.
5440
    return !(Y.UA.ios || Y.UA.android);
5441
},
5442
    "trigger": "autocomplete-list"
5443
});
5444
// dd-gestures
5445
add('load', '2', {
5446
    "name": "dd-gestures",
5447
    "trigger": "dd-drag",
5448
    "ua": "touchEnabled"
5449
});
5450
// dom-style-ie
5451
add('load', '3', {
5452
    "name": "dom-style-ie",
5453
    "test": function (Y) {
5454
 
5455
    var testFeature = Y.Features.test,
5456
        addFeature = Y.Features.add,
5457
        WINDOW = Y.config.win,
5458
        DOCUMENT = Y.config.doc,
5459
        DOCUMENT_ELEMENT = 'documentElement',
5460
        ret = false;
5461
 
5462
    addFeature('style', 'computedStyle', {
5463
        test: function() {
5464
            return WINDOW && 'getComputedStyle' in WINDOW;
5465
        }
5466
    });
5467
 
5468
    addFeature('style', 'opacity', {
5469
        test: function() {
5470
            return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
5471
        }
5472
    });
5473
 
5474
    ret =  (!testFeature('style', 'opacity') &&
5475
            !testFeature('style', 'computedStyle'));
5476
 
5477
    return ret;
5478
},
5479
    "trigger": "dom-style"
5480
});
5481
// editor-para-ie
5482
add('load', '4', {
5483
    "name": "editor-para-ie",
5484
    "trigger": "editor-para",
5485
    "ua": "ie",
5486
    "when": "instead"
5487
});
5488
// event-base-ie
5489
add('load', '5', {
5490
    "name": "event-base-ie",
5491
    "test": function(Y) {
5492
    var imp = Y.config.doc && Y.config.doc.implementation;
5493
    return (imp && (!imp.hasFeature('Events', '2.0')));
5494
},
5495
    "trigger": "node-base"
5496
});
5497
// graphics-canvas
5498
add('load', '6', {
5499
    "name": "graphics-canvas",
5500
    "test": function(Y) {
5501
    var DOCUMENT = Y.config.doc,
5502
        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
5503
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5504
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5505
    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
5506
},
5507
    "trigger": "graphics"
5508
});
5509
// graphics-canvas-default
5510
add('load', '7', {
5511
    "name": "graphics-canvas-default",
5512
    "test": function(Y) {
5513
    var DOCUMENT = Y.config.doc,
5514
        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
5515
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5516
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5517
    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
5518
},
5519
    "trigger": "graphics"
5520
});
5521
// graphics-svg
5522
add('load', '8', {
5523
    "name": "graphics-svg",
5524
    "test": function(Y) {
5525
    var DOCUMENT = Y.config.doc,
5526
        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
5527
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5528
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5529
 
5530
    return svg && (useSVG || !canvas);
5531
},
5532
    "trigger": "graphics"
5533
});
5534
// graphics-svg-default
5535
add('load', '9', {
5536
    "name": "graphics-svg-default",
5537
    "test": function(Y) {
5538
    var DOCUMENT = Y.config.doc,
5539
        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
5540
		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5541
        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5542
 
5543
    return svg && (useSVG || !canvas);
5544
},
5545
    "trigger": "graphics"
5546
});
5547
// graphics-vml
5548
add('load', '10', {
5549
    "name": "graphics-vml",
5550
    "test": function(Y) {
5551
    var DOCUMENT = Y.config.doc,
5552
		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5553
    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
5554
},
5555
    "trigger": "graphics"
5556
});
5557
// graphics-vml-default
5558
add('load', '11', {
5559
    "name": "graphics-vml-default",
5560
    "test": function(Y) {
5561
    var DOCUMENT = Y.config.doc,
5562
		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5563
    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
5564
},
5565
    "trigger": "graphics"
5566
});
5567
// history-hash-ie
5568
add('load', '12', {
5569
    "name": "history-hash-ie",
5570
    "test": function (Y) {
5571
    var docMode = Y.config.doc && Y.config.doc.documentMode;
5572
 
5573
    return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
5574
            !docMode || docMode < 8);
5575
},
5576
    "trigger": "history-hash"
5577
});
5578
// io-nodejs
5579
add('load', '13', {
5580
    "name": "io-nodejs",
5581
    "trigger": "io-base",
5582
    "ua": "nodejs"
5583
});
5584
// json-parse-shim
5585
add('load', '14', {
5586
    "name": "json-parse-shim",
5587
    "test": function (Y) {
5588
    var _JSON = Y.config.global.JSON,
5589
        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
5590
        nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
5591
 
5592
    function workingNative( k, v ) {
5593
        return k === "ok" ? true : v;
5594
    }
5595
 
5596
    // Double check basic functionality.  This is mainly to catch early broken
5597
    // implementations of the JSON API in Firefox 3.1 beta1 and beta2
5598
    if ( nativeSupport ) {
5599
        try {
5600
            nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
5601
        }
5602
        catch ( e ) {
5603
            nativeSupport = false;
5604
        }
5605
    }
5606
 
5607
    return !nativeSupport;
5608
},
5609
    "trigger": "json-parse"
5610
});
5611
// json-stringify-shim
5612
add('load', '15', {
5613
    "name": "json-stringify-shim",
5614
    "test": function (Y) {
5615
    var _JSON = Y.config.global.JSON,
5616
        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
5617
        nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
5618
 
5619
    // Double check basic native functionality.  This is primarily to catch broken
5620
    // early JSON API implementations in Firefox 3.1 beta1 and beta2.
5621
    if ( nativeSupport ) {
5622
        try {
5623
            nativeSupport = ( '0' === Native.stringify(0) );
5624
        } catch ( e ) {
5625
            nativeSupport = false;
5626
        }
5627
    }
5628
 
5629
 
5630
    return !nativeSupport;
5631
},
5632
    "trigger": "json-stringify"
5633
});
5634
// scrollview-base-ie
5635
add('load', '16', {
5636
    "name": "scrollview-base-ie",
5637
    "trigger": "scrollview-base",
5638
    "ua": "ie"
5639
});
5640
// selector-css2
5641
add('load', '17', {
5642
    "name": "selector-css2",
5643
    "test": function (Y) {
5644
    var DOCUMENT = Y.config.doc,
5645
        ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
5646
 
5647
    return ret;
5648
},
5649
    "trigger": "selector"
5650
});
5651
// transition-timer
5652
add('load', '18', {
5653
    "name": "transition-timer",
5654
    "test": function (Y) {
5655
    var DOCUMENT = Y.config.doc,
5656
        node = (DOCUMENT) ? DOCUMENT.documentElement: null,
5657
        ret = true;
5658
 
5659
    if (node && node.style) {
5660
        ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
5661
    }
5662
 
5663
    return ret;
5664
},
5665
    "trigger": "transition"
5666
});
5667
// widget-base-ie
5668
add('load', '19', {
5669
    "name": "widget-base-ie",
5670
    "trigger": "widget-base",
5671
    "ua": "ie"
5672
});
5673
// yql-jsonp
5674
add('load', '20', {
5675
    "name": "yql-jsonp",
5676
    "test": function (Y) {
5677
    /* Only load the JSONP module when not in nodejs or winjs
5678
    TODO Make the winjs module a CORS module
5679
    */
5680
    return (!Y.UA.nodejs && !Y.UA.winjs);
5681
},
5682
    "trigger": "yql"
5683
});
5684
// yql-nodejs
5685
add('load', '21', {
5686
    "name": "yql-nodejs",
5687
    "trigger": "yql",
5688
    "ua": "nodejs"
5689
});
5690
// yql-winjs
5691
add('load', '22', {
5692
    "name": "yql-winjs",
5693
    "trigger": "yql",
5694
    "ua": "winjs"
5695
});
5696
 
5697
}, '3.18.1', {"requires": ["yui-base"]});
5698
YUI.add('intl-base', function (Y, NAME) {
5699
 
5700
/**
5701
 * The Intl utility provides a central location for managing sets of
5702
 * localized resources (strings and formatting patterns).
5703
 *
5704
 * @class Intl
5705
 * @uses EventTarget
5706
 * @static
5707
 */
5708
 
5709
var SPLIT_REGEX = /[, ]/;
5710
 
5711
Y.mix(Y.namespace('Intl'), {
5712
 
5713
 /**
5714
    * Returns the language among those available that
5715
    * best matches the preferred language list, using the Lookup
5716
    * algorithm of BCP 47.
5717
    * If none of the available languages meets the user's preferences,
5718
    * then "" is returned.
5719
    * Extended language ranges are not supported.
5720
    *
5721
    * @method lookupBestLang
5722
    * @param {String[] | String} preferredLanguages The list of preferred
5723
    * languages in descending preference order, represented as BCP 47
5724
    * language tags. A string array or a comma-separated list.
5725
    * @param {String[]} availableLanguages The list of languages
5726
    * that the application supports, represented as BCP 47 language
5727
    * tags.
5728
    *
5729
    * @return {String} The available language that best matches the
5730
    * preferred language list, or "".
5731
    * @since 3.1.0
5732
    */
5733
    lookupBestLang: function(preferredLanguages, availableLanguages) {
5734
 
5735
        var i, language, result, index;
5736
 
5737
        // check whether the list of available languages contains language;
5738
        // if so return it
5739
        function scan(language) {
5740
            var i;
5741
            for (i = 0; i < availableLanguages.length; i += 1) {
5742
                if (language.toLowerCase() ===
5743
                            availableLanguages[i].toLowerCase()) {
5744
                    return availableLanguages[i];
5745
                }
5746
            }
5747
        }
5748
 
5749
        if (Y.Lang.isString(preferredLanguages)) {
5750
            preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
5751
        }
5752
 
5753
        for (i = 0; i < preferredLanguages.length; i += 1) {
5754
            language = preferredLanguages[i];
5755
            if (!language || language === '*') {
5756
                continue;
5757
            }
5758
            // check the fallback sequence for one language
5759
            while (language.length > 0) {
5760
                result = scan(language);
5761
                if (result) {
5762
                    return result;
5763
                } else {
5764
                    index = language.lastIndexOf('-');
5765
                    if (index >= 0) {
5766
                        language = language.substring(0, index);
5767
                        // one-character subtags get cut along with the
5768
                        // following subtag
5769
                        if (index >= 2 && language.charAt(index - 2) === '-') {
5770
                            language = language.substring(0, index - 2);
5771
                        }
5772
                    } else {
5773
                        // nothing available for this language
5774
                        break;
5775
                    }
5776
                }
5777
            }
5778
        }
5779
 
5780
        return '';
5781
    }
5782
});
5783
 
5784
 
5785
}, '3.18.1', {"requires": ["yui-base"]});
5786
YUI.add('yui-log', function (Y, NAME) {
5787
 
5788
/**
5789
 * Provides console log capability and exposes a custom event for
5790
 * console implementations. This module is a `core` YUI module,
5791
 * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
5792
 *
5793
 * @module yui
5794
 * @submodule yui-log
5795
 */
5796
 
5797
var INSTANCE = Y,
5798
    LOGEVENT = 'yui:log',
5799
    UNDEFINED = 'undefined',
5800
    LEVELS = { debug: 1,
5801
               info: 2,
5802
               warn: 4,
5803
               error: 8 };
5804
 
5805
/**
5806
 * If the 'debug' config is true, a 'yui:log' event will be
5807
 * dispatched, which the Console widget and anything else
5808
 * can consume.  If the 'useBrowserConsole' config is true, it will
5809
 * write to the browser console if available.  YUI-specific log
5810
 * messages will only be present in the -debug versions of the
5811
 * JS files.  The build system is supposed to remove log statements
5812
 * from the raw and minified versions of the files.
5813
 *
5814
 * @method log
5815
 * @for YUI
5816
 * @param  {String}  msg  The message to log.
5817
 * @param  {String}  cat  The log category for the message.  Default
5818
 *                        categories are "info", "warn", "error", "debug".
5819
 *                        Custom categories can be used as well. (opt).
5820
 * @param  {String}  src  The source of the the message (opt).
5821
 * @param  {boolean} silent If true, the log event won't fire.
5822
 * @return {YUI}      YUI instance.
5823
 */
5824
INSTANCE.log = function(msg, cat, src, silent) {
5825
    var bail, excl, incl, m, f, minlevel,
5826
        Y = INSTANCE,
5827
        c = Y.config,
5828
        publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
5829
    // suppress log message if the config is off or the event stack
5830
    // or the event call stack contains a consumer of the yui:log event
5831
    if (c.debug) {
5832
        // apply source filters
5833
        src = src || "";
5834
        if (typeof src !== "undefined") {
5835
            excl = c.logExclude;
5836
            incl = c.logInclude;
5837
            if (incl && !(src in incl)) {
5838
                bail = 1;
5839
            } else if (incl && (src in incl)) {
5840
                bail = !incl[src];
5841
            } else if (excl && (src in excl)) {
5842
                bail = excl[src];
5843
            }
5844
 
5845
            // Set a default category of info if the category was not defined.
5846
            if ((typeof cat === 'undefined')) {
5847
                cat = 'info';
5848
            }
5849
 
5850
            // Determine the current minlevel as defined in configuration
5851
            Y.config.logLevel = Y.config.logLevel || 'debug';
5852
            minlevel = LEVELS[Y.config.logLevel.toLowerCase()];
5853
 
5854
            if (cat in LEVELS && LEVELS[cat] < minlevel) {
5855
                // Skip this message if the we don't meet the defined minlevel
5856
                bail = 1;
5857
            }
5858
        }
5859
        if (!bail) {
5860
            if (c.useBrowserConsole) {
5861
                m = (src) ? src + ': ' + msg : msg;
5862
                if (Y.Lang.isFunction(c.logFn)) {
5863
                    c.logFn.call(Y, msg, cat, src);
5864
                } else if (typeof console !== UNDEFINED && console.log) {
5865
                    f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
5866
                    console[f](m);
5867
                } else if (typeof opera !== UNDEFINED) {
5868
                    opera.postError(m);
5869
                }
5870
            }
5871
 
5872
            if (publisher && !silent) {
5873
 
5874
                if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
5875
                    publisher.publish(LOGEVENT, {
5876
                        broadcast: 2
5877
                    });
5878
                }
5879
 
5880
                publisher.fire(LOGEVENT, {
5881
                    msg: msg,
5882
                    cat: cat,
5883
                    src: src
5884
                });
5885
            }
5886
        }
5887
    }
5888
 
5889
    return Y;
5890
};
5891
 
5892
/**
5893
 * Write a system message.  This message will be preserved in the
5894
 * minified and raw versions of the YUI files, unlike log statements.
5895
 * @method message
5896
 * @for YUI
5897
 * @param  {String}  msg  The message to log.
5898
 * @param  {String}  cat  The log category for the message.  Default
5899
 *                        categories are "info", "warn", "error", "debug".
5900
 *                        Custom categories can be used as well. (opt).
5901
 * @param  {String}  src  The source of the the message (opt).
5902
 * @param  {boolean} silent If true, the log event won't fire.
5903
 * @return {YUI}      YUI instance.
5904
 */
5905
INSTANCE.message = function() {
5906
    return INSTANCE.log.apply(INSTANCE, arguments);
5907
};
5908
 
5909
 
5910
}, '3.18.1', {"requires": ["yui-base"]});
5911
YUI.add('yui-later', function (Y, NAME) {
5912
 
5913
/**
5914
 * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module,
5915
 * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
5916
 *
5917
 * @module yui
5918
 * @submodule yui-later
5919
 */
5920
 
5921
var NO_ARGS = [];
5922
 
5923
/**
5924
 * Executes the supplied function in the context of the supplied
5925
 * object 'when' milliseconds later.  Executes the function a
5926
 * single time unless periodic is set to true.
5927
 * @for YUI
5928
 * @method later
5929
 * @param when {Number} the number of milliseconds to wait until the fn
5930
 * is executed.
5931
 * @param o the context object.
5932
 * @param fn {Function|String} the function to execute or the name of
5933
 * the method in the 'o' object to execute.
5934
 * @param data [Array] data that is provided to the function.  This
5935
 * accepts either a single item or an array.  If an array is provided,
5936
 * the function is executed with one parameter for each array item.
5937
 * If you need to pass a single array parameter, it needs to be wrapped
5938
 * in an array [myarray].
5939
 *
5940
 * Note: native methods in IE may not have the call and apply methods.
5941
 * In this case, it will work, but you are limited to four arguments.
5942
 *
5943
 * @param periodic {boolean} if true, executes continuously at supplied
5944
 * interval until canceled.
5945
 * @return {object} a timer object. Call the cancel() method on this
5946
 * object to stop the timer.
5947
 */
5948
Y.later = function(when, o, fn, data, periodic) {
5949
    when = when || 0;
5950
    data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS;
5951
    o = o || Y.config.win || Y;
5952
 
5953
    var cancelled = false,
5954
        method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
5955
        wrapper = function() {
5956
            // IE 8- may execute a setInterval callback one last time
5957
            // after clearInterval was called, so in order to preserve
5958
            // the cancel() === no more runny-run, we have to jump through
5959
            // an extra hoop.
5960
            if (!cancelled) {
5961
                if (!method.apply) {
5962
                    method(data[0], data[1], data[2], data[3]);
5963
                } else {
5964
                    method.apply(o, data || NO_ARGS);
5965
                }
5966
            }
5967
        },
5968
        id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
5969
 
5970
    return {
5971
        id: id,
5972
        interval: periodic,
5973
        cancel: function() {
5974
            cancelled = true;
5975
            if (this.interval) {
5976
                clearInterval(id);
5977
            } else {
5978
                clearTimeout(id);
5979
            }
5980
        }
5981
    };
5982
};
5983
 
5984
Y.Lang.later = Y.later;
5985
 
5986
 
5987
 
5988
}, '3.18.1', {"requires": ["yui-base"]});
5989
YUI.add('yui', function (Y, NAME) {}, '3.18.1', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});