~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

Viewing changes to lib/yuilib/3.13.0/yui-base/yui-base.js

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

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