1
/* YUI 3.9.1 (build 5852) Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ */
3
The YUI module contains the components required for building the YUI seed file.
4
This includes the script loading mechanism, a simple queue, and the core
5
utilities for the library.
12
/*jshint eqeqeq: false*/
13
if (typeof YUI != 'undefined') {
18
The YUI global namespace object. This is the constructor for all YUI instances.
20
This is a self-instantiable factory function, meaning you don't need to precede
21
it with the `new` operator. You can invoke it directly like this:
23
YUI().use('*', function (Y) {
24
// Y is a new YUI instance.
27
But it also works like this:
31
The `YUI` constructor accepts an optional config object, like this:
36
}).use('node', function (Y) {
37
// Y.Node is ready to use.
40
See the API docs for the <a href="config.html">Config</a> class for the complete
41
list of supported configuration properties accepted by the YUI constuctor.
43
If a global `YUI` object is already defined, the existing YUI object will not be
44
overwritten, to ensure that defined namespaces are preserved.
46
Each YUI instance has full custom event support, but only if the event system is
53
@param {Object} [config]* Zero or more optional configuration objects. Config
54
values are stored in the `Y.config` property. See the
55
<a href="config.html">Config</a> docs for the list of supported properties.
60
var YUI = function() {
65
instanceOf = function(o, type) {
66
return (o && o.hasOwnProperty && (o instanceof type));
68
gconf = (typeof YUI_config !== 'undefined') && YUI_config;
70
if (!(instanceOf(Y, YUI))) {
73
// set up the core environment
77
Master configuration that might span multiple contexts in a non-
78
browser environment. It is applied first to all instances in all
87
YUI().use('node', function (Y) {
88
// debug files used here
93
}).use('node', function (Y) {
94
// min files used here
97
@property {Object} GlobalConfig
101
if (YUI.GlobalConfig) {
102
Y.applyConfig(YUI.GlobalConfig);
106
Page-level config applied to all YUI instances created on the
107
current page. This is applied after `YUI.GlobalConfig` and before
108
any instance-level configuration.
112
// Single global var to include before YUI seed file
117
YUI().use('node', function (Y) {
118
// debug files used here
123
}).use('node', function (Y) {
124
// min files used here
127
@property {Object} YUI_config
131
Y.applyConfig(gconf);
134
// bind the specified additional modules for this instance
141
// Each instance can accept one or more configuration objects.
142
// These are applied after YUI.GlobalConfig and YUI_Config,
143
// overriding values set in those config files if there is a
144
// matching property.
146
Y.applyConfig(args[i]);
152
Y.instanceOf = instanceOf;
162
BASE = 'http://yui.yahooapis.com/',
164
These CSS class names can't be generated by
165
getClassName since it is not available at the
166
time they are being used.
168
DOC_LABEL = 'yui3-js-enabled',
169
CSS_STAMP_EL = 'yui3-css-stamp',
170
NOOP = function() {},
171
SLICE = Array.prototype.slice,
172
APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo
173
'io.xdrResponse': 1, // can call. this should
174
'SWF.eventHandler': 1 }, // be done at build time
175
hasWin = (typeof window != 'undefined'),
176
win = (hasWin) ? window : null,
177
doc = (hasWin) ? win.document : null,
178
docEl = doc && doc.documentElement,
179
docClass = docEl && docEl.className,
181
time = new Date().getTime(),
182
add = function(el, type, fn, capture) {
183
if (el && el.addEventListener) {
184
el.addEventListener(type, fn, capture);
185
} else if (el && el.attachEvent) {
186
el.attachEvent('on' + type, fn);
189
remove = function(el, type, fn, capture) {
190
if (el && el.removeEventListener) {
191
// this can throw an uncaught exception in FF
193
el.removeEventListener(type, fn, capture);
195
} else if (el && el.detachEvent) {
196
el.detachEvent('on' + type, fn);
199
handleLoad = function() {
200
YUI.Env.windowLoaded = true;
201
YUI.Env.DOMReady = true;
203
remove(window, 'load', handleLoad);
206
getLoader = function(Y, o) {
207
var loader = Y.Env._loader,
208
lCore = [ 'loader-base' ],
213
//loader._config(Y.config);
214
loader.ignoreRegistered = false;
217
loader.required = [];
218
loader.loadType = null;
220
loader = new Y.Loader(Y.config);
221
Y.Env._loader = loader;
223
if (mods && mods.loader) {
224
lCore = [].concat(lCore, YUI.Env.loaderExtras);
226
YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore));
231
clobber = function(r, s) {
233
if (s.hasOwnProperty(i)) {
239
ALREADY_DONE = { success: true };
241
// Stamp the documentElement (HTML) with a class of "yui-loaded" to
242
// enable styles that need to key off of JS being enabled.
243
if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
247
docClass += DOC_LABEL;
248
docEl.className = docClass;
251
if (VERSION.indexOf('@') > -1) {
252
VERSION = '3.5.0'; // dev time hack for cdn test
257
Applies a new configuration object to the config of this YUI instance. This
258
will merge new group/module definitions, and will also update the loader
259
cache if necessary. Updating `Y.config` directly will not update the cache.
262
@param {Object} o the configuration object.
265
applyConfig: function(o) {
272
config = this.config,
273
mods = config.modules,
274
groups = config.groups,
275
aliases = config.aliases,
276
loader = this.Env._loader;
279
if (o.hasOwnProperty(name)) {
281
if (mods && name == 'modules') {
283
} else if (aliases && name == 'aliases') {
284
clobber(aliases, attr);
285
} else if (groups && name == 'groups') {
286
clobber(groups, attr);
287
} else if (name == 'win') {
288
config[name] = (attr && attr.contentWindow) || attr;
289
config.doc = config[name] ? config[name].document : null;
290
} else if (name == '_yuid') {
305
Old way to apply a config to this instance (calls `applyConfig` under the
310
@param {Object} o The config to apply
312
_config: function(o) {
317
Initializes this YUI instance.
330
The version number of this YUI instance.
332
This value is typically updated by a script when a YUI release is built,
333
so it may not reflect the correct version number when YUI is run from
334
the development source tree.
336
@property {String} version
342
core: ['get', 'features', 'intl-base', 'yui-log', 'yui-later'],
343
loaderExtras: ['loader-rollup', 'loader-yui3'],
344
mods: {}, // flat module map
345
versions: {}, // version module map
347
cdn: BASE + VERSION + '/build/',
348
// bootstrapped: false,
359
// I'll start at the \b(simpleyui).
360
// 1. Look in the test string for "simpleyui" or "yui" or
361
// "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it
362
// can't match "foyui" or "i_heart_simpleyui". This can be anywhere in the string.
363
// 2. After #1 must come a forward slash followed by the string matched in #1, so
364
// "yui-base/yui-base" or "simpleyui/simpleyui" or "yui-pants/yui-pants".
365
// 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
366
// so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
367
// 4. This is followed by ".js", so "yui/yui.js", "simpleyui/simpleyui-min.js"
368
// 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
369
// then capture the junk between the LAST "&" and the string in 1-4. So
370
// "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
371
// will capture "3.3.0/build/"
375
// (?:[^&]*&) followed by 0..n characters followed by an &
376
// * in fact, find as many sets of characters followed by a & as you can
377
// ([^&]*) capture the stuff after the last & in \1
378
// )? but it's ok if all this ?junk&more_junk stuff isn't even there
379
// \b(simpleyui| after a word break find either the string "simpleyui" or
380
// yui(?:-\w+)? the string "yui" optionally followed by a -, then more characters
381
// ) and store the simpleyui or yui-* string in \2
382
// \/\2 then comes a / followed by the simpleyui or yui-* string in \2
383
// (?:-(min|debug))? optionally followed by "-min" or "-debug"
384
// .js and ending in ".js"
385
_BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
386
parseBasePath: function(src, pattern) {
387
var match = src.match(pattern),
391
path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
393
// this is to set up the path to the loader. The file
394
// filter for loader should match the yui include.
397
// extract correct path for mixed combo urls
398
// http://yuilibrary.com/projects/yui3/ticket/2528423
400
path += '?' + match[1];
409
getBase: G_ENV && G_ENV.getBase ||
411
var nodes = (doc && doc.getElementsByTagName('script')) || [],
412
path = Env.cdn, parsed,
415
for (i = 0, len = nodes.length; i < len; ++i) {
418
parsed = Y.Env.parseBasePath(src, pattern);
420
filter = parsed.filter;
435
Env._loaded[VERSION] = {};
437
if (G_ENV && Y !== YUI) {
438
Env._yidx = ++G_ENV._yidx;
439
Env._guidp = ('yui_' + VERSION + '_' +
440
Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_');
441
} else if (YUI._YUI) {
443
G_ENV = YUI._YUI.Env;
444
Env._yidx += G_ENV._yidx;
445
Env._uidx += G_ENV._uidx;
447
for (prop in G_ENV) {
448
if (!(prop in Env)) {
449
Env[prop] = G_ENV[prop];
463
// configuration defaults
464
Y.config = Y.config || {
471
useBrowserConsole: true,
474
global: Function('return this')()
477
//Register the CSS stamp element
478
if (doc && !doc.getElementById(CSS_STAMP_EL)) {
479
el = doc.createElement('div');
480
el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
481
YUI.Env.cssStampEl = el.firstChild;
483
doc.body.appendChild(YUI.Env.cssStampEl);
485
docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
487
} else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) {
488
YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL);
491
Y.config.lang = Y.config.lang || 'en-US';
493
Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
495
if (!filter || (!('mindebug').indexOf(filter))) {
498
filter = (filter) ? '-' + filter : filter;
499
Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
504
Finishes the instance setup. Attaches whatever YUI modules were defined
505
at the time that this instance was created.
514
extras = Y.config.core || [].concat(YUI.Env.core); //Clone it..
516
for (i = 0; i < extras.length; i++) {
517
if (mods[extras[i]]) {
518
core.push(extras[i]);
522
Y._attach(['yui-base']);
529
// Y.log(Y.id + ' initialized', 'info', 'yui');
533
Executes the named method on the specified YUI instance if that method is
537
@param {String} id YUI instance id.
538
@param {String} method Name of the method to execute. For example:
540
@param {Array} args Arguments to apply to the method.
541
@return {Mixed} Return value from the applied method, or `null` if the
542
specified instance was not found or the method was not whitelisted.
544
applyTo: function(id, method, args) {
545
if (!(method in APPLY_TO_AUTH)) {
546
this.log(method + ': applyTo not allowed', 'warn', 'yui');
550
var instance = instances[id], nest, m, i;
552
nest = method.split('.');
554
for (i = 0; i < nest.length; i = i + 1) {
557
this.log('applyTo not found: ' + method, 'warn', 'yui');
560
return m && m.apply(instance, args);
567
Registers a YUI module and makes it available for use in a `YUI().use()` call or
568
as a dependency for other modules.
570
The easiest way to create a first-class YUI module is to use
571
<a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
574
Shifter will automatically wrap your module code in a `YUI.add()` call along
575
with any configuration info required for the module.
579
YUI.add('davglass', function (Y) {
580
Y.davglass = function () {
581
Y.log('Dav was here!');
584
requires: ['harley-davidson', 'mt-dew']
588
@param {String} name Module name.
589
@param {Function} fn Function containing module code. This function will be
590
executed whenever the module is attached to a specific YUI instance.
592
@param {YUI} fn.Y The YUI instance to which this module is attached.
593
@param {String} fn.name Name of the module
595
@param {String} version Module version number. This is currently used only for
596
informational purposes, and is not used internally by YUI.
598
@param {Object} [config] Module config.
599
@param {Array} [config.requires] Array of other module names that must be
600
attached before this module can be attached.
601
@param {Array} [config.optional] Array of optional module names that should
602
be attached before this module is attached if they've already been
603
loaded. If the `loadOptional` YUI option is `true`, optional modules
604
that have not yet been loaded will be loaded just as if they were hard
606
@param {Array} [config.use] Array of module names that are included within
607
or otherwise provided by this module, and which should be attached
608
automatically when this module is attached. This makes it possible to
609
create "virtual rollup" modules that simply attach a collection of other
610
modules or submodules.
612
@return {YUI} This YUI instance.
614
add: function(name, fn, version, details) {
615
details = details || {};
623
//Instance hash so we don't apply it to the same instance twice
626
i, versions = env.versions;
628
env.mods[name] = mod;
629
versions[version] = versions[version] || {};
630
versions[version][name] = mod;
632
for (i in instances) {
633
if (instances.hasOwnProperty(i)) {
635
if (!applied[inst.id]) {
636
applied[inst.id] = true;
637
loader = inst.Env._loader;
639
if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
640
loader.addModule(details, name);
651
Executes the callback function associated with each required module,
652
attaching the module to this YUI instance.
655
@param {Array} r The array of modules to attach
656
@param {Boolean} [moot=false] If `true`, don't throw a warning if the module
660
_attach: function(r, moot) {
661
var i, name, mod, details, req, use, after,
663
aliases = YUI.Env.aliases,
665
cache = YUI.Env._renderedMods,
666
loader = Y.Env._loader,
667
done = Y.Env._attached,
668
len = r.length, loader, def, go,
671
//Check for conditional modules (in a second+ instance) and add their requirements
672
//TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
673
for (i = 0; i < len; i++) {
677
if (loader && loader.conditions[name]) {
678
for (j in loader.conditions[name]) {
679
if (loader.conditions[name].hasOwnProperty(j)) {
680
def = loader.conditions[name][j];
681
go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
692
for (i = 0; i < len; i++) {
697
if (aliases && aliases[name] && !mod) {
698
Y._attach(aliases[name]);
702
if (loader && loader.moduleInfo[name]) {
703
mod = loader.moduleInfo[name];
707
// Y.log('no js def for: ' + name, 'info', 'yui');
709
//if (!loader || !loader.moduleInfo[name]) {
710
//if ((!loader || !loader.moduleInfo[name]) && !moot) {
712
if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
713
Y.Env._missed.push(name);
714
Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
715
Y.message('NOT loaded: ' + name, 'warn', 'yui');
720
//Don't like this, but in case a mod was asked for once, then we fetch it
721
//We need to remove it from the missed list ^davglass
722
for (j = 0; j < Y.Env._missed.length; j++) {
723
if (Y.Env._missed[j] === name) {
724
Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
725
Y.Env._missed.splice(j, 1);
729
If it's a temp module, we need to redo it's requirements if it's already loaded
730
since it may have been loaded by another instance and it's dependencies might
731
have been redefined inside the fetched file.
733
if (loader && cache && cache[name] && cache[name].temp) {
734
loader.getRequires(cache[name]);
736
for (j in loader.moduleInfo[name].expanded_map) {
737
if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
744
details = mod.details;
745
req = details.requires;
747
after = details.after;
748
//Force Intl load if there is a language (Loader logic) @todo fix this shit
755
for (j = 0; j < req.length; j++) {
757
if (!Y._attach(req)) {
766
for (j = 0; j < after.length; j++) {
767
if (!done[after[j]]) {
768
if (!Y._attach(after, true)) {
777
if (Y.config.throwFail) {
783
Y.error('Attach error: ' + name, e, name);
790
for (j = 0; j < use.length; j++) {
792
if (!Y._attach(use)) {
810
Delays the `use` callback until another event has taken place such as
811
`window.onload`, `domready`, `contentready`, or `available`.
814
@method _delayCallback
815
@param {Function} cb The original `use` callback.
816
@param {String|Object} until Either an event name ('load', 'domready', etc.)
817
or an object containing event/args keys for contentready/available.
820
_delayCallback: function(cb, until) {
823
mod = ['event-base'];
825
until = (Y.Lang.isObject(until) ? until : { event: until });
827
if (until.event === 'load') {
828
mod.push('event-synthetic');
831
Y.log('Delaying use callback until: ' + until.event, 'info', 'yui');
833
Y.log('Use callback fired, waiting on delay', 'info', 'yui');
834
var args = arguments;
835
Y._use(mod, function() {
836
Y.log('Delayed use wrapper callback after dependencies', 'info', 'yui');
837
Y.on(until.event, function() {
838
args[1].delayUntil = until.event;
839
Y.log('Delayed use callback done after ' + until.event, 'info', 'yui');
847
Attaches one or more modules to this YUI instance. When this is executed,
848
the requirements of the desired modules are analyzed, and one of several
852
* All required modules have already been loaded, and just need to be
853
attached to this YUI instance. In this case, the `use()` callback will
854
be executed synchronously after the modules are attached.
856
* One or more modules have not yet been loaded, or the Get utility is not
857
available, or the `bootstrap` config option is `false`. In this case,
858
a warning is issued indicating that modules are missing, but all
859
available modules will still be attached and the `use()` callback will
860
be executed synchronously.
862
* One or more modules are missing and the Loader is not available but the
863
Get utility is, and `bootstrap` is not `false`. In this case, the Get
864
utility will be used to load the Loader, and we will then proceed to
867
* One or more modules are missing and the Loader is available. In this
868
case, the Loader will be used to resolve the dependency tree for the
869
missing modules and load them and their dependencies. When the Loader is
870
finished loading modules, the `use()` callback will be executed
875
// Loads and attaches dd and its dependencies.
876
YUI().use('dd', function (Y) {
880
// Loads and attaches dd and node as well as all of their dependencies.
881
YUI().use(['dd', 'node'], function (Y) {
885
// Attaches all modules that have already been loaded.
886
YUI().use('*', function (Y) {
890
// Attaches a gallery module.
891
YUI().use('gallery-yql', function (Y) {
895
// Attaches a YUI 2in3 module.
896
YUI().use('yui2-datatable', function (Y) {
901
@param {String|Array} modules* One or more module names to attach.
902
@param {Function} [callback] Callback function to be executed once all
903
specified modules and their dependencies have been attached.
904
@param {YUI} callback.Y The YUI instance created for this sandbox.
905
@param {Object} callback.status Object containing `success`, `msg` and
910
var args = SLICE.call(arguments, 0),
911
callback = args[args.length - 1],
918
// The last argument supplied to use can be a load complete callback
919
if (Y.Lang.isFunction(callback)) {
921
if (Y.config.delayUntil) {
922
callback = Y._delayCallback(callback, Y.config.delayUntil);
927
if (Y.Lang.isArray(args[0])) {
931
if (Y.config.cacheUse) {
932
while ((name = args[i++])) {
933
if (!Env._attached[name]) {
941
Y.log('already provisioned: ' + args, 'info', 'yui');
943
Y._notify(callback, ALREADY_DONE, args);
949
Y._useQueue = Y._useQueue || new Y.Queue();
950
Y._useQueue.add([args, callback]);
952
Y._use(args, function(Y, response) {
953
Y._notify(callback, response, args);
961
Handles Loader notifications about attachment/load errors.
964
@param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
965
@param {Object} response Response returned from Loader.
966
@param {Array} args Arguments passed from Loader.
969
_notify: function(callback, response, args) {
970
if (!response.success && this.config.loadErrorFn) {
971
this.config.loadErrorFn.call(this, this, callback, response, args);
972
} else if (callback) {
973
if (this.Env._missed && this.Env._missed.length) {
974
response.msg = 'Missing modules: ' + this.Env._missed.join();
975
response.success = false;
977
if (this.config.throwFail) {
978
callback(this, response);
981
callback(this, response);
983
this.error('use callback error', e, args);
990
Called from the `use` method queue to ensure that only one set of loading
991
logic is performed at a time.
994
@param {String} args* One or more modules to attach.
995
@param {Function} [callback] Function to call once all required modules have
999
_use: function(args, callback) {
1002
this._attach(['yui-base']);
1005
var len, loader, handleBoot,
1011
aliases = G_ENV.aliases,
1012
queue = G_ENV._loaderQueue,
1016
boot = config.bootstrap,
1021
fetchCSS = config.fetchCSS,
1022
process = function(names, skip) {
1024
var i = 0, a = [], name, len, m, req, use;
1026
if (!names.length) {
1032
for (i = 0; i < len; i++) {
1033
if (aliases[names[i]] && !mods[names[i]]) {
1034
a = [].concat(a, aliases[names[i]]);
1044
for (i = 0; i < len; i++) {
1050
// only attach a module once
1061
req = m.details.requires;
1062
use = m.details.use;
1064
// CSS files don't register themselves, see if it has
1066
if (!G_ENV._loaded[VERSION][name]) {
1069
used[name] = true; // probably css
1073
// make sure requirements are attached
1074
if (req && req.length) {
1078
// make sure we grab the submodule dependencies too
1079
if (use && use.length) {
1086
handleLoader = function(fromLoader) {
1087
var response = fromLoader || {
1093
data = response.data;
1098
origMissing = missing;
1102
redo = missing.length;
1104
if ([].concat(missing).sort().join() ==
1105
origMissing.sort().join()) {
1113
Y._use(missing, function() {
1114
Y.log('Nested use callback: ' + data, 'info', 'yui');
1115
if (Y._attach(data)) {
1116
Y._notify(callback, response, data);
1121
// Y.log('attaching from loader: ' + data, 'info', 'yui');
1122
ret = Y._attach(data);
1125
Y._notify(callback, response, args);
1129
if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
1130
Y._use.apply(Y, Y._useQueue.next());
1135
// Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');
1137
// YUI().use('*'); // bind everything available
1138
if (firstArg === '*') {
1141
if (mods.hasOwnProperty(i)) {
1145
ret = Y._attach(args);
1152
if ((mods.loader || mods['loader-base']) && !Y.Loader) {
1153
Y.log('Loader was found in meta, but it is not attached. Attaching..', 'info', 'yui');
1154
Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
1157
// Y.log('before loader requirements: ' + args, 'info', 'yui');
1159
// use loader to expand dependencies and sort the
1160
// requirements if it is available.
1161
if (boot && Y.Loader && args.length) {
1162
Y.log('Using loader to expand dependencies', 'info', 'yui');
1163
loader = getLoader(Y);
1164
loader.require(args);
1165
loader.ignoreRegistered = true;
1166
loader._boot = true;
1167
loader.calculate(null, (fetchCSS) ? null : 'js');
1168
args = loader.sorted;
1169
loader._boot = false;
1174
len = missing.length;
1178
missing = YArray.dedupe(missing);
1179
len = missing.length;
1180
Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
1185
if (boot && len && Y.Loader) {
1186
// Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
1187
Y.log('Using Loader', 'info', 'yui');
1189
loader = getLoader(Y);
1190
loader.onEnd = handleLoader;
1193
loader.ignoreRegistered = false;
1194
loader.require(missing);
1195
loader.insert(null, (fetchCSS) ? null : 'js');
1197
} else if (boot && len && Y.Get && !Env.bootstrapped) {
1201
handleBoot = function() {
1203
queue.running = false;
1204
Env.bootstrapped = true;
1205
G_ENV._bootstrapping = false;
1206
if (Y._attach(['loader'])) {
1207
Y._use(args, callback);
1211
if (G_ENV._bootstrapping) {
1212
Y.log('Waiting for loader', 'info', 'yui');
1213
queue.add(handleBoot);
1215
G_ENV._bootstrapping = true;
1216
Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
1217
Y.Get.script(config.base + config.loaderPath, {
1223
Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
1224
ret = Y._attach(args);
1235
Utility method for safely creating namespaces if they don't already exist.
1236
May be called statically on the YUI global object or as a method on a YUI
1239
When called statically, a namespace will be created on the YUI global
1242
// Create `YUI.your.namespace.here` as nested objects, preserving any
1243
// objects that already exist instead of overwriting them.
1244
YUI.namespace('your.namespace.here');
1246
When called as a method on a YUI instance, a namespace will be created on
1249
// Creates `Y.property.package`.
1250
Y.namespace('property.package');
1252
Dots in the input string cause `namespace` to create nested objects for each
1253
token. If any part of the requested namespace already exists, the current
1254
object will be left in place and will not be overwritten. This allows
1255
multiple calls to `namespace` to preserve existing namespaced properties.
1257
If the first token in the namespace string is "YAHOO", that token is
1258
discarded. This is legacy behavior for backwards compatibility with YUI 2.
1260
Be careful with namespace tokens. Reserved words may work in some browsers
1261
and not others. For instance, the following will fail in some browsers
1262
because the supported version of JavaScript reserves the word "long":
1264
Y.namespace('really.long.nested.namespace');
1266
Note: If you pass multiple arguments to create multiple namespaces, only the
1267
last one created is returned from this function.
1270
@param {String} namespace* One or more namespaces to create.
1271
@return {Object} Reference to the last namespace object created.
1273
namespace: function() {
1274
var a = arguments, o, i = 0, j, d, arg;
1276
for (; i < a.length; i++) {
1277
o = this; //Reset base object per argument or it will get reused from the last
1279
if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1280
d = arg.split(PERIOD);
1281
for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1282
o[d[j]] = o[d[j]] || {};
1286
o[arg] = o[arg] || {};
1287
o = o[arg]; //Reset base object to the new object so it's returned
1293
// this is replaced if the log module is included
1296
// this is replaced if the dump module is included
1297
dump: function (o) { return ''+o; },
1302
The reporting mechanism is controlled by the `throwFail` configuration
1303
attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
1304
truthy, a JS exception is thrown.
1306
If an `errorFn` is specified in the config it must return `true` to indicate
1307
that the exception was handled and keep it from being thrown.
1310
@param {String} msg Error message.
1311
@param {Error|String} [e] JavaScript error object or an error string.
1312
@param {String} [src] Source of the error (such as the name of the module in
1313
which the error occurred).
1316
error: function(msg, e, src) {
1317
//TODO Add check for window.onerror here
1321
if (Y.config.errorFn) {
1322
ret = Y.config.errorFn.apply(Y, arguments);
1326
throw (e || new Error(msg));
1328
Y.message(msg, 'error', ''+src); // don't scrub this one
1335
Generates an id string that is unique among all YUI instances in this
1339
@param {String} [pre] Prefix.
1340
@return {String} Unique id.
1342
guid: function(pre) {
1343
var id = this.Env._guidp + '_' + (++this.Env._uidx);
1344
return (pre) ? (pre + id) : id;
1348
Returns a unique id associated with the given object and (if *readOnly* is
1349
falsy) stamps the object with that id so it can be identified in the future.
1351
Stamping an object involves adding a `_yuid` property to it that contains
1352
the object's id. One exception to this is that in Internet Explorer, DOM
1353
nodes have a `uniqueID` property that contains a browser-generated unique
1354
id, which will be used instead of a YUI-generated id when available.
1357
@param {Object} o Object to stamp.
1358
@param {Boolean} readOnly If truthy and the given object has not already
1359
been stamped, the object will not be modified and `null` will be
1361
@return {String} Object's unique id, or `null` if *readOnly* was truthy and
1362
the given object was not already stamped.
1364
stamp: function(o, readOnly) {
1370
// IE generates its own unique ID for dom nodes
1371
// The uniqueID property of a document node returns a new ID
1372
if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1375
uid = (typeof o === 'string') ? o : o._yuid;
1392
Destroys this YUI instance.
1397
destroy: function() {
1402
delete instances[Y.id];
1408
Safe `instanceof` wrapper that works around a memory leak in IE when the
1409
object being tested is `window` or `document`.
1411
Unless you are testing objects that may be `window` or `document`, you
1412
should use the native `instanceof` operator instead of this method.
1415
@param {Object} o Object to check.
1416
@param {Object} type Class to check against.
1421
YUI.prototype = proto;
1423
// inheritance utilities are not available yet
1424
for (prop in proto) {
1425
if (proto.hasOwnProperty(prop)) {
1426
YUI[prop] = proto[prop];
1431
Applies a configuration to all YUI instances in this execution context.
1433
The main use case for this method is in "mashups" where several third-party
1434
scripts need to write to a global YUI config, but cannot share a single
1435
centrally-managed config object. This way they can all call
1436
`YUI.applyConfig({})` instead of overwriting the single global config.
1443
fullpath: './davglass.js'
1451
fullpath: './foo.js'
1456
YUI().use('davglass', function (Y) {
1457
// Module davglass will be available here.
1461
@param {Object} o Configuration object to apply.
1465
YUI.applyConfig = function(o) {
1469
//If there is a GlobalConfig, apply it first to set the defaults
1470
if (YUI.GlobalConfig) {
1471
this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1473
//Apply this config to it
1474
this.prototype.applyConfig.call(this, o);
1475
//Reset GlobalConfig to the combined config
1476
YUI.GlobalConfig = this.config;
1479
// set up the environment
1483
// add a window load event at load time so we can capture
1484
// the case where it fires before dynamic loading is
1486
add(window, 'load', handleLoad);
1492
YUI.Env.remove = remove;
1495
// Support the CommonJS method for exporting our single global
1496
if (typeof exports == 'object') {
1499
* Set a method to be called when `Get.script` is called in Node.js
1500
* `Get` will open the file, then pass it's content and it's path
1501
* to this method before attaching it. Commonly used for code coverage
1502
* instrumentation. <strong>Calling this multiple times will only
1503
* attach the last hook method</strong>. This method is only
1504
* available in Node.js.
1505
* @method setLoadHook
1507
* @param {Function} fn The function to set
1508
* @param {String} fn.data The content of the file
1509
* @param {String} fn.path The file path of the file
1511
YUI.setLoadHook = function(fn) {
1512
YUI._getLoadHook = fn;
1515
* Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
1516
* @method _getLoadHook
1518
* @param {String} data The content of the file
1519
* @param {String} path The file path of the file
1521
YUI._getLoadHook = null;
1528
Config object that contains all of the configuration options for
1529
this `YUI` instance.
1531
This object is supplied by the implementer when instantiating YUI. Some
1532
properties have default values if they are not supplied by the implementer.
1534
This object should not be updated directly because some values are cached. Use
1535
`applyConfig()` to update the config object on a YUI instance that has already
1543
If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
1544
if they're needed to load additional dependencies and aren't already available.
1546
Setting this to `false` will prevent YUI from automatically loading the Loader
1547
and module metadata, so you will need to manually ensure that they're available
1548
or handle dependency resolution yourself.
1550
@property {Boolean} bootstrap
1555
If `true`, `Y.log()` messages will be written to the browser's debug console
1556
when available and when `useBrowserConsole` is also `true`.
1558
@property {Boolean} debug
1563
Log messages to the browser console if `debug` is `true` and the browser has a
1566
@property {Boolean} useBrowserConsole
1571
A hash of log sources that should be logged. If specified, only messages from
1572
these sources will be logged. Others will be discarded.
1574
@property {Object} logInclude
1579
A hash of log sources that should be not be logged. If specified, all sources
1580
will be logged *except* those on this list.
1582
@property {Object} logExclude
1586
When the YUI seed file is dynamically loaded after the `window.onload` event has
1587
fired, set this to `true` to tell YUI that it shouldn't wait for `window.onload`
1590
This ensures that components that rely on `window.onload` and the `domready`
1591
custom event will work as expected even when YUI is dynamically injected.
1593
@property {Boolean} injected
1598
If `true`, `Y.error()` will generate or re-throw a JavaScript error. Otherwise,
1599
errors are merely logged silently.
1601
@property {Boolean} throwFail
1606
Reference to the global object for this execution context.
1608
In a browser, this is the current `window` object. In Node.js, this is the
1609
Node.js `global` object.
1611
@property {Object} global
1615
The browser window or frame that this YUI instance should operate in.
1617
When running in Node.js, this property is `undefined`, since there is no
1618
`window` object. Use `global` to get a reference to the global object that will
1619
work in both browsers and Node.js.
1621
@property {Window} win
1625
The browser `document` object associated with this YUI instance's `win` object.
1627
When running in Node.js, this property is `undefined`, since there is no
1630
@property {Document} doc
1634
A list of modules that defines the YUI core (overrides the default list).
1636
@property {Array} core
1638
@default ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3']
1642
A list of languages to use in order of preference.
1644
This list is matched against the list of available languages in modules that the
1645
YUI instance uses to determine the best possible localization of language
1648
Languages are represented using BCP 47 language tags, such as "en-GB" for
1649
English as used in the United Kingdom, or "zh-Hans-CN" for simplified Chinese as
1650
used in China. The list may be provided as a comma-separated string or as an
1653
@property {String|String[]} lang
1657
Default date format.
1659
@property {String} dateFormat
1660
@deprecated Use configuration in `DataType.Date.format()` instead.
1666
@property {String} locale
1667
@deprecated Use `config.lang` instead.
1671
Default generic polling interval in milliseconds.
1673
@property {Number} pollInterval
1678
The number of dynamic `<script>` nodes to insert by default before automatically
1679
removing them when loading scripts.
1681
This applies only to script nodes because removing the node will not make the
1682
evaluated script unavailable. Dynamic CSS nodes are not auto purged, because
1683
removing a linked style sheet will also remove the style definitions.
1685
@property {Number} purgethreshold
1690
Delay in milliseconds to wait after a window `resize` event before firing the
1691
event. If another `resize` event occurs before this delay has elapsed, the
1692
delay will start over to ensure that `resize` events are throttled.
1694
@property {Number} windowResizeDelay
1699
Base directory for dynamic loading.
1701
@property {String} base
1705
Base URL for a dynamic combo handler. This will be used to make combo-handled
1706
module requests if `combine` is set to `true.
1708
@property {String} comboBase
1709
@default "http://yui.yahooapis.com/combo?"
1713
Root path to prepend to each module path when creating a combo-handled request.
1715
This is updated for each YUI release to point to a specific version of the
1716
library; for example: "3.8.0/build/".
1718
@property {String} root
1722
Filter to apply to module urls. This filter will modify the default path for all
1725
The default path for the YUI library is the minified version of the files (e.g.,
1726
event-min.js). The filter property can be a predefined filter or a custom
1727
filter. The valid predefined filters are:
1729
- **debug**: Loads debug versions of modules (e.g., event-debug.js).
1730
- **raw**: Loads raw, non-minified versions of modules without debug logging
1733
You can also define a custom filter, which must be an object literal containing
1734
a search regular expression and a replacement string:
1737
searchExp : "-min\\.js",
1738
replaceStr: "-debug.js"
1741
@property {Object|String} filter
1745
Skin configuration and customizations.
1747
@property {Object} skin
1748
@param {String} [skin.defaultSkin='sam'] Default skin name. This skin will be
1749
applied automatically to skinnable components if not overridden by a
1750
component-specific skin name.
1751
@param {String} [skin.base='assets/skins/'] Default base path for a skin,
1752
relative to Loader's `base` path.
1753
@param {Object} [skin.overrides] Component-specific skin name overrides. Specify
1754
a component name as the key and, as the value, a string or array of strings
1755
for a skin or skins that should be loaded for that component instead of the
1760
Hash of per-component filter specifications. If specified for a given component,
1761
this overrides the global `filter` config.
1763
@property {Object} filters
1767
If `true`, YUI will use a combo handler to load multiple modules in as few
1768
requests as possible.
1770
The YUI CDN (which YUI uses by default) supports combo handling, but other
1771
servers may not. If the server from which you're loading YUI does not support
1772
combo handling, set this to `false`.
1774
Providing a value for the `base` config property will cause `combine` to default
1775
to `false` instead of `true`.
1777
@property {Boolean} combine
1782
Array of module names that should never be dynamically loaded.
1784
@property {String[]} ignore
1788
Array of module names that should always be loaded when required, even if
1789
already present on the page.
1791
@property {String[]} force
1795
DOM element or id that should be used as the insertion point for dynamically
1796
added `<script>` and `<link>` nodes.
1798
@property {HTMLElement|String} insertBefore
1802
Object hash containing attributes to add to dynamically added `<script>` nodes.
1804
@property {Object} jsAttributes
1808
Object hash containing attributes to add to dynamically added `<link>` nodes.
1810
@property {Object} cssAttributes
1814
Timeout in milliseconds before a dynamic JS or CSS request will be considered a
1815
failure. If not set, no timeout will be enforced.
1817
@property {Number} timeout
1821
Callback for the 'CSSComplete' event. When dynamically loading YUI components
1822
with CSS, this property fires when the CSS is finished loading.
1824
This provides an opportunity to enhance the presentation of a loading page a
1825
little bit before the entire loading process is done.
1827
@property {Function} onCSS
1831
A hash of module definitions to add to the list of available YUI modules. These
1832
modules can then be dynamically loaded via the `use()` method.
1834
This is a hash in which keys are module names and values are objects containing
1837
See `Loader.addModule()` for the supported module metadata fields. Also see
1838
`groups`, which provides a way to configure the base and combo spec for a set of
1846
fullpath: '/mymod1/mymod1.js'
1850
requires: ['mymod1'],
1851
fullpath: '/mymod2/mymod2.js'
1854
mymod3: '/js/mymod3.js',
1855
mycssmod: '/css/mycssmod.css'
1858
@property {Object} modules
1862
Aliases are dynamic groups of modules that can be used as shortcuts.
1868
davglass: [ 'node', 'yql', 'dd' ],
1869
mine: [ 'davglass', 'autocomplete']
1871
}).use('mine', function (Y) {
1872
// Node, YQL, DD & AutoComplete available here.
1875
@property {Object} aliases
1879
A hash of module group definitions.
1881
For each group you can specify a list of modules and the base path and
1882
combo spec to use when dynamically loading the modules.
1888
// specify whether or not this group has a combo service
1891
// The comboSeperator to use with this group's combo handler
1894
// The maxURLLength for this server
1897
// the base path for non-combo paths
1898
base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1900
// the path to the combo service
1901
comboBase: 'http://yui.yahooapis.com/combo?',
1903
// a fragment to prepend to the path attribute when
1904
// when building combo urls
1905
root: '2.8.0r4/build/',
1907
// the module definitions
1910
path: "yahoo-dom-event/yahoo-dom-event.js"
1913
path: "animation/animation.js",
1914
requires: ['yui2_yde']
1920
@property {Object} groups
1924
Path to the Loader JS file, relative to the `base` path.
1926
This is used to dynamically bootstrap the Loader when it's needed and isn't yet
1929
@property {String} loaderPath
1930
@default "loader/loader-min.js"
1934
If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
1935
`false` to prevent YUI from loading any CSS, or set it to the string `"force"`
1936
to force CSS dependencies to be loaded even if their associated JS modules are
1939
@property {Boolean|String} fetchCSS
1944
Default gallery version used to build gallery module urls.
1946
@property {String} gallery
1951
Default YUI 2 version used to build YUI 2 module urls.
1953
This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
1954
`2in3` config for pulling different revisions of the wrapped YUI 2 modules.
1956
@property {String} yui2
1962
Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
1964
@property {String} 2in3
1970
Alternate console log function that should be used in environments without a
1971
supported native console. This function is executed with the YUI instance as its
1974
@property {Function} logFn
1979
Callback to execute when `Y.error()` is called. It receives the error message
1980
and a JavaScript error object if one was provided.
1982
This function is executed with the YUI instance as its `this` object.
1984
Returning `true` from this function will prevent an exception from being thrown.
1986
@property {Function} errorFn
1987
@param {String} errorFn.msg Error message
1988
@param {Object} [errorFn.err] Error object (if one was provided).
1993
A callback to execute when Loader fails to load one or more resources.
1995
This could be because of a script load failure. It could also be because a
1996
module fails to register itself when the `requireRegistration` config is `true`.
1998
If this function is defined, the `use()` callback will only be called when the
1999
loader succeeds. Otherwise, `use()` will always executes unless there was a
2000
JavaScript error when attaching a module.
2002
@property {Function} loadErrorFn
2007
If `true`, Loader will expect all loaded scripts to be first-class YUI modules
2008
that register themselves with the YUI global, and will trigger a failure if a
2009
loaded script does not register a YUI module.
2011
@property {Boolean} requireRegistration
2017
Cache serviced use() requests.
2019
@property {Boolean} cacheUse
2022
@deprecated No longer used.
2026
Whether or not YUI should use native ES5 functionality when available for
2027
features like `Y.Array.each()`, `Y.Object()`, etc.
2029
When `false`, YUI will always use its own fallback implementations instead of
2030
relying on ES5 functionality, even when ES5 functionality is available.
2032
@property {Boolean} useNativeES5
2038
* Leverage native JSON stringify if the browser has a native
2039
* implementation. In general, this is a good idea. See the Known Issues
2040
* section in the JSON user guide for caveats. The default value is true
2041
* for browsers with native JSON support.
2043
* @property useNativeJSONStringify
2050
* Leverage native JSON parse if the browser has a native implementation.
2051
* In general, this is a good idea. See the Known Issues section in the
2052
* JSON user guide for caveats. The default value is true for browsers with
2053
* native JSON support.
2055
* @property useNativeJSONParse
2062
Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
2063
@property delayUntil
2068
You can use `load` or `domready` strings by default:
2071
delayUntil: 'domready'
2073
// This will not execute until 'domeready' occurs.
2076
Or you can delay until a node is available (with `available` or `contentready`):
2084
// This will not execute until a node matching the selector "#foo" is
2085
// available in the DOM.
2088
@property {Object|String} delayUntil
2091
YUI.add('yui-base', function (Y, NAME) {
2096
* @submodule yui-base
2099
* The YUI module contains the components required for building the YUI
2100
* seed file. This includes the script loading mechanism, a simple queue,
2101
* and the core utilities for the library.
2103
* @submodule yui-base
2107
* Provides core language utilites and extensions used throughout YUI.
2113
var L = Y.Lang || (Y.Lang = {}),
2115
STRING_PROTO = String.prototype,
2116
TOSTRING = Object.prototype.toString,
2119
'undefined' : 'undefined',
2120
'number' : 'number',
2121
'boolean' : 'boolean',
2122
'string' : 'string',
2123
'[object Function]': 'function',
2124
'[object RegExp]' : 'regexp',
2125
'[object Array]' : 'array',
2126
'[object Date]' : 'date',
2127
'[object Error]' : 'error'
2130
SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
2131
TRIMREGEX = /^\s+|\s+$/g,
2132
NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i;
2134
// -- Protected Methods --------------------------------------------------------
2137
Returns `true` if the given function appears to be implemented in native code,
2138
`false` otherwise. Will always return `false` -- even in ES5-capable browsers --
2139
if the `useNativeES5` YUI config option is set to `false`.
2141
This isn't guaranteed to be 100% accurate and won't work for anything other than
2142
functions, but it can be useful for determining whether a function like
2143
`Array.prototype.forEach` is native or a JS shim provided by another library.
2145
There's a great article by @kangax discussing certain flaws with this technique:
2146
<http://perfectionkills.com/detecting-built-in-host-methods/>
2148
While his points are valid, it's still possible to benefit from this function
2149
as long as it's used carefully and sparingly, and in such a way that false
2150
negatives have minimal consequences. It's used internally to avoid using
2151
potentially broken non-native ES5 shims that have been added to the page by
2155
@param {Function} fn Function to test.
2156
@return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
2161
L._isNative = function (fn) {
2162
return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
2165
// -- Public Methods -----------------------------------------------------------
2168
* Determines whether or not the provided item is an array.
2170
* Returns `false` for array-like collections such as the function `arguments`
2171
* collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
2172
* test for an array-like collection.
2175
* @param o The object to test.
2176
* @return {boolean} true if o is an array.
2179
L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
2180
return L.type(o) === 'array';
2184
* Determines whether or not the provided item is a boolean.
2187
* @param o The object to test.
2188
* @return {boolean} true if o is a boolean.
2190
L.isBoolean = function(o) {
2191
return typeof o === 'boolean';
2195
* Determines whether or not the supplied item is a date instance.
2198
* @param o The object to test.
2199
* @return {boolean} true if o is a date.
2201
L.isDate = function(o) {
2202
return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
2207
* Determines whether or not the provided item is a function.
2208
* Note: Internet Explorer thinks certain functions are objects:
2212
* var obj = document.createElement("object");
2213
* Y.Lang.isFunction(obj.getAttribute) // reports false in IE
2215
* var input = document.createElement("input"); // append to body
2216
* Y.Lang.isFunction(input.focus) // reports false in IE
2220
* You will have to implement additional tests if these functions
2224
* @method isFunction
2226
* @param o The object to test.
2227
* @return {boolean} true if o is a function.
2229
L.isFunction = function(o) {
2230
return L.type(o) === 'function';
2234
* Determines whether or not the provided item is null.
2237
* @param o The object to test.
2238
* @return {boolean} true if o is null.
2240
L.isNull = function(o) {
2245
* Determines whether or not the provided item is a legal number.
2248
* @param o The object to test.
2249
* @return {boolean} true if o is a number.
2251
L.isNumber = function(o) {
2252
return typeof o === 'number' && isFinite(o);
2256
* Determines whether or not the provided item is of type object
2257
* or function. Note that arrays are also objects, so
2258
* <code>Y.Lang.isObject([]) === true</code>.
2261
* @param o The object to test.
2262
* @param failfn {boolean} fail if the input is a function.
2263
* @return {boolean} true if o is an object.
2264
* @see isPlainObject
2266
L.isObject = function(o, failfn) {
2268
return (o && (t === 'object' ||
2269
(!failfn && (t === 'function' || L.isFunction(o))))) || false;
2273
* Determines whether or not the provided item is a string.
2276
* @param o The object to test.
2277
* @return {boolean} true if o is a string.
2279
L.isString = function(o) {
2280
return typeof o === 'string';
2284
* Determines whether or not the provided item is undefined.
2285
* @method isUndefined
2287
* @param o The object to test.
2288
* @return {boolean} true if o is undefined.
2290
L.isUndefined = function(o) {
2291
return typeof o === 'undefined';
2295
* A convenience method for detecting a legitimate non-null value.
2296
* Returns false for null/undefined/NaN, true for other values,
2297
* including 0/false/''
2300
* @param o The item to test.
2301
* @return {boolean} true if it is not null/undefined/NaN || false.
2303
L.isValue = function(o) {
2310
case 'null': // fallthru
2320
* Returns the current time in milliseconds.
2323
* @return {Number} Current time in milliseconds.
2327
L.now = Date.now || function () {
2328
return new Date().getTime();
2332
* Lightweight version of <code>Y.substitute</code>. Uses the same template
2333
* structure as <code>Y.substitute</code>, but doesn't support recursion,
2334
* auto-object coersion, or formats.
2336
* @param {string} s String to be modified.
2337
* @param {object} o Object containing replacement values.
2338
* @return {string} the substitute result.
2342
L.sub = function(s, o) {
2343
return s.replace ? s.replace(SUBREGEX, function (match, key) {
2344
return L.isUndefined(o[key]) ? match : o[key];
2349
* Returns a string without any leading or trailing whitespace. If
2350
* the input is not a string, the input will be returned untouched.
2353
* @param s {string} the string to trim.
2354
* @return {string} the trimmed string.
2356
L.trim = STRING_PROTO.trim ? function(s) {
2357
return s && s.trim ? s.trim() : s;
2360
return s.replace(TRIMREGEX, '');
2367
* Returns a string without any leading whitespace.
2370
* @param s {string} the string to trim.
2371
* @return {string} the trimmed string.
2373
L.trimLeft = STRING_PROTO.trimLeft ? function (s) {
2374
return s.trimLeft();
2376
return s.replace(/^\s+/, '');
2380
* Returns a string without any trailing whitespace.
2383
* @param s {string} the string to trim.
2384
* @return {string} the trimmed string.
2386
L.trimRight = STRING_PROTO.trimRight ? function (s) {
2387
return s.trimRight();
2389
return s.replace(/\s+$/, '');
2393
Returns one of the following strings, representing the type of the item passed
2410
* `typeof HTMLElementCollection` returns function in Safari, but
2411
`Y.Lang.type()` reports "object", which could be a good thing --
2412
but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2415
@param o the item to test.
2416
@return {string} the detected type.
2419
L.type = function(o) {
2420
return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2428
Native = Array.prototype,
2430
hasOwn = Object.prototype.hasOwnProperty;
2433
Provides utility methods for working with arrays. Additional array helpers can
2434
be found in the `collection` and `array-extras` modules.
2436
`Y.Array(thing)` returns a native array created from _thing_. Depending on
2437
_thing_'s type, one of the following will happen:
2439
* Arrays are returned unmodified unless a non-zero _startIndex_ is
2441
* Array-like collections (see `Array.test()`) are converted to arrays.
2442
* For everything else, a new array is created with _thing_ as the sole
2445
Note: elements that are also collections, such as `<form>` and `<select>`
2446
elements, are not automatically converted to arrays. To force a conversion,
2447
pass `true` as the value of the _force_ parameter.
2451
@param {Any} thing The thing to arrayify.
2452
@param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2453
collection, a subset of items starting at the specified index will be
2455
@param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2456
array-like collection no matter what.
2457
@return {Array} A native array created from _thing_, according to the rules
2460
function YArray(thing, startIndex, force) {
2463
/*jshint expr: true*/
2464
startIndex || (startIndex = 0);
2466
if (force || YArray.test(thing)) {
2467
// IE throws when trying to slice HTMLElement collections.
2469
return Native.slice.call(thing, startIndex);
2473
for (len = thing.length; startIndex < len; ++startIndex) {
2474
result.push(thing[startIndex]);
2487
Dedupes an array of strings, returning an array that's guaranteed to contain
2488
only one copy of a given string.
2490
This method differs from `Array.unique()` in that it's optimized for use only
2491
with strings, whereas `unique` may be used with other types (but is slower).
2492
Using `dedupe()` with non-string values may result in unexpected behavior.
2495
@param {String[]} array Array of strings to dedupe.
2496
@return {Array} Deduped copy of _array_.
2500
YArray.dedupe = function (array) {
2505
for (i = 0, len = array.length; i < len; ++i) {
2508
if (!hasOwn.call(hash, item)) {
2518
Executes the supplied function on each item in the array. This method wraps
2519
the native ES5 `Array.forEach()` method if available.
2522
@param {Array} array Array to iterate.
2523
@param {Function} fn Function to execute on each item in the array. The function
2524
will receive the following arguments:
2525
@param {Any} fn.item Current array item.
2526
@param {Number} fn.index Current array index.
2527
@param {Array} fn.array Array being iterated.
2528
@param {Object} [thisObj] `this` object to use when calling _fn_.
2529
@return {YUI} The YUI instance.
2532
YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2533
Native.forEach.call(array || [], fn, thisObj || Y);
2535
} : function (array, fn, thisObj) {
2536
for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2538
fn.call(thisObj || Y, array[i], i, array);
2553
Returns an object using the first array as keys and the second as values. If
2554
the second array is not provided, or if it doesn't contain the same number of
2555
values as the first array, then `true` will be used in place of the missing
2560
Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2561
// => {a: 'foo', b: 'bar', c: true}
2564
@param {String[]} keys Array of strings to use as keys.
2565
@param {Array} [values] Array to use as values.
2566
@return {Object} Hash using the first array as keys and the second as values.
2569
YArray.hash = function (keys, values) {
2571
vlen = (values && values.length) || 0,
2574
for (i = 0, len = keys.length; i < len; ++i) {
2576
hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2584
Returns the index of the first item in the array that's equal (using a strict
2585
equality check) to the specified _value_, or `-1` if the value isn't found.
2587
This method wraps the native ES5 `Array.indexOf()` method if available.
2590
@param {Array} array Array to search.
2591
@param {Any} value Value to search for.
2592
@param {Number} [from=0] The index at which to begin the search.
2593
@return {Number} Index of the item strictly equal to _value_, or `-1` if not
2597
YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2598
return Native.indexOf.call(array, value, from);
2599
} : function (array, value, from) {
2600
// http://es5.github.com/#x15.4.4.14
2601
var len = array.length;
2604
from = (from > 0 || -1) * Math.floor(Math.abs(from));
2614
for (; from < len; ++from) {
2615
if (from in array && array[from] === value) {
2624
Numeric sort convenience function.
2626
The native `Array.prototype.sort()` function converts values to strings and
2627
sorts them in lexicographic order, which is unsuitable for sorting numeric
2628
values. Provide `Array.numericSort` as a custom sort function when you want
2629
to sort values in numeric order.
2633
[42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2634
// => [4, 8, 15, 16, 23, 42]
2637
@param {Number} a First value to compare.
2638
@param {Number} b Second value to compare.
2639
@return {Number} Difference between _a_ and _b_.
2642
YArray.numericSort = function (a, b) {
2647
Executes the supplied function on each item in the array. Returning a truthy
2648
value from the function will stop the processing of remaining items.
2651
@param {Array} array Array to iterate over.
2652
@param {Function} fn Function to execute on each item. The function will receive
2653
the following arguments:
2654
@param {Any} fn.value Current array item.
2655
@param {Number} fn.index Current array index.
2656
@param {Array} fn.array Array being iterated over.
2657
@param {Object} [thisObj] `this` object to use when calling _fn_.
2658
@return {Boolean} `true` if the function returns a truthy value on any of the
2659
items in the array; `false` otherwise.
2662
YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2663
return Native.some.call(array, fn, thisObj);
2664
} : function (array, fn, thisObj) {
2665
for (var i = 0, len = array.length; i < len; ++i) {
2666
if (i in array && fn.call(thisObj, array[i], i, array)) {
2675
Evaluates _obj_ to determine if it's an array, an array-like collection, or
2676
something else. This is useful when working with the function `arguments`
2677
collection and `HTMLElement` collections.
2679
Note: This implementation doesn't consider elements that are also
2680
collections, such as `<form>` and `<select>`, to be array-like.
2683
@param {Object} obj Object to test.
2684
@return {Number} A number indicating the results of the test:
2686
* 0: Neither an array nor an array-like collection.
2688
* 2: Array-like collection.
2692
YArray.test = function (obj) {
2695
if (Lang.isArray(obj)) {
2697
} else if (Lang.isObject(obj)) {
2699
// indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
2700
// or functions without apply/call (Safari
2701
// HTMLElementCollection bug).
2702
if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
2711
* The YUI module contains the components required for building the YUI
2712
* seed file. This includes the script loading mechanism, a simple queue,
2713
* and the core utilities for the library.
2715
* @submodule yui-base
2719
* A simple FIFO queue. Items are added to the Queue with add(1..n items) and
2720
* removed using next().
2724
* @param {MIXED} item* 0..n items to seed the queue.
2728
this.add.apply(this, arguments);
2733
* Initialize the queue
2740
* The collection of enqueued items
2750
* Get the next item in the queue. FIFO support
2753
* @return {MIXED} the next item in the queue.
2756
return this._q.shift();
2760
* Get the last in the queue. LIFO support.
2763
* @return {MIXED} the last item in the queue.
2766
return this._q.pop();
2770
* Add 0..n items to the end of the queue.
2773
* @param {MIXED} item* 0..n items.
2774
* @return {object} this queue.
2777
this._q.push.apply(this._q, arguments);
2783
* Returns the current number of queued items.
2786
* @return {Number} The size.
2789
return this._q.length;
2795
YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2798
The YUI module contains the components required for building the YUI seed file.
2799
This includes the script loading mechanism, a simple queue, and the core
2800
utilities for the library.
2806
var CACHED_DELIMITER = '__',
2808
hasOwn = Object.prototype.hasOwnProperty,
2809
isObject = Y.Lang.isObject;
2812
Returns a wrapper for a function which caches the return value of that function,
2813
keyed off of the combined string representation of the argument values provided
2814
when the wrapper is called.
2816
Calling this function again with the same arguments will return the cached value
2817
rather than executing the wrapped function.
2819
Note that since the cache is keyed off of the string representation of arguments
2820
passed to the wrapper function, arguments that aren't strings and don't provide
2821
a meaningful `toString()` method may result in unexpected caching behavior. For
2822
example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2823
string `[object Object]` when used as a cache key.
2826
@param {Function} source The function to memoize.
2827
@param {Object} [cache={}] Object in which to store cached values. You may seed
2828
this object with pre-existing cached values if desired.
2829
@param {any} [refetch] If supplied, this value is compared with the cached value
2830
using a `==` comparison. If the values are equal, the wrapped function is
2831
executed again even though a cached value exists.
2832
@return {Function} Wrapped function.
2835
Y.cached = function (source, cache, refetch) {
2836
/*jshint expr: true*/
2837
cache || (cache = {});
2839
return function (arg) {
2840
var key = arguments.length > 1 ?
2841
Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2844
/*jshint eqeqeq: false*/
2845
if (!(key in cache) || (refetch && cache[key] == refetch)) {
2846
cache[key] = source.apply(source, arguments);
2854
Returns the `location` object from the window/frame in which this YUI instance
2855
operates, or `undefined` when executing in a non-browser environment
2858
It is _not_ recommended to hold references to the `window.location` object
2859
outside of the scope of a function in which its properties are being accessed or
2860
its methods are being called. This is because of a nasty bug/issue that exists
2861
in both Safari and MobileSafari browsers:
2862
[WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
2865
@return {location} The `location` object from the window/frame in which this YUI
2869
Y.getLocation = function () {
2870
// It is safer to look this up every time because yui-base is attached to a
2871
// YUI instance before a user's config is applied; i.e. `Y.config.win` does
2872
// not point the correct window object when this file is loaded.
2873
var win = Y.config.win;
2875
// It is not safe to hold a reference to the `location` object outside the
2876
// scope in which it is being used. The WebKit engine used in Safari and
2877
// MobileSafari will "disconnect" the `location` object from the `window`
2878
// when a page is restored from back/forward history cache.
2879
return win && win.location;
2883
Returns a new object containing all of the properties of all the supplied
2884
objects. The properties from later objects will overwrite those in earlier
2887
Passing in a single object will create a shallow copy of it. For a deep copy,
2891
@param {Object} objects* One or more objects to merge.
2892
@return {Object} A new merged object.
2894
Y.merge = function () {
2896
len = arguments.length,
2901
for (; i < len; ++i) {
2905
if (hasOwn.call(obj, key)) {
2906
result[key] = obj[key];
2915
Mixes _supplier_'s properties into _receiver_.
2917
Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
2918
shadowed unless the _overwrite_ parameter is `true`, and will not be merged
2919
unless the _merge_ parameter is `true`.
2921
In the default mode (0), only properties the supplier owns are copied (prototype
2922
properties are not copied). The following copying modes are available:
2924
* `0`: _Default_. Object to object.
2925
* `1`: Prototype to prototype.
2926
* `2`: Prototype to prototype and object to object.
2927
* `3`: Prototype to object.
2928
* `4`: Object to prototype.
2931
@param {Function|Object} receiver The object or function to receive the mixed
2933
@param {Function|Object} supplier The object or function supplying the
2934
properties to be mixed.
2935
@param {Boolean} [overwrite=false] If `true`, properties that already exist
2936
on the receiver will be overwritten with properties from the supplier.
2937
@param {String[]} [whitelist] An array of property names to copy. If
2938
specified, only the whitelisted properties will be copied, and all others
2940
@param {Number} [mode=0] Mix mode to use. See above for available modes.
2941
@param {Boolean} [merge=false] If `true`, objects and arrays that already
2942
exist on the receiver will have the corresponding object/array from the
2943
supplier merged into them, rather than being skipped or overwritten. When
2944
both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
2945
@return {Function|Object|YUI} The receiver, or the YUI instance if the
2946
specified receiver is falsy.
2948
Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
2949
var alwaysOverwrite, exists, from, i, key, len, to;
2951
// If no supplier is given, we return the receiver. If no receiver is given,
2952
// we return Y. Returning Y doesn't make much sense to me, but it's
2953
// grandfathered in for backcompat reasons.
2954
if (!receiver || !supplier) {
2955
return receiver || Y;
2959
// In mode 2 (prototype to prototype and object to object), we recurse
2960
// once to do the proto to proto mix. The object to object mix will be
2961
// handled later on.
2963
Y.mix(receiver.prototype, supplier.prototype, overwrite,
2964
whitelist, 0, merge);
2967
// Depending on which mode is specified, we may be copying from or to
2968
// the prototypes of the supplier and receiver.
2969
from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
2970
to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
2972
// If either the supplier or receiver doesn't actually have a
2973
// prototype property, then we could end up with an undefined `from`
2974
// or `to`. If that happens, we abort and return the receiver.
2983
// If `overwrite` is truthy and `merge` is falsy, then we can skip a
2984
// property existence check on each iteration and save some time.
2985
alwaysOverwrite = overwrite && !merge;
2988
for (i = 0, len = whitelist.length; i < len; ++i) {
2991
// We call `Object.prototype.hasOwnProperty` instead of calling
2992
// `hasOwnProperty` on the object itself, since the object's
2993
// `hasOwnProperty` method may have been overridden or removed.
2994
// Also, some native objects don't implement a `hasOwnProperty`
2996
if (!hasOwn.call(from, key)) {
3000
// The `key in to` check here is (sadly) intentional for backwards
3001
// compatibility reasons. It prevents undesired shadowing of
3002
// prototype members on `to`.
3003
exists = alwaysOverwrite ? false : key in to;
3005
if (merge && exists && isObject(to[key], true)
3006
&& isObject(from[key], true)) {
3007
// If we're in merge mode, and the key is present on both
3008
// objects, and the value on both objects is either an object or
3009
// an array (but not a function), then we recurse to merge the
3010
// `from` value into the `to` value instead of overwriting it.
3012
// Note: It's intentional that the whitelist isn't passed to the
3013
// recursive call here. This is legacy behavior that lots of
3014
// code still depends on.
3015
Y.mix(to[key], from[key], overwrite, null, 0, merge);
3016
} else if (overwrite || !exists) {
3017
// We're not in merge mode, so we'll only copy the `from` value
3018
// to the `to` value if we're in overwrite mode or if the
3019
// current key doesn't exist on the `to` object.
3020
to[key] = from[key];
3025
// The code duplication here is for runtime performance reasons.
3026
// Combining whitelist and non-whitelist operations into a single
3027
// loop or breaking the shared logic out into a function both result
3028
// in worse performance, and Y.mix is critical enough that the byte
3029
// tradeoff is worth it.
3030
if (!hasOwn.call(from, key)) {
3034
// The `key in to` check here is (sadly) intentional for backwards
3035
// compatibility reasons. It prevents undesired shadowing of
3036
// prototype members on `to`.
3037
exists = alwaysOverwrite ? false : key in to;
3039
if (merge && exists && isObject(to[key], true)
3040
&& isObject(from[key], true)) {
3041
Y.mix(to[key], from[key], overwrite, null, 0, merge);
3042
} else if (overwrite || !exists) {
3043
to[key] = from[key];
3047
// If this is an IE browser with the JScript enumeration bug, force
3048
// enumeration of the buggy properties by making a recursive call with
3049
// the buggy properties as the whitelist.
3050
if (Y.Object._hasEnumBug) {
3051
Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
3058
* The YUI module contains the components required for building the YUI
3059
* seed file. This includes the script loading mechanism, a simple queue,
3060
* and the core utilities for the library.
3062
* @submodule yui-base
3066
* Adds utilities to the YUI instance for working with objects.
3072
hasOwn = Object.prototype.hasOwnProperty,
3074
UNDEFINED, // <-- Note the comma. We're still declaring vars.
3077
* Returns a new object that uses _obj_ as its prototype. This method wraps the
3078
* native ES5 `Object.create()` method if available, but doesn't currently
3079
* pass through `Object.create()`'s second argument (properties) in order to
3080
* ensure compatibility with older browsers.
3083
* @param {Object} obj Prototype object.
3084
* @return {Object} New object using _obj_ as its prototype.
3087
O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
3088
// We currently wrap the native Object.create instead of simply aliasing it
3089
// to ensure consistency with our fallback shim, which currently doesn't
3090
// support Object.create()'s second argument (properties). Once we have a
3091
// safe fallback for the properties arg, we can stop wrapping
3093
return Object.create(obj);
3095
// Reusable constructor function for the Object.create() shim.
3099
return function (obj) {
3106
* Property names that IE doesn't enumerate in for..in loops, even when they
3107
* should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
3108
* manually enumerate these properties.
3110
* @property _forceEnum
3115
forceEnum = O._forceEnum = [
3118
'propertyIsEnumerable',
3125
* `true` if this browser has the JScript enumeration bug that prevents
3126
* enumeration of the properties named in the `_forceEnum` array, `false`
3130
* - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
3131
* - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
3133
* @property _hasEnumBug
3138
hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
3141
* `true` if this browser incorrectly considers the `prototype` property of
3142
* functions to be enumerable. Currently known to affect Opera 11.50.
3144
* @property _hasProtoEnumBug
3149
hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
3152
* Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
3153
* exists only on _obj_'s prototype. This is essentially a safer version of
3154
* `obj.hasOwnProperty()`.
3157
* @param {Object} obj Object to test.
3158
* @param {String} key Property name to look for.
3159
* @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3162
owns = O.owns = function (obj, key) {
3163
return !!obj && hasOwn.call(obj, key);
3164
}; // <-- End of var declarations.
3167
* Alias for `owns()`.
3170
* @param {Object} obj Object to test.
3171
* @param {String} key Property name to look for.
3172
* @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3178
* Returns an array containing the object's enumerable keys. Does not include
3179
* prototype keys or non-enumerable keys.
3181
* Note that keys are returned in enumeration order (that is, in the same order
3182
* that they would be enumerated by a `for-in` loop), which may not be the same
3183
* as the order in which they were defined.
3185
* This method is an alias for the native ES5 `Object.keys()` method if
3190
* Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
3191
* // => ['a', 'b', 'c']
3194
* @param {Object} obj An object.
3195
* @return {String[]} Array of keys.
3198
O.keys = Lang._isNative(Object.keys) ? Object.keys : function (obj) {
3199
if (!Lang.isObject(obj)) {
3200
throw new TypeError('Object.keys called on a non-object');
3206
if (hasProtoEnumBug && typeof obj === 'function') {
3208
if (owns(obj, key) && key !== 'prototype') {
3214
if (owns(obj, key)) {
3221
for (i = 0, len = forceEnum.length; i < len; ++i) {
3224
if (owns(obj, key)) {
3234
* Returns an array containing the values of the object's enumerable keys.
3236
* Note that values are returned in enumeration order (that is, in the same
3237
* order that they would be enumerated by a `for-in` loop), which may not be the
3238
* same as the order in which they were defined.
3242
* Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
3243
* // => ['foo', 'bar', 'baz']
3246
* @param {Object} obj An object.
3247
* @return {Array} Array of values.
3250
O.values = function (obj) {
3251
var keys = O.keys(obj),
3256
for (; i < len; ++i) {
3257
values.push(obj[keys[i]]);
3264
* Returns the number of enumerable keys owned by an object.
3267
* @param {Object} obj An object.
3268
* @return {Number} The object's size.
3271
O.size = function (obj) {
3273
return O.keys(obj).length;
3275
return 0; // Legacy behavior for non-objects.
3280
* Returns `true` if the object owns an enumerable property with the specified
3284
* @param {Object} obj An object.
3285
* @param {any} value The value to search for.
3286
* @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3289
O.hasValue = function (obj, value) {
3290
return Y.Array.indexOf(O.values(obj), value) > -1;
3294
* Executes a function on each enumerable property in _obj_. The function
3295
* receives the value, the key, and the object itself as parameters (in that
3298
* By default, only properties owned by _obj_ are enumerated. To include
3299
* prototype properties, set the _proto_ parameter to `true`.
3302
* @param {Object} obj Object to enumerate.
3303
* @param {Function} fn Function to execute on each enumerable property.
3304
* @param {mixed} fn.value Value of the current property.
3305
* @param {String} fn.key Key of the current property.
3306
* @param {Object} fn.obj Object being enumerated.
3307
* @param {Object} [thisObj] `this` object to use when calling _fn_.
3308
* @param {Boolean} [proto=false] Include prototype properties.
3309
* @return {YUI} the YUI instance.
3313
O.each = function (obj, fn, thisObj, proto) {
3317
if (proto || owns(obj, key)) {
3318
fn.call(thisObj || Y, obj[key], key, obj);
3326
* Executes a function on each enumerable property in _obj_, but halts if the
3327
* function returns a truthy value. The function receives the value, the key,
3328
* and the object itself as paramters (in that order).
3330
* By default, only properties owned by _obj_ are enumerated. To include
3331
* prototype properties, set the _proto_ parameter to `true`.
3334
* @param {Object} obj Object to enumerate.
3335
* @param {Function} fn Function to execute on each enumerable property.
3336
* @param {mixed} fn.value Value of the current property.
3337
* @param {String} fn.key Key of the current property.
3338
* @param {Object} fn.obj Object being enumerated.
3339
* @param {Object} [thisObj] `this` object to use when calling _fn_.
3340
* @param {Boolean} [proto=false] Include prototype properties.
3341
* @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3342
* `false` otherwise.
3345
O.some = function (obj, fn, thisObj, proto) {
3349
if (proto || owns(obj, key)) {
3350
if (fn.call(thisObj || Y, obj[key], key, obj)) {
3360
* Retrieves the sub value at the provided path,
3361
* from the value object provided.
3365
* @param o The object from which to extract the property value.
3366
* @param path {Array} A path array, specifying the object traversal path
3367
* from which to obtain the sub value.
3368
* @return {Any} The value stored in the path, undefined if not found,
3369
* undefined if the source is not an object. Returns the source object
3370
* if an empty path is provided.
3372
O.getValue = function(o, path) {
3373
if (!Lang.isObject(o)) {
3381
for (i = 0; o !== UNDEFINED && i < l; i++) {
3389
* Sets the sub-attribute value at the provided path on the
3390
* value object. Returns the modified value object, or
3391
* undefined if the path is invalid.
3395
* @param o The object on which to set the sub value.
3396
* @param path {Array} A path array, specifying the object traversal path
3397
* at which to set the sub value.
3398
* @param val {Any} The new value for the sub-attribute.
3399
* @return {Object} The modified object, with the new sub value set, or
3400
* undefined, if the path was invalid.
3402
O.setValue = function(o, path, val) {
3405
leafIdx = p.length - 1,
3409
for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3413
if (ref !== UNDEFINED) {
3424
* Returns `true` if the object has no enumerable properties of its own.
3427
* @param {Object} obj An object.
3428
* @return {Boolean} `true` if the object is empty.
3432
O.isEmpty = function (obj) {
3433
return !O.keys(Object(obj)).length;
3436
* The YUI module contains the components required for building the YUI seed
3437
* file. This includes the script loading mechanism, a simple queue, and the
3438
* core utilities for the library.
3440
* @submodule yui-base
3444
* YUI user agent detection.
3445
* Do not fork for a browser if it can be avoided. Use feature detection when
3446
* you can. Use the user agent as a last resort. For all fields listed
3447
* as @type float, UA stores a version number for the browser engine,
3448
* 0 otherwise. This value may or may not map to the version number of
3449
* the browser using the engine. The value is presented as a float so
3450
* that it can easily be used for boolean evaluation as well as for
3451
* looking for a particular range of versions. Because of this,
3452
* some of the granularity of the version info may be lost. The fields that
3453
* are @type string default to null. The API docs list the values that
3454
* these fields can have.
3460
* Static method on `YUI.Env` for parsing a UA string. Called at instantiation
3461
* to populate `Y.UA`.
3465
* @param {String} [subUA=navigator.userAgent] UA string to parse
3466
* @return {Object} The Y.UA object
3468
YUI.Env.parseUA = function(subUA) {
3470
var numberify = function(s) {
3472
return parseFloat(s.replace(/\./g, function() {
3473
return (c++ === 1) ? '' : '.';
3479
nav = win && win.navigator,
3484
* Internet Explorer version number or 0. Example: 6
3492
* Opera version number or 0. Example: 9.2
3500
* Gecko engine revision number. Will evaluate to 1 if Gecko
3501
* is detected but the revision could not be found. Other browsers
3502
* will be 0. Example: 1.8
3504
* Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
3505
* Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3506
* Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3507
* Firefox 3.0 <-- 1.9
3508
* Firefox 3.5 <-- 1.91
3517
* AppleWebKit version. KHTML browsers that are not WebKit browsers
3518
* will evaluate to 1, other browsers 0. Example: 418.9
3520
* Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3521
* latest available for Mac OSX 10.3.
3522
* Safari 2.0.2: 416 <-- hasOwnProperty introduced
3523
* Safari 2.0.4: 418 <-- preventDefault fixed
3524
* Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3525
* different versions of webkit
3526
* Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
3527
* updated, but not updated
3528
* to the latest patch.
3529
* Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native
3530
* SVG and many major issues fixed).
3531
* Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic
3532
* update from 2.x via the 10.4.11 OS patch.
3533
* Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
3534
* yahoo.com user agent hack removed.
3536
* http://en.wikipedia.org/wiki/Safari_version_history
3544
* Safari will be detected as webkit, but this property will also
3545
* be populated with the Safari version number
3553
* Chrome will be detected as webkit, but this property will also
3554
* be populated with the Chrome version number
3562
* The mobile property will be set to a string containing any relevant
3563
* user agent information when a modern mobile browser is detected.
3564
* Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3565
* devices with the WebKit-based browser, and Opera Mini.
3574
* Adobe AIR version number or 0. Only populated if webkit is detected.
3581
* PhantomJS version number or 0. Only populated if webkit is detected.
3583
* @property phantomjs
3588
* Detects Apple iPad's OS version
3595
* Detects Apple iPhone's OS version
3602
* Detects Apples iPod's OS version
3609
* General truthy check for iPad, iPhone or iPod
3617
* Detects Googles Android OS version
3624
* Detects Kindle Silk
3631
* Detects Kindle Silk Acceleration
3638
* Detects Palms WebOS version
3646
* Google Caja version number or 0.
3650
caja: nav && nav.cajaVersion,
3653
* Set to true if the page appears to be in SSL
3661
* The operating system. Currently only detecting windows or macintosh
3670
* The Nodejs Version
3678
* Window8/IE10 Application host environment
3683
winjs: !!((typeof Windows !== "undefined") && Windows.System),
3685
* Are touch/msPointer events available on this device
3686
* @property touchEnabled
3693
ua = subUA || nav && nav.userAgent,
3695
loc = win && win.location,
3697
href = loc && loc.href,
3702
* The User Agent string that was parsed
3703
* @property userAgent
3710
o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3714
if ((/windows|win32/i).test(ua)) {
3716
} else if ((/macintosh|mac_powerpc/i).test(ua)) {
3718
} else if ((/android/i).test(ua)) {
3720
} else if ((/symbos/i).test(ua)) {
3722
} else if ((/linux/i).test(ua)) {
3724
} else if ((/rhino/i).test(ua)) {
3728
// Modern KHTML browsers should qualify as Safari X-Grade
3729
if ((/KHTML/).test(ua)) {
3732
if ((/IEMobile|XBLWP7/).test(ua)) {
3733
o.mobile = 'windows';
3735
if ((/Fennec/).test(ua)) {
3738
// Modern WebKit browsers are at least X-Grade
3739
m = ua.match(/AppleWebKit\/([^\s]*)/);
3741
o.webkit = numberify(m[1]);
3742
o.safari = o.webkit;
3744
if (/PhantomJS/.test(ua)) {
3745
m = ua.match(/PhantomJS\/([^\s]*)/);
3747
o.phantomjs = numberify(m[1]);
3751
// Mobile browser check
3752
if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
3753
o.mobile = 'Apple'; // iPhone or iPod Touch
3755
m = ua.match(/OS ([^\s]*)/);
3757
m = numberify(m[1].replace('_', '.'));
3761
o.ipad = o.ipod = o.iphone = 0;
3763
m = ua.match(/iPad|iPod|iPhone/);
3765
o[m[0].toLowerCase()] = o.ios;
3768
m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3770
// Nokia N-series, webOS, ex: NokiaN95
3773
if (/webOS/.test(ua)) {
3775
m = ua.match(/webOS\/([^\s]*);/);
3777
o.webos = numberify(m[1]);
3780
if (/ Android/.test(ua)) {
3781
if (/Mobile/.test(ua)) {
3782
o.mobile = 'Android';
3784
m = ua.match(/Android ([^\s]*);/);
3786
o.android = numberify(m[1]);
3790
if (/Silk/.test(ua)) {
3791
m = ua.match(/Silk\/([^\s]*)\)/);
3793
o.silk = numberify(m[1]);
3796
o.android = 2.34; //Hack for desktop mode in Kindle
3799
if (/Accelerated=true/.test(ua)) {
3805
m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
3806
if (m && m[1] && m[2]) {
3807
o.chrome = numberify(m[2]); // Chrome
3808
o.safari = 0; //Reset safari back to 0
3809
if (m[1] === 'CrMo') {
3810
o.mobile = 'chrome';
3813
m = ua.match(/AdobeAIR\/([^\s]*)/);
3815
o.air = m[0]; // Adobe AIR 1.0 or better
3820
if (!o.webkit) { // not webkit
3821
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3822
if (/Opera/.test(ua)) {
3823
m = ua.match(/Opera[\s\/]([^\s]*)/);
3825
o.opera = numberify(m[1]);
3827
m = ua.match(/Version\/([^\s]*)/);
3829
o.opera = numberify(m[1]); // opera 10+
3832
if (/Opera Mobi/.test(ua)) {
3834
m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
3836
o.opera = numberify(m[1]);
3839
m = ua.match(/Opera Mini[^;]*/);
3842
o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3844
} else { // not opera or webkit
3845
m = ua.match(/MSIE\s([^;]*)/);
3847
o.ie = numberify(m[1]);
3848
} else { // not opera, webkit, or ie
3849
m = ua.match(/Gecko\/([^\s]*)/);
3851
o.gecko = 1; // Gecko detected, look for revision
3852
m = ua.match(/rv:([^\s\)]*)/);
3854
o.gecko = numberify(m[1]);
3862
//Check for known properties to tell if touch events are enabled on this device or if
3863
//the number of MSPointer touchpoints on this device is greater than 0.
3864
if (win && nav && !(o.chrome && o.chrome < 6)) {
3865
o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
3868
//It was a parsed UA, do not assign the global value.
3871
if (typeof process === 'object') {
3873
if (process.versions && process.versions.node) {
3875
o.os = process.platform;
3876
o.nodejs = numberify(process.versions.node);
3888
Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3891
Performs a simple comparison between two version numbers, accounting for
3892
standard versioning logic such as the fact that "535.8" is a lower version than
3893
"535.24", even though a simple numerical comparison would indicate that it's
3894
greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
3895
considered equivalent.
3897
Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
3898
1 if _a_ is higher than _b_.
3900
Versions may be numbers or strings containing numbers and dots. For example,
3901
both `535` and `"535.8.10"` are acceptable. A version string containing
3902
non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
3904
@method compareVersions
3905
@param {Number|String} a First version number to compare.
3906
@param {Number|String} b Second version number to compare.
3907
@return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
3910
Y.UA.compareVersions = function (a, b) {
3911
var aPart, aParts, bPart, bParts, i, len;
3917
aParts = (a + '').split('.');
3918
bParts = (b + '').split('.');
3920
for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
3921
aPart = parseInt(aParts[i], 10);
3922
bPart = parseInt(bParts[i], 10);
3924
/*jshint expr: true*/
3925
isNaN(aPart) && (aPart = 0);
3926
isNaN(bPart) && (bPart = 0);
3928
if (aPart < bPart) {
3932
if (aPart > bPart) {
3940
"anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
3941
"anim-shape-transform": ["anim-shape"],
3942
"app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],
3943
"attribute": ["attribute-base","attribute-complex"],
3944
"attribute-events": ["attribute-observable"],
3945
"autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
3946
"axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
3947
"axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
3948
"base": ["base-base","base-pluginhost","base-build"],
3949
"cache": ["cache-base","cache-offline","cache-plugin"],
3950
"charts": ["charts-base"],
3951
"collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
3952
"color": ["color-base","color-hsl","color-harmony"],
3953
"controller": ["router"],
3954
"dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
3955
"datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
3956
"datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
3957
"datatype": ["datatype-date","datatype-number","datatype-xml"],
3958
"datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
3959
"datatype-number": ["datatype-number-parse","datatype-number-format"],
3960
"datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
3961
"dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
3962
"dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
3963
"editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
3964
"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"],
3965
"event-custom": ["event-custom-base","event-custom-complex"],
3966
"event-gestures": ["event-flick","event-move"],
3967
"handlebars": ["handlebars-compiler"],
3968
"highlight": ["highlight-base","highlight-accentfold"],
3969
"history": ["history-base","history-hash","history-hash-ie","history-html5"],
3970
"io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
3971
"json": ["json-parse","json-stringify"],
3972
"loader": ["loader-base","loader-rollup","loader-yui3"],
3973
"node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
3974
"pluginhost": ["pluginhost-base","pluginhost-config"],
3975
"querystring": ["querystring-parse","querystring-stringify"],
3976
"recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
3977
"resize": ["resize-base","resize-proxy","resize-constrain"],
3978
"slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
3979
"template": ["template-base","template-micro"],
3980
"text": ["text-accentfold","text-wordbreak"],
3981
"widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
3985
}, '3.9.1', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
3986
YUI.add('get', function (Y, NAME) {
3988
/*jslint boss:true, expr:true, laxbreak: true */
3991
Provides dynamic loading of remote JavaScript and CSS resources.
4000
CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode()
4005
// -- Public Properties ----------------------------------------------------
4008
Default options for CSS requests. Options specified here will override
4009
global defaults for CSS requests.
4011
See the `options` property for all available options.
4013
@property cssOptions
4023
doc : Y.config.linkDoc || Y.config.doc,
4028
Default options for JS requests. Options specified here will override global
4029
defaults for JS requests.
4031
See the `options` property for all available options.
4040
doc : Y.config.scriptDoc || Y.config.doc
4044
Default options to use for all requests.
4046
Note that while all available options are documented here for ease of
4047
discovery, some options (like callback functions) only make sense at the
4050
Callback functions specified via the options object or the `options`
4051
parameter of the `css()`, `js()`, or `load()` methods will receive the
4052
transaction object as a parameter. See `Y.Get.Transaction` for details on
4053
the properties and methods available on transactions.
4057
@property {Object} options
4059
@property {Boolean} [options.async=false] Whether or not to load scripts
4060
asynchronously, meaning they're requested in parallel and execution
4061
order is not guaranteed. Has no effect on CSS, since CSS is always
4062
loaded asynchronously.
4064
@property {Object} [options.attributes] HTML attribute name/value pairs that
4065
should be added to inserted nodes. By default, the `charset` attribute
4066
will be set to "utf-8" and nodes will be given an auto-generated `id`
4067
attribute, but you can override these with your own values if desired.
4069
@property {Boolean} [options.autopurge] Whether or not to automatically
4070
purge inserted nodes after the purge threshold is reached. This is
4071
`true` by default for JavaScript, but `false` for CSS since purging a
4072
CSS node will also remove any styling applied by the referenced file.
4074
@property {Object} [options.context] `this` object to use when calling
4075
callback functions. Defaults to the transaction object.
4077
@property {Mixed} [options.data] Arbitrary data object to pass to "on*"
4080
@property {Document} [options.doc] Document into which nodes should be
4081
inserted. By default, the current document is used.
4083
@property {HTMLElement|String} [options.insertBefore] HTML element or id
4084
string of an element before which all generated nodes should be
4085
inserted. If not specified, Get will automatically determine the best
4086
place to insert nodes for maximum compatibility.
4088
@property {Function} [options.onEnd] Callback to execute after a transaction
4089
is complete, regardless of whether it succeeded or failed.
4091
@property {Function} [options.onFailure] Callback to execute after a
4092
transaction fails, times out, or is aborted.
4094
@property {Function} [options.onProgress] Callback to execute after each
4095
individual request in a transaction either succeeds or fails.
4097
@property {Function} [options.onSuccess] Callback to execute after a
4098
transaction completes successfully with no errors. Note that in browsers
4099
that don't support the `error` event on CSS `<link>` nodes, a failed CSS
4100
request may still be reported as a success because in these browsers
4101
it can be difficult or impossible to distinguish between success and
4102
failure for CSS resources.
4104
@property {Function} [options.onTimeout] Callback to execute after a
4105
transaction times out.
4107
@property {Number} [options.pollInterval=50] Polling interval (in
4108
milliseconds) for detecting CSS load completion in browsers that don't
4109
support the `load` event on `<link>` nodes. This isn't used for
4112
@property {Number} [options.purgethreshold=20] Number of nodes to insert
4113
before triggering an automatic purge when `autopurge` is `true`.
4115
@property {Number} [options.timeout] Number of milliseconds to wait before
4116
aborting a transaction. When a timeout occurs, the `onTimeout` callback
4117
is called, followed by `onFailure` and finally `onEnd`. By default,
4118
there is no timeout.
4120
@property {String} [options.type] Resource type ("css" or "js"). This option
4121
is set automatically by the `css()` and `js()` functions and will be
4122
ignored there, but may be useful when using the `load()` function. If
4123
not specified, the type will be inferred from the URL, defaulting to
4124
"js" if the URL doesn't contain a recognizable file extension.
4134
// -- Protected Properties -------------------------------------------------
4137
Regex that matches a CSS URL. Used to guess the file type when it's not
4147
REGEX_CSS: /\.css(?:[?;].*)?$/i,
4150
Regex that matches a JS URL. Used to guess the file type when it's not
4160
REGEX_JS : /\.js(?:[?;].*)?$/i,
4163
Contains information about the current environment, such as what script and
4164
link injection features it supports.
4166
This object is created and populated the first time the `_getEnv()` method
4177
Mapping of document _yuid strings to <head> or <base> node references so we
4178
don't have to look the node up each time we want to insert a request node.
4180
@property _insertCache
4189
Information about the currently pending transaction, if any.
4191
This is actually an object with two properties: `callback`, containing the
4192
optional callback passed to `css()`, `load()`, or `js()`; and `transaction`,
4193
containing the actual transaction instance.
4204
HTML nodes eligible to be purged next time autopurge is triggered.
4206
@property _purgeNodes
4215
Queued transactions and associated callbacks.
4225
// -- Public Methods -------------------------------------------------------
4228
Aborts the specified transaction.
4230
This will cause the transaction's `onFailure` callback to be called and
4231
will prevent any new script and link nodes from being added to the document,
4232
but any resources that have already been requested will continue loading
4233
(there's no safe way to prevent this, unfortunately).
4235
*Note:* This method is deprecated as of 3.5.0, and will be removed in a
4236
future version of YUI. Use the transaction-level `abort()` method instead.
4239
@param {Get.Transaction} transaction Transaction to abort.
4240
@deprecated Use the `abort()` method on the transaction instead.
4243
abort: function (transaction) {
4244
var i, id, item, len, pending;
4246
Y.log('`Y.Get.abort()` is deprecated as of 3.5.0. Use the `abort()` method on the transaction instead.', 'warn', 'get');
4248
if (!transaction.abort) {
4250
pending = this._pending;
4253
if (pending && pending.transaction.id === id) {
4254
transaction = pending.transaction;
4255
this._pending = null;
4257
for (i = 0, len = this._queue.length; i < len; ++i) {
4258
item = this._queue[i].transaction;
4260
if (item.id === id) {
4262
this._queue.splice(i, 1);
4269
transaction && transaction.abort();
4273
Loads one or more CSS files.
4275
The _urls_ parameter may be provided as a URL string, a request object,
4276
or an array of URL strings and/or request objects.
4278
A request object is just an object that contains a `url` property and zero
4279
or more options that should apply specifically to that request.
4280
Request-specific options take priority over transaction-level options and
4283
URLs may be relative or absolute, and do not have to have the same origin
4284
as the current page.
4286
The `options` parameter may be omitted completely and a callback passed in
4287
its place, if desired.
4291
// Load a single CSS file and log a message on completion.
4292
Y.Get.css('foo.css', function (err) {
4294
Y.log('foo.css failed to load!');
4296
Y.log('foo.css was loaded successfully');
4300
// Load multiple CSS files and log a message when all have finished
4302
var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css'];
4304
Y.Get.css(urls, function (err) {
4306
Y.log('one or more files failed to load!');
4308
Y.log('all files loaded successfully');
4312
// Specify transaction-level options, which will apply to all requests
4313
// within the transaction.
4315
attributes: {'class': 'my-css'},
4319
// Specify per-request options, which override transaction-level and
4322
{url: 'foo.css', attributes: {id: 'foo'}},
4323
{url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}}
4327
@param {String|Object|Array} urls URL string, request object, or array
4328
of URLs and/or request objects to load.
4329
@param {Object} [options] Options for this transaction. See the
4330
`Y.Get.options` property for a complete list of available options.
4331
@param {Function} [callback] Callback function to be called on completion.
4332
This is a general callback and will be called before any more granular
4333
callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4336
@param {Array|null} callback.err Array of errors that occurred during
4337
the transaction, or `null` on success.
4338
@param {Get.Transaction} callback.transaction Transaction object.
4340
@return {Get.Transaction} Transaction object.
4343
css: function (urls, options, callback) {
4344
return this._load('css', urls, options, callback);
4348
Loads one or more JavaScript resources.
4350
The _urls_ parameter may be provided as a URL string, a request object,
4351
or an array of URL strings and/or request objects.
4353
A request object is just an object that contains a `url` property and zero
4354
or more options that should apply specifically to that request.
4355
Request-specific options take priority over transaction-level options and
4358
URLs may be relative or absolute, and do not have to have the same origin
4359
as the current page.
4361
The `options` parameter may be omitted completely and a callback passed in
4362
its place, if desired.
4364
Scripts will be executed in the order they're specified unless the `async`
4365
option is `true`, in which case they'll be loaded in parallel and executed
4366
in whatever order they finish loading.
4370
// Load a single JS file and log a message on completion.
4371
Y.Get.js('foo.js', function (err) {
4373
Y.log('foo.js failed to load!');
4375
Y.log('foo.js was loaded successfully');
4379
// Load multiple JS files, execute them in order, and log a message when
4380
// all have finished loading.
4381
var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js'];
4383
Y.Get.js(urls, function (err) {
4385
Y.log('one or more files failed to load!');
4387
Y.log('all files loaded successfully');
4391
// Specify transaction-level options, which will apply to all requests
4392
// within the transaction.
4394
attributes: {'class': 'my-js'},
4398
// Specify per-request options, which override transaction-level and
4401
{url: 'foo.js', attributes: {id: 'foo'}},
4402
{url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}}
4406
@param {String|Object|Array} urls URL string, request object, or array
4407
of URLs and/or request objects to load.
4408
@param {Object} [options] Options for this transaction. See the
4409
`Y.Get.options` property for a complete list of available options.
4410
@param {Function} [callback] Callback function to be called on completion.
4411
This is a general callback and will be called before any more granular
4412
callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4415
@param {Array|null} callback.err Array of errors that occurred during
4416
the transaction, or `null` on success.
4417
@param {Get.Transaction} callback.transaction Transaction object.
4419
@return {Get.Transaction} Transaction object.
4423
js: function (urls, options, callback) {
4424
return this._load('js', urls, options, callback);
4428
Loads one or more CSS and/or JavaScript resources in the same transaction.
4430
Use this method when you want to load both CSS and JavaScript in a single
4431
transaction and be notified when all requested URLs have finished loading,
4434
Behavior and options are the same as for the `css()` and `js()` methods. If
4435
a resource type isn't specified in per-request options or transaction-level
4436
options, Get will guess the file type based on the URL's extension (`.css`
4437
or `.js`, with or without a following query string). If the file type can't
4438
be guessed from the URL, a warning will be logged and Get will assume the
4439
URL is a JavaScript resource.
4443
// Load both CSS and JS files in a single transaction, and log a message
4444
// when all files have finished loading.
4445
Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) {
4447
Y.log('one or more files failed to load!');
4449
Y.log('all files loaded successfully');
4454
@param {String|Object|Array} urls URL string, request object, or array
4455
of URLs and/or request objects to load.
4456
@param {Object} [options] Options for this transaction. See the
4457
`Y.Get.options` property for a complete list of available options.
4458
@param {Function} [callback] Callback function to be called on completion.
4459
This is a general callback and will be called before any more granular
4460
callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
4463
@param {Array|null} err Array of errors that occurred during the
4464
transaction, or `null` on success.
4465
@param {Get.Transaction} Transaction object.
4467
@return {Get.Transaction} Transaction object.
4471
load: function (urls, options, callback) {
4472
return this._load(null, urls, options, callback);
4475
// -- Protected Methods ----------------------------------------------------
4478
Triggers an automatic purge if the purge threshold has been reached.
4481
@param {Number} threshold Purge threshold to use, in milliseconds.
4486
_autoPurge: function (threshold) {
4487
if (threshold && this._purgeNodes.length >= threshold) {
4488
Y.log('autopurge triggered after ' + this._purgeNodes.length + ' nodes', 'info', 'get');
4489
this._purge(this._purgeNodes);
4494
Populates the `_env` property with information about the current
4498
@return {Object} Environment information.
4503
_getEnv: function () {
4504
var doc = Y.config.doc,
4507
// Note: some of these checks require browser sniffs since it's not
4508
// feasible to load test files on every pageview just to perform a
4509
// feature test. I'm sorry if this makes you sad.
4510
return (this._env = {
4512
// True if this is a browser that supports disabling async mode on
4513
// dynamically created script nodes. See
4514
// https://developer.mozilla.org/En/HTML/Element/Script#Attributes
4516
// IE10 doesn't return true for the MDN feature test, so setting it explicitly,
4517
// because it is async by default, and allows you to disable async by setting it to false
4518
async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10),
4520
// True if this browser fires an event when a dynamically injected
4521
// link node fails to load. This is currently true for Firefox 9+
4522
// and WebKit 535.24+
4523
cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0,
4525
// True if this browser fires an event when a dynamically injected
4526
// link node finishes loading. This is currently true for IE, Opera,
4527
// Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the
4528
// DOM 0 "onload" event, but not "load". All versions of IE fire
4530
// davglass: Seems that Chrome on Android needs this to be false.
4532
(!ua.gecko && !ua.webkit) || ua.gecko >= 9 ||
4533
ua.compareVersions(ua.webkit, 535.24) >= 0
4534
) && !(ua.chrome && ua.chrome <= 18),
4536
// True if this browser preserves script execution order while
4537
// loading scripts in parallel as long as the script node's `async`
4538
// attribute is set to false to explicitly disable async execution.
4539
preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10))
4543
_getTransaction: function (urls, options) {
4547
if (!Lang.isArray(urls)) {
4551
options = Y.merge(this.options, options);
4553
// Clone the attributes object so we don't end up modifying it by ref.
4554
options.attributes = Y.merge(this.options.attributes,
4555
options.attributes);
4557
for (i = 0, len = urls.length; i < len; ++i) {
4559
req = {attributes: {}};
4561
// If `url` is a string, we create a URL object for it, then mix in
4562
// global options and request-specific options. If it's an object
4563
// with a "url" property, we assume it's a request object containing
4564
// URL-specific options.
4565
if (typeof url === 'string') {
4567
} else if (url.url) {
4568
// URL-specific options override both global defaults and
4569
// request-specific options.
4570
Y.mix(req, url, false, null, 0, true);
4571
url = url.url; // Make url a string so we can use it later.
4573
Y.log('URL must be a string or an object with a `url` property.', 'error', 'get');
4577
Y.mix(req, options, false, null, 0, true);
4579
// If we didn't get an explicit type for this URL either in the
4580
// request options or the URL-specific options, try to determine
4581
// one from the file extension.
4583
if (this.REGEX_CSS.test(url)) {
4586
if (!this.REGEX_JS.test(url)) {
4587
Y.log("Can't guess file type from URL. Assuming JS: " + url, 'warn', 'get');
4594
// Mix in type-specific default options, but don't overwrite any
4595
// options that have already been set.
4596
Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions,
4597
false, null, 0, true);
4599
// Give the node an id attribute if it doesn't already have one.
4600
req.attributes.id || (req.attributes.id = Y.guid());
4602
// Backcompat for <3.5.0 behavior.
4604
Y.log('The `win` option is deprecated as of 3.5.0. Use `doc` instead.', 'warn', 'get');
4605
req.doc = req.win.document;
4607
req.win = req.doc.defaultView || req.doc.parentWindow;
4611
Y.log('The `charset` option is deprecated as of 3.5.0. Set `attributes.charset` instead.', 'warn', 'get');
4612
req.attributes.charset = req.charset;
4618
return new Transaction(requests, options);
4621
_load: function (type, urls, options, callback) {
4624
// Allow callback as third param.
4625
if (typeof options === 'function') {
4630
options || (options = {});
4631
options.type = type;
4633
options._onFinish = Get._onTransactionFinish;
4639
transaction = this._getTransaction(urls, options);
4642
callback : callback,
4643
transaction: transaction
4651
_onTransactionFinish : function() {
4652
Get._pending = null;
4656
_next: function () {
4659
if (this._pending) {
4663
item = this._queue.shift();
4666
this._pending = item;
4667
item.transaction.execute(item.callback);
4671
_purge: function (nodes) {
4672
var purgeNodes = this._purgeNodes,
4673
isTransaction = nodes !== purgeNodes,
4676
while (node = nodes.pop()) { // assignment
4677
// Don't purge nodes that haven't finished loading (or errored out),
4678
// since this can hang the transaction.
4679
if (!node._yuiget_finished) {
4683
node.parentNode && node.parentNode.removeChild(node);
4685
// If this is a transaction-level purge and this node also exists in
4686
// the Get-level _purgeNodes array, we need to remove it from
4687
// _purgeNodes to avoid creating a memory leak. The indexOf lookup
4688
// sucks, but until we get WeakMaps, this is the least troublesome
4689
// way to do this (we can't just hold onto node ids because they may
4690
// not be in the same document).
4691
if (isTransaction) {
4692
index = Y.Array.indexOf(purgeNodes, node);
4695
purgeNodes.splice(index, 1);
4708
Get.script = Get.js;
4711
Represents a Get transaction, which may contain requests for one or more JS or
4714
This class should not be instantiated manually. Instances will be created and
4715
returned as needed by Y.Get's `css()`, `js()`, and `load()` methods.
4717
@class Get.Transaction
4721
Get.Transaction = Transaction = function (requests, options) {
4724
self.id = Transaction._lastId += 1;
4725
self.data = options.data;
4728
self.options = options;
4729
self.requests = requests;
4731
self._callbacks = []; // callbacks to call after execution finishes
4733
self._reqsWaiting = 0;
4735
// Deprecated pre-3.5.0 properties.
4736
self.tId = self.id; // Use `id` instead.
4737
self.win = options.win || Y.config.win;
4741
Arbitrary data object associated with this transaction.
4743
This object comes from the options passed to `Get.css()`, `Get.js()`, or
4744
`Get.load()`, and will be `undefined` if no data object was specified.
4746
@property {Object} data
4750
Array of errors that have occurred during this transaction, if any.
4753
@property {Object[]} errors
4754
@property {String} errors.error Error message.
4755
@property {Object} errors.request Request object related to the error.
4759
Numeric id for this transaction, unique among all transactions within the same
4760
YUI sandbox in the current pageview.
4762
@property {Number} id
4767
HTMLElement nodes (native ones, not YUI Node instances) that have been inserted
4768
during the current transaction.
4770
@property {HTMLElement[]} nodes
4774
Options associated with this transaction.
4776
See `Get.options` for the full list of available options.
4778
@property {Object} options
4783
Request objects contained in this transaction. Each request object represents
4784
one CSS or JS URL that will be (or has been) requested and loaded into the page.
4786
@property {Object} requests
4791
Id of the most recent transaction.
4798
Transaction._lastId = 0;
4800
Transaction.prototype = {
4801
// -- Public Properties ----------------------------------------------------
4804
Current state of this transaction. One of "new", "executing", or "done".
4810
_state: 'new', // "new", "executing", or "done"
4812
// -- Public Methods -------------------------------------------------------
4815
Aborts this transaction.
4817
This will cause the transaction's `onFailure` callback to be called and
4818
will prevent any new script and link nodes from being added to the document,
4819
but any resources that have already been requested will continue loading
4820
(there's no safe way to prevent this, unfortunately).
4823
@param {String} [msg="Aborted."] Optional message to use in the `errors`
4824
array describing why the transaction was aborted.
4826
abort: function (msg) {
4827
this._pending = null;
4828
this._pendingCSS = null;
4829
this._pollTimer = clearTimeout(this._pollTimer);
4831
this._reqsWaiting = 0;
4833
this.errors.push({error: msg || 'Aborted'});
4838
Begins execting the transaction.
4840
There's usually no reason to call this manually, since Get will call it
4841
automatically when other pending transactions have finished. If you really
4842
want to execute your transaction before Get does, you can, but be aware that
4843
this transaction's scripts may end up executing before the scripts in other
4844
pending transactions.
4846
If the transaction is already executing, the specified callback (if any)
4847
will be queued and called after execution finishes. If the transaction has
4848
already finished, the callback will be called immediately (the transaction
4849
will not be executed again).
4852
@param {Function} callback Callback function to execute after all requests
4853
in the transaction are complete, or after the transaction is aborted.
4855
execute: function (callback) {
4857
requests = self.requests,
4858
state = self._state,
4861
if (state === 'done') {
4862
callback && callback(self.errors.length ? self.errors : null, self);
4865
callback && self._callbacks.push(callback);
4867
if (state === 'executing') {
4872
self._state = 'executing';
4873
self._queue = queue = [];
4875
if (self.options.timeout) {
4876
self._timeout = setTimeout(function () {
4877
self.abort('Timeout');
4878
}, self.options.timeout);
4881
self._reqsWaiting = requests.length;
4883
for (i = 0, len = requests.length; i < len; ++i) {
4886
if (req.async || req.type === 'css') {
4887
// No need to queue CSS or fully async JS.
4898
Manually purges any `<script>` or `<link>` nodes this transaction has
4901
Be careful when purging a transaction that contains CSS requests, since
4902
removing `<link>` nodes will also remove any styles they applied.
4906
purge: function () {
4907
Get._purge(this.nodes);
4910
// -- Protected Methods ----------------------------------------------------
4911
_createNode: function (name, attrs, doc) {
4912
var node = doc.createElement(name),
4915
if (!CUSTOM_ATTRS) {
4916
// IE6 and IE7 expect property names rather than attribute names for
4917
// certain attributes. Rather than sniffing, we do a quick feature
4918
// test the first time _createNode() runs to determine whether we
4919
// need to provide a workaround.
4920
testEl = doc.createElement('div');
4921
testEl.setAttribute('class', 'a');
4923
CUSTOM_ATTRS = testEl.className === 'a' ? {} : {
4925
'class': 'className'
4929
for (attr in attrs) {
4930
if (attrs.hasOwnProperty(attr)) {
4931
node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]);
4938
_finish: function () {
4939
var errors = this.errors.length ? this.errors : null,
4940
options = this.options,
4941
thisObj = options.context || this,
4944
if (this._state === 'done') {
4948
this._state = 'done';
4950
for (i = 0, len = this._callbacks.length; i < len; ++i) {
4951
this._callbacks[i].call(thisObj, errors, this);
4954
data = this._getEventData();
4957
if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') {
4958
options.onTimeout.call(thisObj, data);
4961
if (options.onFailure) {
4962
options.onFailure.call(thisObj, data);
4964
} else if (options.onSuccess) {
4965
options.onSuccess.call(thisObj, data);
4968
if (options.onEnd) {
4969
options.onEnd.call(thisObj, data);
4972
if (options._onFinish) {
4973
options._onFinish();
4977
_getEventData: function (req) {
4979
// This merge is necessary for backcompat. I hate it.
4980
return Y.merge(this, {
4981
abort : this.abort, // have to copy these because the prototype isn't preserved
4992
_getInsertBefore: function (req) {
4994
el = req.insertBefore,
4998
return typeof el === 'string' ? doc.getElementById(el) : el;
5001
cache = Get._insertCache;
5002
docStamp = Y.stamp(doc);
5004
if ((el = cache[docStamp])) { // assignment
5008
// Inserting before a <base> tag apparently works around an IE bug
5009
// (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what
5010
// bug that is, exactly. Better safe than sorry?
5011
if ((el = doc.getElementsByTagName('base')[0])) { // assignment
5012
return (cache[docStamp] = el);
5015
// Look for a <head> element.
5016
el = doc.head || doc.getElementsByTagName('head')[0];
5019
// Create a marker node at the end of <head> to use as an insertion
5020
// point. Inserting before this node will ensure that all our CSS
5021
// gets inserted in the correct order, to maintain style precedence.
5022
el.appendChild(doc.createTextNode(''));
5023
return (cache[docStamp] = el.lastChild);
5026
// If all else fails, just insert before the first script node on the
5027
// page, which is virtually guaranteed to exist.
5028
return (cache[docStamp] = doc.getElementsByTagName('script')[0]);
5031
_insert: function (req) {
5033
insertBefore = this._getInsertBefore(req),
5034
isScript = req.type === 'js',
5038
cssTimeout, nodeType;
5042
nodeType = 'script';
5043
} else if (!env.cssLoad && ua.gecko) {
5049
node = req.node = this._createNode(nodeType, req.attributes,
5053
function onError() {
5054
self._progress('Failed to load ' + req.url, req);
5059
clearTimeout(cssTimeout);
5062
self._progress(null, req);
5065
// Deal with script asynchronicity.
5067
node.setAttribute('src', req.url);
5070
// Explicitly indicate that we want the browser to execute this
5071
// script asynchronously. This is necessary for older browsers
5076
// This browser treats injected scripts as async by default
5077
// (standard HTML5 behavior) but asynchronous loading isn't
5078
// desired, so tell the browser not to mark this script as
5083
// If this browser doesn't preserve script execution order based
5084
// on insertion order, we'll need to avoid inserting other
5085
// scripts until this one finishes loading.
5086
if (!env.preservesScriptOrder) {
5087
this._pending = req;
5091
if (!env.cssLoad && ua.gecko) {
5092
// In Firefox <9, we can import the requested URL into a <style>
5093
// node and poll for the existence of node.sheet.cssRules. This
5094
// gives us a reliable way to determine CSS load completion that
5095
// also works for cross-domain stylesheets.
5097
// Props to Zach Leatherman for calling my attention to this
5099
node.innerHTML = (req.attributes.charset ?
5100
'@charset "' + req.attributes.charset + '";' : '') +
5101
'@import "' + req.url + '";';
5103
node.setAttribute('href', req.url);
5108
if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) {
5109
// Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode.
5110
node.onreadystatechange = function () {
5111
if (/loaded|complete/.test(node.readyState)) {
5112
node.onreadystatechange = null;
5116
} else if (!isScript && !env.cssLoad) {
5117
// CSS on Firefox <9 or WebKit.
5120
// Script or CSS on everything else. Using DOM 0 events because that
5121
// evens the playing field with older IEs.
5125
// We currently need to introduce a timeout for IE10, since it
5126
// calls onerror/onload synchronously for 304s - messing up existing
5129
// Remove this block if the following bug gets fixed by GA
5130
/*jshint maxlen: 1500 */
5131
// https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload
5132
node.onerror = function() { setTimeout(onError, 0); };
5133
node.onload = function() { setTimeout(onLoad, 0); };
5135
node.onerror = onError;
5136
node.onload = onLoad;
5139
// If this browser doesn't fire an event when CSS fails to load,
5140
// fail after a timeout to avoid blocking the transaction queue.
5141
if (!env.cssFail && !isScript) {
5142
cssTimeout = setTimeout(onError, req.timeout || 3000);
5146
this.nodes.push(node);
5147
insertBefore.parentNode.insertBefore(node, insertBefore);
5150
_next: function () {
5151
if (this._pending) {
5155
// If there are requests in the queue, insert the next queued request.
5156
// Otherwise, if we're waiting on already-inserted requests to finish,
5157
// wait longer. If there are no queued requests and we're not waiting
5158
// for anything to load, then we're done!
5159
if (this._queue.length) {
5160
this._insert(this._queue.shift());
5161
} else if (!this._reqsWaiting) {
5166
_poll: function (newReq) {
5168
pendingCSS = self._pendingCSS,
5169
isWebKit = Y.UA.webkit,
5170
i, hasRules, j, nodeHref, req, sheets;
5173
pendingCSS || (pendingCSS = self._pendingCSS = []);
5174
pendingCSS.push(newReq);
5176
if (self._pollTimer) {
5177
// A poll timeout is already pending, so no need to create a
5183
self._pollTimer = null;
5185
// Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s
5186
// will still be treated as a success. There's no good workaround for
5189
for (i = 0; i < pendingCSS.length; ++i) {
5190
req = pendingCSS[i];
5193
// Look for a stylesheet matching the pending URL.
5194
sheets = req.doc.styleSheets;
5196
nodeHref = req.node.href;
5199
if (sheets[j].href === nodeHref) {
5200
pendingCSS.splice(i, 1);
5202
self._progress(null, req);
5207
// Many thanks to Zach Leatherman for calling my attention to
5208
// the @import-based cross-domain technique used here, and to
5209
// Oleg Slobodskoi for an earlier same-domain implementation.
5211
// See Zach's blog for more details:
5212
// http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
5214
// We don't really need to store this value since we never
5215
// use it again, but if we don't store it, Closure Compiler
5216
// assumes the code is useless and removes it.
5217
hasRules = !!req.node.sheet.cssRules;
5219
// If we get here, the stylesheet has loaded.
5220
pendingCSS.splice(i, 1);
5222
self._progress(null, req);
5224
// An exception means the stylesheet is still loading.
5229
if (pendingCSS.length) {
5230
self._pollTimer = setTimeout(function () {
5231
self._poll.call(self);
5232
}, self.options.pollInterval);
5236
_progress: function (err, req) {
5237
var options = this.options;
5247
Y.log(err, 'error', 'get');
5250
req.node._yuiget_finished = req.finished = true;
5252
if (options.onProgress) {
5253
options.onProgress.call(options.context || this,
5254
this._getEventData(req));
5257
if (req.autopurge) {
5258
// Pre-3.5.0 Get always excludes the most recent node from an
5259
// autopurge. I find this odd, but I'm keeping that behavior for
5260
// the sake of backcompat.
5261
Get._autoPurge(this.options.purgethreshold);
5262
Get._purgeNodes.push(req.node);
5265
if (this._pending === req) {
5266
this._pending = null;
5269
this._reqsWaiting -= 1;
5276
}, '3.9.1', {"requires": ["yui-base"]});
5277
YUI.add('features', function (Y, NAME) {
5279
var feature_tests = {};
5282
Contains the core of YUI's feature test architecture.
5292
Y.mix(Y.namespace('Features'), {
5295
* Object hash of all registered feature tests
5299
tests: feature_tests,
5302
* Add a test to the system
5305
* Y.Features.add("load", "1", {});
5309
* @param {String} cat The category, right now only 'load' is supported
5310
* @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
5311
* @param {Object} o Object containing test properties
5312
* @param {String} o.name The name of the test
5313
* @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
5314
* @param {String} o.trigger The module that triggers this test.
5316
add: function(cat, name, o) {
5317
feature_tests[cat] = feature_tests[cat] || {};
5318
feature_tests[cat][name] = o;
5321
* Execute all tests of a given category and return the serialized results
5327
* @param {String} cat The category to execute
5328
* @param {Array} args The arguments to pass to the test function
5329
* @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
5331
all: function(cat, args) {
5332
var cat_o = feature_tests[cat],
5336
Y.Object.each(cat_o, function(v, k) {
5337
result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
5341
return (result.length) ? result.join(';') : '';
5344
* Run a sepecific test and return a Boolean response.
5347
* Y.Features.test("load", "1");
5351
* @param {String} cat The category of the test to run
5352
* @param {String} name The name of the test to run
5353
* @param {Array} args The arguments to pass to the test function
5354
* @return {Boolean} True or false if the test passed/failed.
5356
test: function(cat, name, args) {
5358
var result, ua, test,
5359
cat_o = feature_tests[cat],
5360
feature = cat_o && cat_o[name];
5363
Y.log('Feature test ' + cat + ', ' + name + ' not found');
5366
result = feature.result;
5368
if (Y.Lang.isUndefined(result)) {
5372
result = (Y.UA[ua]);
5375
test = feature.test;
5376
if (test && ((!ua) || result)) {
5377
result = test.apply(Y, args);
5380
feature.result = result;
5388
// Y.Features.add("load", "1", {});
5389
// Y.Features.test("load", "1");
5390
// caps=1:1;2:0;3:1;
5392
/* This file is auto-generated by (yogi loader --yes --mix --start ../) */
5393
/*jshint maxlen:900, eqeqeq: false */
5394
var add = Y.Features.add;
5395
// app-transitions-native
5397
"name": "app-transitions-native",
5398
"test": function (Y) {
5399
var doc = Y.config.doc,
5400
node = doc ? doc.documentElement : null;
5402
if (node && node.style) {
5403
return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
5408
"trigger": "app-transitions"
5410
// autocomplete-list-keys
5412
"name": "autocomplete-list-keys",
5413
"test": function (Y) {
5414
// Only add keyboard support to autocomplete-list if this doesn't appear to
5415
// be an iOS or Android-based mobile device.
5417
// There's currently no feasible way to actually detect whether a device has
5418
// a hardware keyboard, so this sniff will have to do. It can easily be
5419
// overridden by manually loading the autocomplete-list-keys module.
5421
// Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
5422
// doesn't fire the keyboard events used by AutoCompleteList, so there's
5423
// no point loading the -keys module even when a bluetooth keyboard may be
5425
return !(Y.UA.ios || Y.UA.android);
5427
"trigger": "autocomplete-list"
5431
"name": "dd-gestures",
5432
"trigger": "dd-drag",
5433
"ua": "touchEnabled"
5437
"name": "dom-style-ie",
5438
"test": function (Y) {
5440
var testFeature = Y.Features.test,
5441
addFeature = Y.Features.add,
5442
WINDOW = Y.config.win,
5443
DOCUMENT = Y.config.doc,
5444
DOCUMENT_ELEMENT = 'documentElement',
5447
addFeature('style', 'computedStyle', {
5449
return WINDOW && 'getComputedStyle' in WINDOW;
5453
addFeature('style', 'opacity', {
5455
return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
5459
ret = (!testFeature('style', 'opacity') &&
5460
!testFeature('style', 'computedStyle'));
5464
"trigger": "dom-style"
5468
"name": "editor-para-ie",
5469
"trigger": "editor-para",
5475
"name": "event-base-ie",
5476
"test": function(Y) {
5477
var imp = Y.config.doc && Y.config.doc.implementation;
5478
return (imp && (!imp.hasFeature('Events', '2.0')));
5480
"trigger": "node-base"
5484
"name": "graphics-canvas",
5485
"test": function(Y) {
5486
var DOCUMENT = Y.config.doc,
5487
useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
5488
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5489
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5490
return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
5492
"trigger": "graphics"
5494
// graphics-canvas-default
5496
"name": "graphics-canvas-default",
5497
"test": function(Y) {
5498
var DOCUMENT = Y.config.doc,
5499
useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
5500
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5501
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5502
return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
5504
"trigger": "graphics"
5508
"name": "graphics-svg",
5509
"test": function(Y) {
5510
var DOCUMENT = Y.config.doc,
5511
useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
5512
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5513
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5515
return svg && (useSVG || !canvas);
5517
"trigger": "graphics"
5519
// graphics-svg-default
5521
"name": "graphics-svg-default",
5522
"test": function(Y) {
5523
var DOCUMENT = Y.config.doc,
5524
useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
5525
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
5526
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5528
return svg && (useSVG || !canvas);
5530
"trigger": "graphics"
5534
"name": "graphics-vml",
5535
"test": function(Y) {
5536
var DOCUMENT = Y.config.doc,
5537
canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5538
return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
5540
"trigger": "graphics"
5542
// graphics-vml-default
5544
"name": "graphics-vml-default",
5545
"test": function(Y) {
5546
var DOCUMENT = Y.config.doc,
5547
canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5548
return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
5550
"trigger": "graphics"
5554
"name": "history-hash-ie",
5555
"test": function (Y) {
5556
var docMode = Y.config.doc && Y.config.doc.documentMode;
5558
return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
5559
!docMode || docMode < 8);
5561
"trigger": "history-hash"
5565
"name": "io-nodejs",
5566
"trigger": "io-base",
5571
"name": "json-parse-shim",
5572
"test": function (Y) {
5573
var _JSON = Y.config.global.JSON,
5574
Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
5575
nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
5577
function workingNative( k, v ) {
5578
return k === "ok" ? true : v;
5581
// Double check basic functionality. This is mainly to catch early broken
5582
// implementations of the JSON API in Firefox 3.1 beta1 and beta2
5583
if ( nativeSupport ) {
5585
nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
5588
nativeSupport = false;
5592
return !nativeSupport;
5594
"trigger": "json-parse"
5596
// json-stringify-shim
5598
"name": "json-stringify-shim",
5599
"test": function (Y) {
5600
var _JSON = Y.config.global.JSON,
5601
Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
5602
nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
5604
// Double check basic native functionality. This is primarily to catch broken
5605
// early JSON API implementations in Firefox 3.1 beta1 and beta2.
5606
if ( nativeSupport ) {
5608
nativeSupport = ( '0' === Native.stringify(0) );
5610
nativeSupport = false;
5615
return !nativeSupport;
5617
"trigger": "json-stringify"
5619
// scrollview-base-ie
5621
"name": "scrollview-base-ie",
5622
"trigger": "scrollview-base",
5627
"name": "selector-css2",
5628
"test": function (Y) {
5629
var DOCUMENT = Y.config.doc,
5630
ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
5634
"trigger": "selector"
5638
"name": "transition-timer",
5639
"test": function (Y) {
5640
var DOCUMENT = Y.config.doc,
5641
node = (DOCUMENT) ? DOCUMENT.documentElement: null,
5644
if (node && node.style) {
5645
ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
5650
"trigger": "transition"
5654
"name": "widget-base-ie",
5655
"trigger": "widget-base",
5660
"name": "yql-jsonp",
5661
"test": function (Y) {
5662
/* Only load the JSONP module when not in nodejs or winjs
5663
TODO Make the winjs module a CORS module
5665
return (!Y.UA.nodejs && !Y.UA.winjs);
5672
"name": "yql-nodejs",
5679
"name": "yql-winjs",
5685
}, '3.9.1', {"requires": ["yui-base"]});
5686
YUI.add('intl-base', function (Y, NAME) {
5689
* The Intl utility provides a central location for managing sets of
5690
* localized resources (strings and formatting patterns).
5697
var SPLIT_REGEX = /[, ]/;
5699
Y.mix(Y.namespace('Intl'), {
5702
* Returns the language among those available that
5703
* best matches the preferred language list, using the Lookup
5704
* algorithm of BCP 47.
5705
* If none of the available languages meets the user's preferences,
5706
* then "" is returned.
5707
* Extended language ranges are not supported.
5709
* @method lookupBestLang
5710
* @param {String[] | String} preferredLanguages The list of preferred
5711
* languages in descending preference order, represented as BCP 47
5712
* language tags. A string array or a comma-separated list.
5713
* @param {String[]} availableLanguages The list of languages
5714
* that the application supports, represented as BCP 47 language
5717
* @return {String} The available language that best matches the
5718
* preferred language list, or "".
5721
lookupBestLang: function(preferredLanguages, availableLanguages) {
5723
var i, language, result, index;
5725
// check whether the list of available languages contains language;
5727
function scan(language) {
5729
for (i = 0; i < availableLanguages.length; i += 1) {
5730
if (language.toLowerCase() ===
5731
availableLanguages[i].toLowerCase()) {
5732
return availableLanguages[i];
5737
if (Y.Lang.isString(preferredLanguages)) {
5738
preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
5741
for (i = 0; i < preferredLanguages.length; i += 1) {
5742
language = preferredLanguages[i];
5743
if (!language || language === '*') {
5746
// check the fallback sequence for one language
5747
while (language.length > 0) {
5748
result = scan(language);
5752
index = language.lastIndexOf('-');
5754
language = language.substring(0, index);
5755
// one-character subtags get cut along with the
5757
if (index >= 2 && language.charAt(index - 2) === '-') {
5758
language = language.substring(0, index - 2);
5761
// nothing available for this language
5773
}, '3.9.1', {"requires": ["yui-base"]});
5774
YUI.add('yui-log', function (Y, NAME) {
5777
* Provides console log capability and exposes a custom event for
5778
* console implementations. This module is a `core` YUI module,
5779
* <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
5782
* @submodule yui-log
5786
LOGEVENT = 'yui:log',
5787
UNDEFINED = 'undefined',
5788
LEVELS = { debug: 1,
5794
* If the 'debug' config is true, a 'yui:log' event will be
5795
* dispatched, which the Console widget and anything else
5796
* can consume. If the 'useBrowserConsole' config is true, it will
5797
* write to the browser console if available. YUI-specific log
5798
* messages will only be present in the -debug versions of the
5799
* JS files. The build system is supposed to remove log statements
5800
* from the raw and minified versions of the files.
5804
* @param {String} msg The message to log.
5805
* @param {String} cat The log category for the message. Default
5806
* categories are "info", "warn", "error", time".
5807
* Custom categories can be used as well. (opt).
5808
* @param {String} src The source of the the message (opt).
5809
* @param {boolean} silent If true, the log event won't fire.
5810
* @return {YUI} YUI instance.
5812
INSTANCE.log = function(msg, cat, src, silent) {
5813
var bail, excl, incl, m, f,
5816
publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
5817
// suppress log message if the config is off or the event stack
5818
// or the event call stack contains a consumer of the yui:log event
5820
// apply source filters
5822
if (typeof src !== "undefined") {
5823
excl = c.logExclude;
5824
incl = c.logInclude;
5825
if (incl && !(src in incl)) {
5827
} else if (incl && (src in incl)) {
5829
} else if (excl && (src in excl)) {
5834
if (c.useBrowserConsole) {
5835
m = (src) ? src + ': ' + msg : msg;
5836
if (Y.Lang.isFunction(c.logFn)) {
5837
c.logFn.call(Y, msg, cat, src);
5838
} else if (typeof console !== UNDEFINED && console.log) {
5839
f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
5841
} else if (typeof opera !== UNDEFINED) {
5846
if (publisher && !silent) {
5848
if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
5849
publisher.publish(LOGEVENT, {
5854
publisher.fire(LOGEVENT, {
5867
* Write a system message. This message will be preserved in the
5868
* minified and raw versions of the YUI files, unlike log statements.
5871
* @param {String} msg The message to log.
5872
* @param {String} cat The log category for the message. Default
5873
* categories are "info", "warn", "error", time".
5874
* Custom categories can be used as well. (opt).
5875
* @param {String} src The source of the the message (opt).
5876
* @param {boolean} silent If true, the log event won't fire.
5877
* @return {YUI} YUI instance.
5879
INSTANCE.message = function() {
5880
return INSTANCE.log.apply(INSTANCE, arguments);
5884
}, '3.9.1', {"requires": ["yui-base"]});
5885
YUI.add('yui-later', function (Y, NAME) {
5888
* Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module,
5889
* <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
5892
* @submodule yui-later
5898
* Executes the supplied function in the context of the supplied
5899
* object 'when' milliseconds later. Executes the function a
5900
* single time unless periodic is set to true.
5903
* @param when {int} the number of milliseconds to wait until the fn
5905
* @param o the context object.
5906
* @param fn {Function|String} the function to execute or the name of
5907
* the method in the 'o' object to execute.
5908
* @param data [Array] data that is provided to the function. This
5909
* accepts either a single item or an array. If an array is provided,
5910
* the function is executed with one parameter for each array item.
5911
* If you need to pass a single array parameter, it needs to be wrapped
5912
* in an array [myarray].
5914
* Note: native methods in IE may not have the call and apply methods.
5915
* In this case, it will work, but you are limited to four arguments.
5917
* @param periodic {boolean} if true, executes continuously at supplied
5918
* interval until canceled.
5919
* @return {object} a timer object. Call the cancel() method on this
5920
* object to stop the timer.
5922
Y.later = function(when, o, fn, data, periodic) {
5924
data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS;
5925
o = o || Y.config.win || Y;
5927
var cancelled = false,
5928
method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
5929
wrapper = function() {
5930
// IE 8- may execute a setInterval callback one last time
5931
// after clearInterval was called, so in order to preserve
5932
// the cancel() === no more runny-run, we have to jump through
5935
if (!method.apply) {
5936
method(data[0], data[1], data[2], data[3]);
5938
method.apply(o, data || NO_ARGS);
5942
id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
5947
cancel: function() {
5949
if (this.interval) {
5958
Y.Lang.later = Y.later;
5962
}, '3.9.1', {"requires": ["yui-base"]});
5963
YUI.add('yui', function (Y, NAME) {}, '3.9.1', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});