3
Copyright 2012 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
8
* The YUI module contains the components required for building the YUI seed
9
* file. This includes the script loading mechanism, a simple queue, and
10
* the core utilities for the library.
15
if (typeof YUI != 'undefined') {
20
The YUI global namespace object. If YUI is already defined, the
21
existing YUI object will not be overwritten so that defined
22
namespaces are preserved. It is the constructor for the object
23
the end user interacts with. As indicated below, each instance
24
has full custom event support, but only if the event system
25
is available. This is a self-instantiable factory function. You
26
can invoke it directly like this:
28
YUI().use('*', function(Y) {
32
But it also works like this:
36
Configuring the YUI object:
41
}).use('node', function(Y) {
42
//Node is ready to use
45
See the API docs for the <a href="config.html">Config</a> class
46
for the complete list of supported configuration properties accepted
47
by the YUI constuctor.
53
@param [o]* {Object} 0..n optional configuration objects. these values
54
are store in Y.config. See <a href="config.html">Config</a> for the list of supported
59
var YUI = function() {
64
instanceOf = function(o, type) {
65
return (o && o.hasOwnProperty && (o instanceof type));
67
gconf = (typeof YUI_config !== 'undefined') && YUI_config;
69
if (!(instanceOf(Y, YUI))) {
72
// set up the core environment
76
YUI.GlobalConfig is a master configuration that might span
77
multiple contexts in a non-browser environment. It is applied
78
first to all instances in all contexts.
79
@property GlobalConfig
90
YUI().use('node', function(Y) {
91
//debug files used here
96
}).use('node', function(Y) {
101
if (YUI.GlobalConfig) {
102
Y.applyConfig(YUI.GlobalConfig);
106
YUI_config is a page-level config. It is applied to all
107
instances created on the page. This is applied after
108
YUI.GlobalConfig, and before the instance level configuration
116
//Single global var to include before YUI seed file
121
YUI().use('node', function(Y) {
122
//debug files used here
127
}).use('node', function(Y) {
128
//min files used here
132
Y.applyConfig(gconf);
135
// bind the specified additional modules for this instance
142
// Each instance can accept one or more configuration objects.
143
// These are applied after YUI.GlobalConfig and YUI_Config,
144
// overriding values set in those config files if there is a '
145
// matching property.
147
Y.applyConfig(args[i]);
153
Y.instanceOf = instanceOf;
163
BASE = 'http://yui.yahooapis.com/',
164
DOC_LABEL = 'yui3-js-enabled',
165
CSS_STAMP_EL = 'yui3-css-stamp',
166
NOOP = function() {},
167
SLICE = Array.prototype.slice,
168
APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo
169
'io.xdrResponse': 1, // can call. this should
170
'SWF.eventHandler': 1 }, // be done at build time
171
hasWin = (typeof window != 'undefined'),
172
win = (hasWin) ? window : null,
173
doc = (hasWin) ? win.document : null,
174
docEl = doc && doc.documentElement,
175
docClass = docEl && docEl.className,
177
time = new Date().getTime(),
178
add = function(el, type, fn, capture) {
179
if (el && el.addEventListener) {
180
el.addEventListener(type, fn, capture);
181
} else if (el && el.attachEvent) {
182
el.attachEvent('on' + type, fn);
185
remove = function(el, type, fn, capture) {
186
if (el && el.removeEventListener) {
187
// this can throw an uncaught exception in FF
189
el.removeEventListener(type, fn, capture);
191
} else if (el && el.detachEvent) {
192
el.detachEvent('on' + type, fn);
195
handleLoad = function() {
196
YUI.Env.windowLoaded = true;
197
YUI.Env.DOMReady = true;
199
remove(window, 'load', handleLoad);
202
getLoader = function(Y, o) {
203
var loader = Y.Env._loader;
205
//loader._config(Y.config);
206
loader.ignoreRegistered = false;
209
loader.required = [];
210
loader.loadType = null;
212
loader = new Y.Loader(Y.config);
213
Y.Env._loader = loader;
215
YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, [ 'loader-base', 'loader-rollup', 'loader-yui3' ]));
220
clobber = function(r, s) {
222
if (s.hasOwnProperty(i)) {
228
ALREADY_DONE = { success: true };
230
// Stamp the documentElement (HTML) with a class of "yui-loaded" to
231
// enable styles that need to key off of JS being enabled.
232
if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
236
docClass += DOC_LABEL;
237
docEl.className = docClass;
240
if (VERSION.indexOf('@') > -1) {
241
VERSION = '3.3.0'; // dev time hack for cdn test
246
* Applies a new configuration object to the YUI instance config.
247
* This will merge new group/module definitions, and will also
248
* update the loader cache if necessary. Updating Y.config directly
249
* will not update the cache.
250
* @method applyConfig
251
* @param {Object} o the configuration object.
254
applyConfig: function(o) {
261
config = this.config,
262
mods = config.modules,
263
groups = config.groups,
264
aliases = config.aliases,
265
loader = this.Env._loader;
268
if (o.hasOwnProperty(name)) {
270
if (mods && name == 'modules') {
272
} else if (aliases && name == 'aliases') {
273
clobber(aliases, attr);
274
} else if (groups && name == 'groups') {
275
clobber(groups, attr);
276
} else if (name == 'win') {
277
config[name] = (attr && attr.contentWindow) || attr;
278
config.doc = config[name] ? config[name].document : null;
279
} else if (name == '_yuid') {
293
* Old way to apply a config to the instance (calls `applyConfig` under the hood)
296
* @param {Object} o The config to apply
298
_config: function(o) {
303
* Initialize this YUI instance
315
* The version number of the YUI instance.
323
core: ['get','intl-base'],
324
mods: {}, // flat module map
325
versions: {}, // version module map
327
cdn: BASE + VERSION + '/build/',
328
// bootstrapped: false,
339
// I'll start at the \b(simpleyui).
340
// 1. Look in the test string for "simpleyui" or "yui" or
341
// "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it
342
// can't match "foyui" or "i_heart_simpleyui". This can be anywhere in the string.
343
// 2. After #1 must come a forward slash followed by the string matched in #1, so
344
// "yui-base/yui-base" or "simpleyui/simpleyui" or "yui-pants/yui-pants".
345
// 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
346
// so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
347
// 4. This is followed by ".js", so "yui/yui.js", "simpleyui/simpleyui-min.js"
348
// 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
349
// then capture the junk between the LAST "&" and the string in 1-4. So
350
// "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
351
// will capture "3.3.0/build/"
355
// (?:[^&]*&) followed by 0..n characters followed by an &
356
// * in fact, find as many sets of characters followed by a & as you can
357
// ([^&]*) capture the stuff after the last & in \1
358
// )? but it's ok if all this ?junk&more_junk stuff isn't even there
359
// \b(simpleyui| after a word break find either the string "simpleyui" or
360
// yui(?:-\w+)? the string "yui" optionally followed by a -, then more characters
361
// ) and store the simpleyui or yui-* string in \2
362
// \/\2 then comes a / followed by the simpleyui or yui-* string in \2
363
// (?:-(min|debug))? optionally followed by "-min" or "-debug"
364
// .js and ending in ".js"
365
_BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
366
parseBasePath: function(src, pattern) {
367
var match = src.match(pattern),
371
path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
373
// this is to set up the path to the loader. The file
374
// filter for loader should match the yui include.
377
// extract correct path for mixed combo urls
378
// http://yuilibrary.com/projects/yui3/ticket/2528423
380
path += '?' + match[1];
389
getBase: G_ENV && G_ENV.getBase ||
391
var nodes = (doc && doc.getElementsByTagName('script')) || [],
392
path = Env.cdn, parsed,
395
for (i = 0, len = nodes.length; i < len; ++i) {
398
parsed = Y.Env.parseBasePath(src, pattern);
400
filter = parsed.filter;
415
Env._loaded[VERSION] = {};
417
if (G_ENV && Y !== YUI) {
418
Env._yidx = ++G_ENV._yidx;
419
Env._guidp = ('yui_' + VERSION + '_' +
420
Env._yidx + '_' + time).replace(/\./g, '_');
421
} else if (YUI._YUI) {
423
G_ENV = YUI._YUI.Env;
424
Env._yidx += G_ENV._yidx;
425
Env._uidx += G_ENV._uidx;
427
for (prop in G_ENV) {
428
if (!(prop in Env)) {
429
Env[prop] = G_ENV[prop];
443
// configuration defaults
444
Y.config = Y.config || {
451
useBrowserConsole: true,
456
//Register the CSS stamp element
457
if (doc && !doc.getElementById(CSS_STAMP_EL)) {
458
el = doc.createElement('div');
459
el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
460
YUI.Env.cssStampEl = el.firstChild;
461
docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
464
Y.config.lang = Y.config.lang || 'en-US';
466
Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
468
if (!filter || (!('mindebug').indexOf(filter))) {
471
filter = (filter) ? '-' + filter : filter;
472
Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
477
* Finishes the instance setup. Attaches whatever modules were defined
478
* when the yui modules was registered.
482
_setup: function(o) {
486
//extras = Y.config.core || ['get','intl-base'];
487
extras = Y.config.core || [].concat(YUI.Env.core); //Clone it..
489
for (i = 0; i < extras.length; i++) {
490
if (mods[extras[i]]) {
491
core.push(extras[i]);
495
Y._attach(['yui-base']);
505
* Executes a method on a YUI instance with
506
* the specified id if the specified method is whitelisted.
508
* @param id {String} the YUI instance id.
509
* @param method {String} the name of the method to exectute.
511
* @param args {Array} the arguments to apply to the method.
512
* @return {Object} the return value from the applied method or null.
514
applyTo: function(id, method, args) {
515
if (!(method in APPLY_TO_AUTH)) {
516
this.log(method + ': applyTo not allowed', 'warn', 'yui');
520
var instance = instances[id], nest, m, i;
522
nest = method.split('.');
524
for (i = 0; i < nest.length; i = i + 1) {
527
this.log('applyTo not found: ' + method, 'warn', 'yui');
530
return m && m.apply(instance, args);
537
Registers a module with the YUI global. The easiest way to create a
538
first-class YUI module is to use the YUI component build tool.
540
http://yuilibrary.com/projects/builder
542
The build system will produce the `YUI.add` wrapper for you module, along
543
with any configuration info required for the module.
545
@param name {String} module name.
546
@param fn {Function} entry point into the module that is used to bind module to the YUI instance.
547
@param {YUI} fn.Y The YUI instance this module is executed in.
548
@param {String} fn.name The name of the module
549
@param version {String} version string.
550
@param details {Object} optional config data:
551
@param details.requires {Array} features that must be present before this module can be attached.
552
@param details.optional {Array} optional features that should be present if loadOptional
553
is defined. Note: modules are not often loaded this way in YUI 3,
554
but this field is still useful to inform the user that certain
555
features in the component will require additional dependencies.
556
@param details.use {Array} features that are included within this module which need to
557
be attached automatically when this module is attached. This
558
supports the YUI 3 rollup system -- a module with submodules
559
defined will need to have the submodules listed in the 'use'
560
config. The YUI component build tool does this for you.
561
@return {YUI} the YUI instance.
564
YUI.add('davglass', function(Y, name) {
565
Y.davglass = function() {
566
alert('Dav was here!');
568
}, '3.4.0', { requires: ['yui-base', 'harley-davidson', 'mt-dew'] });
571
add: function(name, fn, version, details) {
572
details = details || {};
581
i, versions = env.versions;
583
env.mods[name] = mod;
584
versions[version] = versions[version] || {};
585
versions[version][name] = mod;
587
for (i in instances) {
588
if (instances.hasOwnProperty(i)) {
589
loader = instances[i].Env._loader;
591
if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
592
loader.addModule(details, name);
602
* Executes the function associated with each required
603
* module, binding the module to the YUI instance.
604
* @param {Array} r The array of modules to attach
605
* @param {Boolean} [moot=false] Don't throw a warning if the module is not attached
609
_attach: function(r, moot) {
610
var i, name, mod, details, req, use, after,
612
aliases = YUI.Env.aliases,
614
loader = Y.Env._loader,
615
done = Y.Env._attached,
616
len = r.length, loader,
619
//Check for conditional modules (in a second+ instance) and add their requirements
620
//TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
621
for (i = 0; i < len; i++) {
625
if (loader && loader.conditions[name]) {
626
Y.Object.each(loader.conditions[name], function(def) {
627
var go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
637
for (i = 0; i < len; i++) {
642
if (aliases && aliases[name]) {
643
Y._attach(aliases[name]);
647
if (loader && loader.moduleInfo[name]) {
648
mod = loader.moduleInfo[name];
653
//if (!loader || !loader.moduleInfo[name]) {
654
//if ((!loader || !loader.moduleInfo[name]) && !moot) {
656
if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
657
Y.Env._missed.push(name);
658
Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
659
Y.message('NOT loaded: ' + name, 'warn', 'yui');
664
//Don't like this, but in case a mod was asked for once, then we fetch it
665
//We need to remove it from the missed list ^davglass
666
for (j = 0; j < Y.Env._missed.length; j++) {
667
if (Y.Env._missed[j] === name) {
668
Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
669
Y.Env._missed.splice(j, 1);
672
details = mod.details;
673
req = details.requires;
675
after = details.after;
678
for (j = 0; j < req.length; j++) {
680
if (!Y._attach(req)) {
689
for (j = 0; j < after.length; j++) {
690
if (!done[after[j]]) {
691
if (!Y._attach(after, true)) {
703
Y.error('Attach error: ' + name, e, name);
709
for (j = 0; j < use.length; j++) {
711
if (!Y._attach(use)) {
729
* Attaches one or more modules to the YUI instance. When this
730
* is executed, the requirements are analyzed, and one of
731
* several things can happen:
733
* * All requirements are available on the page -- The modules
734
* are attached to the instance. If supplied, the use callback
735
* is executed synchronously.
737
* * Modules are missing, the Get utility is not available OR
738
* the 'bootstrap' config is false -- A warning is issued about
739
* the missing modules and all available modules are attached.
741
* * Modules are missing, the Loader is not available but the Get
742
* utility is and boostrap is not false -- The loader is bootstrapped
743
* before doing the following....
745
* * Modules are missing and the Loader is available -- The loader
746
* expands the dependency tree and fetches missing modules. When
747
* the loader is finshed the callback supplied to use is executed
751
* @param modules* {String|Array} 1-n modules to bind (uses arguments array).
752
* @param [callback] {Function} callback function executed when
753
* the instance has the required functionality. If included, it
754
* must be the last parameter.
755
* @param callback.Y {YUI} The `YUI` instance created for this sandbox
756
* @param callback.data {Object} Object data returned from `Loader`.
759
* // loads and attaches dd and its dependencies
760
* YUI().use('dd', function(Y) {});
762
* // loads and attaches dd and node as well as all of their dependencies (since 3.4.0)
763
* YUI().use(['dd', 'node'], function(Y) {});
765
* // attaches all modules that are available on the page
766
* YUI().use('*', function(Y) {});
768
* // intrinsic YUI gallery support (since 3.1.0)
769
* YUI().use('gallery-yql', function(Y) {});
771
* // intrinsic YUI 2in3 support (since 3.1.0)
772
* YUI().use('yui2-datatable', function(Y) {});
774
* @return {YUI} the YUI instance.
777
var args = SLICE.call(arguments, 0),
778
callback = args[args.length - 1],
786
// The last argument supplied to use can be a load complete callback
787
if (Y.Lang.isFunction(callback)) {
792
if (Y.Lang.isArray(args[0])) {
796
if (Y.config.cacheUse) {
797
while ((name = args[i++])) {
798
if (!Env._attached[name]) {
807
Y._notify(callback, ALREADY_DONE, args);
813
Y._useQueue = Y._useQueue || new Y.Queue();
814
Y._useQueue.add([args, callback]);
816
Y._use(args, function(Y, response) {
817
Y._notify(callback, response, args);
824
* Notify handler from Loader for attachment/load errors
826
* @param callback {Function} The callback to pass to the `Y.config.loadErrorFn`
827
* @param response {Object} The response returned from Loader
828
* @param args {Array} The aruments passed from Loader
831
_notify: function(callback, response, args) {
832
if (!response.success && this.config.loadErrorFn) {
833
this.config.loadErrorFn.call(this, this, callback, response, args);
834
} else if (callback) {
836
callback(this, response);
838
this.error('use callback error', e, args);
844
* This private method is called from the `use` method queue. To ensure that only one set of loading
845
* logic is performed at a time.
848
* @param args* {String} 1-n modules to bind (uses arguments array).
849
* @param *callback {Function} callback function executed when
850
* the instance has the required functionality. If included, it
851
* must be the last parameter.
853
_use: function(args, callback) {
856
this._attach(['yui-base']);
859
var len, loader, handleBoot, handleRLS,
865
aliases = G_ENV.aliases,
866
queue = G_ENV._loaderQueue,
870
boot = config.bootstrap,
874
fetchCSS = config.fetchCSS,
875
process = function(names, skip) {
884
for (i = 0; i < names.length; i++) {
885
if (aliases[names[i]]) {
886
a = [].concat(a, aliases[names[i]]);
894
YArray.each(names, function(name) {
896
// add this module to full list of things to attach
901
// only attach a module once
906
var m = mods[name], req, use;
910
req = m.details.requires;
913
// CSS files don't register themselves, see if it has
915
if (!G_ENV._loaded[VERSION][name]) {
918
used[name] = true; // probably css
922
// make sure requirements are attached
923
if (req && req.length) {
927
// make sure we grab the submodule dependencies too
928
if (use && use.length) {
934
handleLoader = function(fromLoader) {
935
var response = fromLoader || {
941
data = response.data;
946
origMissing = missing;
950
redo = missing.length;
952
if (missing.sort().join() ==
953
origMissing.sort().join()) {
961
Y._use(missing, function() {
962
if (Y._attach(data)) {
963
Y._notify(callback, response, data);
968
ret = Y._attach(data);
971
Y._notify(callback, response, args);
975
if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
976
Y._use.apply(Y, Y._useQueue.next());
982
// YUI().use('*'); // bind everything available
983
if (firstArg === '*') {
984
ret = Y._attach(Y.Object.keys(mods));
991
if (mods['loader'] && !Y.Loader) {
992
Y._attach(['loader']);
996
// use loader to expand dependencies and sort the
997
// requirements if it is available.
998
if (boot && Y.Loader && args.length) {
999
loader = getLoader(Y);
1000
loader.require(args);
1001
loader.ignoreRegistered = true;
1002
loader._boot = true;
1003
loader.calculate(null, (fetchCSS) ? null : 'js');
1004
args = loader.sorted;
1005
loader._boot = false;
1008
// process each requirement and any additional requirements
1009
// the module metadata specifies
1012
len = missing.length;
1015
missing = Y.Object.keys(YArray.hash(missing));
1016
len = missing.length;
1021
if (boot && len && Y.Loader) {
1023
loader = getLoader(Y);
1024
loader.onEnd = handleLoader;
1027
loader.ignoreRegistered = false;
1028
loader.require(args);
1029
loader.insert(null, (fetchCSS) ? null : 'js');
1031
} else if (boot && len && Y.Get && !Env.bootstrapped) {
1035
handleBoot = function() {
1037
queue.running = false;
1038
Env.bootstrapped = true;
1039
G_ENV._bootstrapping = false;
1040
if (Y._attach(['loader'])) {
1041
Y._use(args, callback);
1045
if (G_ENV._bootstrapping) {
1046
queue.add(handleBoot);
1048
G_ENV._bootstrapping = true;
1049
Y.Get.script(config.base + config.loaderPath, {
1055
ret = Y._attach(args);
1066
Adds a namespace object onto the YUI global if called statically.
1068
// creates YUI.your.namespace.here as nested objects
1069
YUI.namespace("your.namespace.here");
1071
If called as a method on a YUI <em>instance</em>, it creates the
1072
namespace on the instance.
1074
// creates Y.property.package
1075
Y.namespace("property.package");
1077
Dots in the input string cause `namespace` to create nested objects for
1078
each token. If any part of the requested namespace already exists, the
1079
current object will be left in place. This allows multiple calls to
1080
`namespace` to preserve existing namespaced properties.
1082
If the first token in the namespace string is "YAHOO", the token is
1085
Be careful with namespace tokens. Reserved words may work in some browsers
1086
and not others. For instance, the following will fail in some browsers
1087
because the supported version of JavaScript reserves the word "long":
1089
Y.namespace("really.long.nested.namespace");
1091
<em>Note: If you pass multiple arguments to create multiple namespaces, only
1092
the last one created is returned from this function.</em>
1095
@param {String} namespace* namespaces to create.
1096
@return {Object} A reference to the last namespace object created.
1098
namespace: function() {
1099
var a = arguments, o, i = 0, j, d, arg;
1101
for (; i < a.length; i++) {
1102
o = this; //Reset base object per argument or it will get reused from the last
1104
if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1105
d = arg.split(PERIOD);
1106
for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1107
o[d[j]] = o[d[j]] || {};
1111
o[arg] = o[arg] || {};
1112
o = o[arg]; //Reset base object to the new object so it's returned
1118
// this is replaced if the log module is included
1121
// this is replaced if the dump module is included
1122
dump: function (o) { return ''+o; },
1125
* Report an error. The reporting mechanism is controlled by
1126
* the `throwFail` configuration attribute. If throwFail is
1127
* not specified, the message is written to the Logger, otherwise
1128
* a JS error is thrown. If an `errorFn` is specified in the config
1129
* it must return `true` to keep the error from being thrown.
1131
* @param msg {String} the error message.
1132
* @param e {Error|String} Optional JS error that was caught, or an error string.
1133
* @param src Optional additional info (passed to `Y.config.errorFn` and `Y.message`)
1134
* and `throwFail` is specified, this error will be re-thrown.
1135
* @return {YUI} this YUI instance.
1137
error: function(msg, e, src) {
1138
//TODO Add check for window.onerror here
1142
if (Y.config.errorFn) {
1143
ret = Y.config.errorFn.apply(Y, arguments);
1146
if (Y.config.throwFail && !ret) {
1147
throw (e || new Error(msg));
1149
Y.message(msg, 'error', ''+src); // don't scrub this one
1156
* Generate an id that is unique among all YUI instances
1158
* @param pre {String} optional guid prefix.
1159
* @return {String} the guid.
1161
guid: function(pre) {
1162
var id = this.Env._guidp + '_' + (++this.Env._uidx);
1163
return (pre) ? (pre + id) : id;
1167
* Returns a `guid` associated with an object. If the object
1168
* does not have one, a new one is created unless `readOnly`
1171
* @param o {Object} The object to stamp.
1172
* @param readOnly {Boolean} if `true`, a valid guid will only
1173
* be returned if the object has one assigned to it.
1174
* @return {String} The object's guid or null.
1176
stamp: function(o, readOnly) {
1182
// IE generates its own unique ID for dom nodes
1183
// The uniqueID property of a document node returns a new ID
1184
if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1187
uid = (typeof o === 'string') ? o : o._yuid;
1204
* Destroys the YUI instance
1208
destroy: function() {
1213
delete instances[Y.id];
1219
* instanceof check for objects that works around
1220
* memory leak in IE when the item tested is
1222
* @method instanceOf
1223
* @param o {Object} The object to check.
1224
* @param type {Object} The class to check against.
1229
YUI.prototype = proto;
1231
// inheritance utilities are not available yet
1232
for (prop in proto) {
1233
if (proto.hasOwnProperty(prop)) {
1234
YUI[prop] = proto[prop];
1239
Static method on the Global YUI object to apply a config to all YUI instances.
1240
It's main use case is "mashups" where several third party scripts are trying to write to
1241
a global YUI config at the same time. This way they can all call `YUI.applyConfig({})` instead of
1242
overwriting other scripts configs.
1246
@param {Object} o the configuration object.
1252
fullpath: './davglass.js'
1260
fullpath: './foo.js'
1265
YUI().use('davglass', function(Y) {
1266
//Module davglass will be available here..
1270
YUI.applyConfig = function(o) {
1274
//If there is a GlobalConfig, apply it first to set the defaults
1275
if (YUI.GlobalConfig) {
1276
this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1278
//Apply this config to it
1279
this.prototype.applyConfig.call(this, o);
1280
//Reset GlobalConfig to the combined config
1281
YUI.GlobalConfig = this.config;
1284
// set up the environment
1288
// add a window load event at load time so we can capture
1289
// the case where it fires before dynamic loading is
1291
add(window, 'load', handleLoad);
1297
YUI.Env.remove = remove;
1300
// Support the CommonJS method for exporting our single global
1301
if (typeof exports == 'object') {
1309
* The config object contains all of the configuration options for
1310
* the `YUI` instance. This object is supplied by the implementer
1311
* when instantiating a `YUI` instance. Some properties have default
1312
* values if they are not supplied by the implementer. This should
1313
* not be updated directly because some values are cached. Use
1314
* `applyConfig()` to update the config object on a YUI instance that
1315
* has already been configured.
1322
* Allows the YUI seed file to fetch the loader component and library
1323
* metadata to dynamically load additional dependencies.
1325
* @property bootstrap
1331
* Turns on writing Ylog messages to the browser console.
1339
* Log to the browser console if debug is on and the browser has a
1340
* supported console.
1342
* @property useBrowserConsole
1348
* A hash of log sources that should be logged. If specified, only
1349
* log messages from these sources will be logged.
1351
* @property logInclude
1356
* A hash of log sources that should be not be logged. If specified,
1357
* all sources are logged if not on this list.
1359
* @property logExclude
1364
* Set to true if the yui seed file was dynamically loaded in
1365
* order to bootstrap components relying on the window load event
1366
* and the `domready` custom event.
1368
* @property injected
1374
* If `throwFail` is set, `Y.error` will generate or re-throw a JS Error.
1375
* Otherwise the failure is logged.
1377
* @property throwFail
1383
* The window/frame that this instance should operate in.
1387
* @default the window hosting YUI
1391
* The document associated with the 'win' configuration.
1395
* @default the document hosting YUI
1399
* A list of modules that defines the YUI core (overrides the default list).
1403
* @default [ get,features,intl-base,yui-log,yui-later,loader-base, loader-rollup, loader-yui3 ]
1407
* A list of languages in order of preference. This list is matched against
1408
* the list of available languages in modules that the YUI instance uses to
1409
* determine the best possible localization of language sensitive modules.
1410
* Languages are represented using BCP 47 language tags, such as "en-GB" for
1411
* English as used in the United Kingdom, or "zh-Hans-CN" for simplified
1412
* Chinese as used in China. The list can be provided as a comma-separated
1413
* list or as an array.
1416
* @type string|string[]
1420
* The default date format
1421
* @property dateFormat
1423
* @deprecated use configuration in `DataType.Date.format()` instead.
1427
* The default locale
1430
* @deprecated use `config.lang` instead.
1434
* The default interval when polling in milliseconds.
1435
* @property pollInterval
1441
* The number of dynamic nodes to insert by default before
1442
* automatically removing them. This applies to script nodes
1443
* because removing the node will not make the evaluated script
1444
* unavailable. Dynamic CSS is not auto purged, because removing
1445
* a linked style sheet will also remove the style definitions.
1446
* @property purgethreshold
1452
* The default interval when polling in milliseconds.
1453
* @property windowResizeDelay
1459
* Base directory for dynamic loading
1465
* The secure base dir (not implemented)
1466
* For dynamic loading.
1467
* @property secureBase
1472
* The YUI combo service base dir. Ex: `http://yui.yahooapis.com/combo?`
1473
* For dynamic loading.
1474
* @property comboBase
1479
* The root path to prepend to module path for the combo service.
1480
* Ex: 3.0.0b1/build/
1481
* For dynamic loading.
1487
* A filter to apply to result urls. This filter will modify the default
1488
* path for all modules. The default path for the YUI library is the
1489
* minified version of the files (e.g., event-min.js). The filter property
1490
* can be a predefined filter or a custom filter. The valid predefined
1494
* <dd>Selects the debug versions of the library (e.g., event-debug.js).
1495
* This option will automatically include the Logger widget</dd>
1497
* <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
1499
* You can also define a custom filter, which must be an object literal
1500
* containing a search expression and a replace string:
1503
* 'searchExp': "-min\\.js",
1504
* 'replaceStr': "-debug.js"
1507
* For dynamic loading.
1510
* @type string|object
1514
* The `skin` config let's you configure application level skin
1515
* customizations. It contains the following attributes which
1516
* can be specified to override the defaults:
1518
* // The default skin, which is automatically applied if not
1519
* // overriden by a component-specific skin definition.
1520
* // Change this in to apply a different skin globally
1521
* defaultSkin: 'sam',
1523
* // This is combined with the loader base property to get
1524
* // the default root directory for a skin.
1525
* base: 'assets/skins/',
1527
* // Any component-specific overrides can be specified here,
1528
* // making it possible to load different skins for different
1529
* // components. It is possible to load more than one skin
1530
* // for a given component as well.
1532
* slider: ['capsule', 'round']
1535
* For dynamic loading.
1541
* Hash of per-component filter specification. If specified for a given
1542
* component, this overrides the filter config.
1544
* For dynamic loading.
1550
* Use the YUI combo service to reduce the number of http connections
1551
* required to load your dependencies. Turning this off will
1552
* disable combo handling for YUI and all module groups configured
1553
* with a combo service.
1555
* For dynamic loading.
1559
* @default true if 'base' is not supplied, false if it is.
1563
* A list of modules that should never be dynamically loaded
1570
* A list of modules that should always be loaded when required, even if already
1571
* present on the page.
1578
* Node or id for a node that should be used as the insertion point for new
1579
* nodes. For dynamic loading.
1581
* @property insertBefore
1586
* Object literal containing attributes to add to dynamically loaded script
1588
* @property jsAttributes
1593
* Object literal containing attributes to add to dynamically loaded link
1595
* @property cssAttributes
1600
* Number of milliseconds before a timeout occurs when dynamically
1601
* loading nodes. If not set, there is no timeout.
1607
* Callback for the 'CSSComplete' event. When dynamically loading YUI
1608
* components with CSS, this property fires when the CSS is finished
1609
* loading but script loading is still ongoing. This provides an
1610
* opportunity to enhance the presentation of a loading page a little
1611
* bit before the entire loading process is done.
1618
* A hash of module definitions to add to the list of YUI components.
1619
* These components can then be dynamically loaded side by side with
1620
* YUI via the `use()` method. This is a hash, the key is the module
1621
* name, and the value is an object literal specifying the metdata
1622
* for the module. See `Loader.addModule` for the supported module
1623
* metadata fields. Also see groups, which provides a way to
1624
* configure the base and combo spec for a set of modules.
1628
* requires: ['node'],
1629
* fullpath: '/mymod1/mymod1.js'
1632
* requires: ['mymod1'],
1633
* fullpath: '/mymod2/mymod2.js'
1635
* mymod3: '/js/mymod3.js',
1636
* mycssmod: '/css/mycssmod.css'
1645
* Aliases are dynamic groups of modules that can be used as
1650
* davglass: [ 'node', 'yql', 'dd' ],
1651
* mine: [ 'davglass', 'autocomplete']
1653
* }).use('mine', function(Y) {
1654
* //Node, YQL, DD & AutoComplete available here..
1662
* A hash of module group definitions. It for each group you
1663
* can specify a list of modules and the base path and
1664
* combo spec to use when dynamically loading the modules.
1668
* // specify whether or not this group has a combo service
1671
* // The comboSeperator to use with this group's combo handler
1674
* // The maxURLLength for this server
1675
* maxURLLength: 500,
1677
* // the base path for non-combo paths
1678
* base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1680
* // the path to the combo service
1681
* comboBase: 'http://yui.yahooapis.com/combo?',
1683
* // a fragment to prepend to the path attribute when
1684
* // when building combo urls
1685
* root: '2.8.0r4/build/',
1687
* // the module definitions
1690
* path: "yahoo-dom-event/yahoo-dom-event.js"
1693
* path: "animation/animation.js",
1694
* requires: ['yui2_yde']
1705
* The loader 'path' attribute to the loader itself. This is combined
1706
* with the 'base' attribute to dynamically load the loader component
1707
* when boostrapping with the get utility alone.
1709
* @property loaderPath
1711
* @default loader/loader-min.js
1715
* Specifies whether or not YUI().use(...) will attempt to load CSS
1716
* resources at all. Any truthy value will cause CSS dependencies
1717
* to load when fetching script. The special value 'force' will
1718
* cause CSS dependencies to be loaded even if no script is needed.
1720
* @property fetchCSS
1721
* @type boolean|string
1726
* The default gallery version to build gallery module urls
1733
* The default YUI 2 version to build yui2 module urls. This is for
1734
* intrinsic YUI 2 support via the 2in3 project. Also see the '2in3'
1735
* config for pulling different revisions of the wrapped YUI 2
1744
* The 2in3 project is a deployment of the various versions of YUI 2
1745
* deployed as first-class YUI 3 modules. Eventually, the wrapper
1746
* for the modules will change (but the underlying YUI 2 code will
1747
* be the same), and you can select a particular version of
1748
* the wrapper modules via this config.
1756
* Alternative console log function for use in environments without
1757
* a supported native console. The function is executed in the
1758
* YUI instance context.
1765
* A callback to execute when Y.error is called. It receives the
1766
* error message and an javascript error object if Y.error was
1767
* executed because a javascript error was caught. The function
1768
* is executed in the YUI instance context. Returning `true` from this
1769
* function will stop the Error from being thrown.
1777
* A callback to execute when the loader fails to load one or
1778
* more resource. This could be because of a script load
1779
* failure. It can also fail if a javascript module fails
1780
* to register itself, but only when the 'requireRegistration'
1781
* is true. If this function is defined, the use() callback will
1782
* only be called when the loader succeeds, otherwise it always
1783
* executes unless there was a javascript error when attaching
1787
* @property loadErrorFn
1792
* When set to true, the YUI loader will expect that all modules
1793
* it is responsible for loading will be first-class YUI modules
1794
* that register themselves with the YUI global. If this is
1795
* set to true, loader will fail if the module registration fails
1796
* to happen after the script is loaded.
1799
* @property requireRegistration
1805
* Cache serviced use() requests.
1807
* @property cacheUse
1810
* @deprecated no longer used
1814
* Whether or not YUI should use native ES5 functionality when available for
1815
* features like `Y.Array.each()`, `Y.Object()`, etc. When `false`, YUI will
1816
* always use its own fallback implementations instead of relying on ES5
1817
* functionality, even when it's available.
1819
* @method useNativeES5
1824
YUI.add('yui-base', function(Y) {
1829
* @submodule yui-base
1832
* The YUI module contains the components required for building the YUI
1833
* seed file. This includes the script loading mechanism, a simple queue,
1834
* and the core utilities for the library.
1836
* @submodule yui-base
1840
* Provides core language utilites and extensions used throughout YUI.
1846
var L = Y.Lang || (Y.Lang = {}),
1848
STRING_PROTO = String.prototype,
1849
TOSTRING = Object.prototype.toString,
1852
'undefined' : 'undefined',
1853
'number' : 'number',
1854
'boolean' : 'boolean',
1855
'string' : 'string',
1856
'[object Function]': 'function',
1857
'[object RegExp]' : 'regexp',
1858
'[object Array]' : 'array',
1859
'[object Date]' : 'date',
1860
'[object Error]' : 'error'
1863
SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
1864
TRIMREGEX = /^\s+|\s+$/g,
1865
NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i;
1867
// -- Protected Methods --------------------------------------------------------
1870
Returns `true` if the given function appears to be implemented in native code,
1871
`false` otherwise. Will always return `false` -- even in ES5-capable browsers --
1872
if the `useNativeES5` YUI config option is set to `false`.
1874
This isn't guaranteed to be 100% accurate and won't work for anything other than
1875
functions, but it can be useful for determining whether a function like
1876
`Array.prototype.forEach` is native or a JS shim provided by another library.
1878
There's a great article by @kangax discussing certain flaws with this technique:
1879
<http://perfectionkills.com/detecting-built-in-host-methods/>
1881
While his points are valid, it's still possible to benefit from this function
1882
as long as it's used carefully and sparingly, and in such a way that false
1883
negatives have minimal consequences. It's used internally to avoid using
1884
potentially broken non-native ES5 shims that have been added to the page by
1888
@param {Function} fn Function to test.
1889
@return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
1894
L._isNative = function (fn) {
1895
return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
1898
// -- Public Methods -----------------------------------------------------------
1901
* Determines whether or not the provided item is an array.
1903
* Returns `false` for array-like collections such as the function `arguments`
1904
* collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
1905
* test for an array-like collection.
1908
* @param o The object to test.
1909
* @return {boolean} true if o is an array.
1912
L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
1913
return L.type(o) === 'array';
1917
* Determines whether or not the provided item is a boolean.
1920
* @param o The object to test.
1921
* @return {boolean} true if o is a boolean.
1923
L.isBoolean = function(o) {
1924
return typeof o === 'boolean';
1928
* Determines whether or not the supplied item is a date instance.
1931
* @param o The object to test.
1932
* @return {boolean} true if o is a date.
1934
L.isDate = function(o) {
1935
return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
1940
* Determines whether or not the provided item is a function.
1941
* Note: Internet Explorer thinks certain functions are objects:
1945
* var obj = document.createElement("object");
1946
* Y.Lang.isFunction(obj.getAttribute) // reports false in IE
1948
* var input = document.createElement("input"); // append to body
1949
* Y.Lang.isFunction(input.focus) // reports false in IE
1953
* You will have to implement additional tests if these functions
1957
* @method isFunction
1959
* @param o The object to test.
1960
* @return {boolean} true if o is a function.
1962
L.isFunction = function(o) {
1963
return L.type(o) === 'function';
1967
* Determines whether or not the provided item is null.
1970
* @param o The object to test.
1971
* @return {boolean} true if o is null.
1973
L.isNull = function(o) {
1978
* Determines whether or not the provided item is a legal number.
1981
* @param o The object to test.
1982
* @return {boolean} true if o is a number.
1984
L.isNumber = function(o) {
1985
return typeof o === 'number' && isFinite(o);
1989
* Determines whether or not the provided item is of type object
1990
* or function. Note that arrays are also objects, so
1991
* <code>Y.Lang.isObject([]) === true</code>.
1994
* @param o The object to test.
1995
* @param failfn {boolean} fail if the input is a function.
1996
* @return {boolean} true if o is an object.
1997
* @see isPlainObject
1999
L.isObject = function(o, failfn) {
2001
return (o && (t === 'object' ||
2002
(!failfn && (t === 'function' || L.isFunction(o))))) || false;
2006
* Determines whether or not the provided item is a string.
2009
* @param o The object to test.
2010
* @return {boolean} true if o is a string.
2012
L.isString = function(o) {
2013
return typeof o === 'string';
2017
* Determines whether or not the provided item is undefined.
2018
* @method isUndefined
2020
* @param o The object to test.
2021
* @return {boolean} true if o is undefined.
2023
L.isUndefined = function(o) {
2024
return typeof o === 'undefined';
2028
* A convenience method for detecting a legitimate non-null value.
2029
* Returns false for null/undefined/NaN, true for other values,
2030
* including 0/false/''
2033
* @param o The item to test.
2034
* @return {boolean} true if it is not null/undefined/NaN || false.
2036
L.isValue = function(o) {
2043
case 'null': // fallthru
2053
* Returns the current time in milliseconds.
2056
* @return {Number} Current time in milliseconds.
2060
L.now = Date.now || function () {
2061
return new Date().getTime();
2065
* Lightweight version of <code>Y.substitute</code>. Uses the same template
2066
* structure as <code>Y.substitute</code>, but doesn't support recursion,
2067
* auto-object coersion, or formats.
2069
* @param {string} s String to be modified.
2070
* @param {object} o Object containing replacement values.
2071
* @return {string} the substitute result.
2075
L.sub = function(s, o) {
2076
return s.replace ? s.replace(SUBREGEX, function (match, key) {
2077
return L.isUndefined(o[key]) ? match : o[key];
2082
* Returns a string without any leading or trailing whitespace. If
2083
* the input is not a string, the input will be returned untouched.
2086
* @param s {string} the string to trim.
2087
* @return {string} the trimmed string.
2089
L.trim = STRING_PROTO.trim ? function(s) {
2090
return s && s.trim ? s.trim() : s;
2093
return s.replace(TRIMREGEX, '');
2100
* Returns a string without any leading whitespace.
2103
* @param s {string} the string to trim.
2104
* @return {string} the trimmed string.
2106
L.trimLeft = STRING_PROTO.trimLeft ? function (s) {
2107
return s.trimLeft();
2109
return s.replace(/^\s+/, '');
2113
* Returns a string without any trailing whitespace.
2116
* @param s {string} the string to trim.
2117
* @return {string} the trimmed string.
2119
L.trimRight = STRING_PROTO.trimRight ? function (s) {
2120
return s.trimRight();
2122
return s.replace(/\s+$/, '');
2126
Returns one of the following strings, representing the type of the item passed
2143
* `typeof HTMLElementCollection` returns function in Safari, but
2144
`Y.Lang.type()` reports "object", which could be a good thing --
2145
but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2148
@param o the item to test.
2149
@return {string} the detected type.
2152
L.type = function(o) {
2153
return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2161
Native = Array.prototype,
2163
hasOwn = Object.prototype.hasOwnProperty;
2166
Provides utility methods for working with arrays. Additional array helpers can
2167
be found in the `collection` and `array-extras` modules.
2169
`Y.Array(thing)` returns a native array created from _thing_. Depending on
2170
_thing_'s type, one of the following will happen:
2172
* Arrays are returned unmodified unless a non-zero _startIndex_ is
2174
* Array-like collections (see `Array.test()`) are converted to arrays.
2175
* For everything else, a new array is created with _thing_ as the sole
2178
Note: elements that are also collections, such as `<form>` and `<select>`
2179
elements, are not automatically converted to arrays. To force a conversion,
2180
pass `true` as the value of the _force_ parameter.
2184
@param {Any} thing The thing to arrayify.
2185
@param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2186
collection, a subset of items starting at the specified index will be
2188
@param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2189
array-like collection no matter what.
2190
@return {Array} A native array created from _thing_, according to the rules
2193
function YArray(thing, startIndex, force) {
2196
startIndex || (startIndex = 0);
2198
if (force || YArray.test(thing)) {
2199
// IE throws when trying to slice HTMLElement collections.
2201
return Native.slice.call(thing, startIndex);
2205
for (len = thing.length; startIndex < len; ++startIndex) {
2206
result.push(thing[startIndex]);
2219
Dedupes an array of strings, returning an array that's guaranteed to contain
2220
only one copy of a given string.
2222
This method differs from `Array.unique()` in that it's optimized for use only
2223
with strings, whereas `unique` may be used with other types (but is slower).
2224
Using `dedupe()` with non-string values may result in unexpected behavior.
2227
@param {String[]} array Array of strings to dedupe.
2228
@return {Array} Deduped copy of _array_.
2232
YArray.dedupe = function (array) {
2237
for (i = 0, len = array.length; i < len; ++i) {
2240
if (!hasOwn.call(hash, item)) {
2250
Executes the supplied function on each item in the array. This method wraps
2251
the native ES5 `Array.forEach()` method if available.
2254
@param {Array} array Array to iterate.
2255
@param {Function} fn Function to execute on each item in the array. The function
2256
will receive the following arguments:
2257
@param {Any} fn.item Current array item.
2258
@param {Number} fn.index Current array index.
2259
@param {Array} fn.array Array being iterated.
2260
@param {Object} [thisObj] `this` object to use when calling _fn_.
2261
@return {YUI} The YUI instance.
2264
YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2265
Native.forEach.call(array || [], fn, thisObj || Y);
2267
} : function (array, fn, thisObj) {
2268
for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2270
fn.call(thisObj || Y, array[i], i, array);
2285
Returns an object using the first array as keys and the second as values. If
2286
the second array is not provided, or if it doesn't contain the same number of
2287
values as the first array, then `true` will be used in place of the missing
2292
Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2293
// => {a: 'foo', b: 'bar', c: true}
2296
@param {String[]} keys Array of strings to use as keys.
2297
@param {Array} [values] Array to use as values.
2298
@return {Object} Hash using the first array as keys and the second as values.
2301
YArray.hash = function (keys, values) {
2303
vlen = (values && values.length) || 0,
2306
for (i = 0, len = keys.length; i < len; ++i) {
2308
hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2316
Returns the index of the first item in the array that's equal (using a strict
2317
equality check) to the specified _value_, or `-1` if the value isn't found.
2319
This method wraps the native ES5 `Array.indexOf()` method if available.
2322
@param {Array} array Array to search.
2323
@param {Any} value Value to search for.
2324
@param {Number} [from=0] The index at which to begin the search.
2325
@return {Number} Index of the item strictly equal to _value_, or `-1` if not
2329
YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2330
return Native.indexOf.call(array, value, from);
2331
} : function (array, value, from) {
2332
// http://es5.github.com/#x15.4.4.14
2333
var len = array.length;
2336
from = (from > 0 || -1) * Math.floor(Math.abs(from));
2346
for (; from < len; ++from) {
2347
if (from in array && array[from] === value) {
2356
Numeric sort convenience function.
2358
The native `Array.prototype.sort()` function converts values to strings and
2359
sorts them in lexicographic order, which is unsuitable for sorting numeric
2360
values. Provide `Array.numericSort` as a custom sort function when you want
2361
to sort values in numeric order.
2365
[42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2366
// => [4, 8, 15, 16, 23, 42]
2369
@param {Number} a First value to compare.
2370
@param {Number} b Second value to compare.
2371
@return {Number} Difference between _a_ and _b_.
2374
YArray.numericSort = function (a, b) {
2379
Executes the supplied function on each item in the array. Returning a truthy
2380
value from the function will stop the processing of remaining items.
2383
@param {Array} array Array to iterate over.
2384
@param {Function} fn Function to execute on each item. The function will receive
2385
the following arguments:
2386
@param {Any} fn.value Current array item.
2387
@param {Number} fn.index Current array index.
2388
@param {Array} fn.array Array being iterated over.
2389
@param {Object} [thisObj] `this` object to use when calling _fn_.
2390
@return {Boolean} `true` if the function returns a truthy value on any of the
2391
items in the array; `false` otherwise.
2394
YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2395
return Native.some.call(array, fn, thisObj);
2396
} : function (array, fn, thisObj) {
2397
for (var i = 0, len = array.length; i < len; ++i) {
2398
if (i in array && fn.call(thisObj, array[i], i, array)) {
2407
Evaluates _obj_ to determine if it's an array, an array-like collection, or
2408
something else. This is useful when working with the function `arguments`
2409
collection and `HTMLElement` collections.
2411
Note: This implementation doesn't consider elements that are also
2412
collections, such as `<form>` and `<select>`, to be array-like.
2415
@param {Object} obj Object to test.
2416
@return {Number} A number indicating the results of the test:
2418
* 0: Neither an array nor an array-like collection.
2420
* 2: Array-like collection.
2424
YArray.test = function (obj) {
2427
if (Lang.isArray(obj)) {
2429
} else if (Lang.isObject(obj)) {
2431
// indexed, but no tagName (element) or alert (window),
2432
// or functions without apply/call (Safari
2433
// HTMLElementCollection bug).
2434
if ('length' in obj && !obj.tagName && !obj.alert && !obj.apply) {
2443
* The YUI module contains the components required for building the YUI
2444
* seed file. This includes the script loading mechanism, a simple queue,
2445
* and the core utilities for the library.
2447
* @submodule yui-base
2451
* A simple FIFO queue. Items are added to the Queue with add(1..n items) and
2452
* removed using next().
2456
* @param {MIXED} item* 0..n items to seed the queue.
2460
this.add.apply(this, arguments);
2465
* Initialize the queue
2472
* The collection of enqueued items
2482
* Get the next item in the queue. FIFO support
2485
* @return {MIXED} the next item in the queue.
2488
return this._q.shift();
2492
* Get the last in the queue. LIFO support.
2495
* @return {MIXED} the last item in the queue.
2498
return this._q.pop();
2502
* Add 0..n items to the end of the queue.
2505
* @param {MIXED} item* 0..n items.
2506
* @return {object} this queue.
2509
this._q.push.apply(this._q, arguments);
2515
* Returns the current number of queued items.
2518
* @return {Number} The size.
2521
return this._q.length;
2527
YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2530
The YUI module contains the components required for building the YUI seed file.
2531
This includes the script loading mechanism, a simple queue, and the core
2532
utilities for the library.
2538
var CACHED_DELIMITER = '__',
2540
hasOwn = Object.prototype.hasOwnProperty,
2541
isObject = Y.Lang.isObject;
2544
Returns a wrapper for a function which caches the return value of that function,
2545
keyed off of the combined string representation of the argument values provided
2546
when the wrapper is called.
2548
Calling this function again with the same arguments will return the cached value
2549
rather than executing the wrapped function.
2551
Note that since the cache is keyed off of the string representation of arguments
2552
passed to the wrapper function, arguments that aren't strings and don't provide
2553
a meaningful `toString()` method may result in unexpected caching behavior. For
2554
example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2555
string `[object Object]` when used as a cache key.
2558
@param {Function} source The function to memoize.
2559
@param {Object} [cache={}] Object in which to store cached values. You may seed
2560
this object with pre-existing cached values if desired.
2561
@param {any} [refetch] If supplied, this value is compared with the cached value
2562
using a `==` comparison. If the values are equal, the wrapped function is
2563
executed again even though a cached value exists.
2564
@return {Function} Wrapped function.
2567
Y.cached = function (source, cache, refetch) {
2568
cache || (cache = {});
2570
return function (arg) {
2571
var key = arguments.length > 1 ?
2572
Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2575
if (!(key in cache) || (refetch && cache[key] == refetch)) {
2576
cache[key] = source.apply(source, arguments);
2584
Returns the `location` object from the window/frame in which this YUI instance
2585
operates, or `undefined` when executing in a non-browser environment
2588
It is _not_ recommended to hold references to the `window.location` object
2589
outside of the scope of a function in which its properties are being accessed or
2590
its methods are being called. This is because of a nasty bug/issue that exists
2591
in both Safari and MobileSafari browsers:
2592
[WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
2595
@return {location} The `location` object from the window/frame in which this YUI
2599
Y.getLocation = function () {
2600
// It is safer to look this up every time because yui-base is attached to a
2601
// YUI instance before a user's config is applied; i.e. `Y.config.win` does
2602
// not point the correct window object when this file is loaded.
2603
var win = Y.config.win;
2605
// It is not safe to hold a reference to the `location` object outside the
2606
// scope in which it is being used. The WebKit engine used in Safari and
2607
// MobileSafari will "disconnect" the `location` object from the `window`
2608
// when a page is restored from back/forward history cache.
2609
return win && win.location;
2613
Returns a new object containing all of the properties of all the supplied
2614
objects. The properties from later objects will overwrite those in earlier
2617
Passing in a single object will create a shallow copy of it. For a deep copy,
2621
@param {Object} objects* One or more objects to merge.
2622
@return {Object} A new merged object.
2624
Y.merge = function () {
2625
var args = arguments,
2630
for (; i < len; ++i) {
2631
Y.mix(result, args[i], true);
2638
Mixes _supplier_'s properties into _receiver_.
2640
Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
2641
shadowed unless the _overwrite_ parameter is `true`, and will not be merged
2642
unless the _merge_ parameter is `true`.
2644
In the default mode (0), only properties the supplier owns are copied (prototype
2645
properties are not copied). The following copying modes are available:
2647
* `0`: _Default_. Object to object.
2648
* `1`: Prototype to prototype.
2649
* `2`: Prototype to prototype and object to object.
2650
* `3`: Prototype to object.
2651
* `4`: Object to prototype.
2654
@param {Function|Object} receiver The object or function to receive the mixed
2656
@param {Function|Object} supplier The object or function supplying the
2657
properties to be mixed.
2658
@param {Boolean} [overwrite=false] If `true`, properties that already exist
2659
on the receiver will be overwritten with properties from the supplier.
2660
@param {String[]} [whitelist] An array of property names to copy. If
2661
specified, only the whitelisted properties will be copied, and all others
2663
@param {Number} [mode=0] Mix mode to use. See above for available modes.
2664
@param {Boolean} [merge=false] If `true`, objects and arrays that already
2665
exist on the receiver will have the corresponding object/array from the
2666
supplier merged into them, rather than being skipped or overwritten. When
2667
both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
2668
@return {Function|Object|YUI} The receiver, or the YUI instance if the
2669
specified receiver is falsy.
2671
Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
2672
var alwaysOverwrite, exists, from, i, key, len, to;
2674
// If no supplier is given, we return the receiver. If no receiver is given,
2675
// we return Y. Returning Y doesn't make much sense to me, but it's
2676
// grandfathered in for backcompat reasons.
2677
if (!receiver || !supplier) {
2678
return receiver || Y;
2682
// In mode 2 (prototype to prototype and object to object), we recurse
2683
// once to do the proto to proto mix. The object to object mix will be
2684
// handled later on.
2686
Y.mix(receiver.prototype, supplier.prototype, overwrite,
2687
whitelist, 0, merge);
2690
// Depending on which mode is specified, we may be copying from or to
2691
// the prototypes of the supplier and receiver.
2692
from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
2693
to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
2695
// If either the supplier or receiver doesn't actually have a
2696
// prototype property, then we could end up with an undefined `from`
2697
// or `to`. If that happens, we abort and return the receiver.
2706
// If `overwrite` is truthy and `merge` is falsy, then we can skip a
2707
// property existence check on each iteration and save some time.
2708
alwaysOverwrite = overwrite && !merge;
2711
for (i = 0, len = whitelist.length; i < len; ++i) {
2714
// We call `Object.prototype.hasOwnProperty` instead of calling
2715
// `hasOwnProperty` on the object itself, since the object's
2716
// `hasOwnProperty` method may have been overridden or removed.
2717
// Also, some native objects don't implement a `hasOwnProperty`
2719
if (!hasOwn.call(from, key)) {
2723
// The `key in to` check here is (sadly) intentional for backwards
2724
// compatibility reasons. It prevents undesired shadowing of
2725
// prototype members on `to`.
2726
exists = alwaysOverwrite ? false : key in to;
2728
if (merge && exists && isObject(to[key], true)
2729
&& isObject(from[key], true)) {
2730
// If we're in merge mode, and the key is present on both
2731
// objects, and the value on both objects is either an object or
2732
// an array (but not a function), then we recurse to merge the
2733
// `from` value into the `to` value instead of overwriting it.
2735
// Note: It's intentional that the whitelist isn't passed to the
2736
// recursive call here. This is legacy behavior that lots of
2737
// code still depends on.
2738
Y.mix(to[key], from[key], overwrite, null, 0, merge);
2739
} else if (overwrite || !exists) {
2740
// We're not in merge mode, so we'll only copy the `from` value
2741
// to the `to` value if we're in overwrite mode or if the
2742
// current key doesn't exist on the `to` object.
2743
to[key] = from[key];
2748
// The code duplication here is for runtime performance reasons.
2749
// Combining whitelist and non-whitelist operations into a single
2750
// loop or breaking the shared logic out into a function both result
2751
// in worse performance, and Y.mix is critical enough that the byte
2752
// tradeoff is worth it.
2753
if (!hasOwn.call(from, key)) {
2757
// The `key in to` check here is (sadly) intentional for backwards
2758
// compatibility reasons. It prevents undesired shadowing of
2759
// prototype members on `to`.
2760
exists = alwaysOverwrite ? false : key in to;
2762
if (merge && exists && isObject(to[key], true)
2763
&& isObject(from[key], true)) {
2764
Y.mix(to[key], from[key], overwrite, null, 0, merge);
2765
} else if (overwrite || !exists) {
2766
to[key] = from[key];
2770
// If this is an IE browser with the JScript enumeration bug, force
2771
// enumeration of the buggy properties by making a recursive call with
2772
// the buggy properties as the whitelist.
2773
if (Y.Object._hasEnumBug) {
2774
Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
2781
* The YUI module contains the components required for building the YUI
2782
* seed file. This includes the script loading mechanism, a simple queue,
2783
* and the core utilities for the library.
2785
* @submodule yui-base
2789
* Adds utilities to the YUI instance for working with objects.
2795
hasOwn = Object.prototype.hasOwnProperty,
2797
UNDEFINED, // <-- Note the comma. We're still declaring vars.
2800
* Returns a new object that uses _obj_ as its prototype. This method wraps the
2801
* native ES5 `Object.create()` method if available, but doesn't currently
2802
* pass through `Object.create()`'s second argument (properties) in order to
2803
* ensure compatibility with older browsers.
2806
* @param {Object} obj Prototype object.
2807
* @return {Object} New object using _obj_ as its prototype.
2810
O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
2811
// We currently wrap the native Object.create instead of simply aliasing it
2812
// to ensure consistency with our fallback shim, which currently doesn't
2813
// support Object.create()'s second argument (properties). Once we have a
2814
// safe fallback for the properties arg, we can stop wrapping
2816
return Object.create(obj);
2818
// Reusable constructor function for the Object.create() shim.
2822
return function (obj) {
2829
* Property names that IE doesn't enumerate in for..in loops, even when they
2830
* should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
2831
* manually enumerate these properties.
2833
* @property _forceEnum
2838
forceEnum = O._forceEnum = [
2841
'propertyIsEnumerable',
2848
* `true` if this browser has the JScript enumeration bug that prevents
2849
* enumeration of the properties named in the `_forceEnum` array, `false`
2853
* - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
2854
* - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
2856
* @property _hasEnumBug
2861
hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
2864
* `true` if this browser incorrectly considers the `prototype` property of
2865
* functions to be enumerable. Currently known to affect Opera 11.50.
2867
* @property _hasProtoEnumBug
2872
hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
2875
* Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
2876
* exists only on _obj_'s prototype. This is essentially a safer version of
2877
* `obj.hasOwnProperty()`.
2880
* @param {Object} obj Object to test.
2881
* @param {String} key Property name to look for.
2882
* @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2885
owns = O.owns = function (obj, key) {
2886
return !!obj && hasOwn.call(obj, key);
2887
}; // <-- End of var declarations.
2890
* Alias for `owns()`.
2893
* @param {Object} obj Object to test.
2894
* @param {String} key Property name to look for.
2895
* @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2901
* Returns an array containing the object's enumerable keys. Does not include
2902
* prototype keys or non-enumerable keys.
2904
* Note that keys are returned in enumeration order (that is, in the same order
2905
* that they would be enumerated by a `for-in` loop), which may not be the same
2906
* as the order in which they were defined.
2908
* This method is an alias for the native ES5 `Object.keys()` method if
2913
* Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
2914
* // => ['a', 'b', 'c']
2917
* @param {Object} obj An object.
2918
* @return {String[]} Array of keys.
2921
O.keys = Lang._isNative(Object.keys) ? Object.keys : function (obj) {
2922
if (!Lang.isObject(obj)) {
2923
throw new TypeError('Object.keys called on a non-object');
2929
if (hasProtoEnumBug && typeof obj === 'function') {
2931
if (owns(obj, key) && key !== 'prototype') {
2937
if (owns(obj, key)) {
2944
for (i = 0, len = forceEnum.length; i < len; ++i) {
2947
if (owns(obj, key)) {
2957
* Returns an array containing the values of the object's enumerable keys.
2959
* Note that values are returned in enumeration order (that is, in the same
2960
* order that they would be enumerated by a `for-in` loop), which may not be the
2961
* same as the order in which they were defined.
2965
* Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
2966
* // => ['foo', 'bar', 'baz']
2969
* @param {Object} obj An object.
2970
* @return {Array} Array of values.
2973
O.values = function (obj) {
2974
var keys = O.keys(obj),
2979
for (; i < len; ++i) {
2980
values.push(obj[keys[i]]);
2987
* Returns the number of enumerable keys owned by an object.
2990
* @param {Object} obj An object.
2991
* @return {Number} The object's size.
2994
O.size = function (obj) {
2996
return O.keys(obj).length;
2998
return 0; // Legacy behavior for non-objects.
3003
* Returns `true` if the object owns an enumerable property with the specified
3007
* @param {Object} obj An object.
3008
* @param {any} value The value to search for.
3009
* @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3012
O.hasValue = function (obj, value) {
3013
return Y.Array.indexOf(O.values(obj), value) > -1;
3017
* Executes a function on each enumerable property in _obj_. The function
3018
* receives the value, the key, and the object itself as parameters (in that
3021
* By default, only properties owned by _obj_ are enumerated. To include
3022
* prototype properties, set the _proto_ parameter to `true`.
3025
* @param {Object} obj Object to enumerate.
3026
* @param {Function} fn Function to execute on each enumerable property.
3027
* @param {mixed} fn.value Value of the current property.
3028
* @param {String} fn.key Key of the current property.
3029
* @param {Object} fn.obj Object being enumerated.
3030
* @param {Object} [thisObj] `this` object to use when calling _fn_.
3031
* @param {Boolean} [proto=false] Include prototype properties.
3032
* @return {YUI} the YUI instance.
3036
O.each = function (obj, fn, thisObj, proto) {
3040
if (proto || owns(obj, key)) {
3041
fn.call(thisObj || Y, obj[key], key, obj);
3049
* Executes a function on each enumerable property in _obj_, but halts if the
3050
* function returns a truthy value. The function receives the value, the key,
3051
* and the object itself as paramters (in that order).
3053
* By default, only properties owned by _obj_ are enumerated. To include
3054
* prototype properties, set the _proto_ parameter to `true`.
3057
* @param {Object} obj Object to enumerate.
3058
* @param {Function} fn Function to execute on each enumerable property.
3059
* @param {mixed} fn.value Value of the current property.
3060
* @param {String} fn.key Key of the current property.
3061
* @param {Object} fn.obj Object being enumerated.
3062
* @param {Object} [thisObj] `this` object to use when calling _fn_.
3063
* @param {Boolean} [proto=false] Include prototype properties.
3064
* @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3065
* `false` otherwise.
3068
O.some = function (obj, fn, thisObj, proto) {
3072
if (proto || owns(obj, key)) {
3073
if (fn.call(thisObj || Y, obj[key], key, obj)) {
3083
* Retrieves the sub value at the provided path,
3084
* from the value object provided.
3088
* @param o The object from which to extract the property value.
3089
* @param path {Array} A path array, specifying the object traversal path
3090
* from which to obtain the sub value.
3091
* @return {Any} The value stored in the path, undefined if not found,
3092
* undefined if the source is not an object. Returns the source object
3093
* if an empty path is provided.
3095
O.getValue = function(o, path) {
3096
if (!Lang.isObject(o)) {
3104
for (i = 0; o !== UNDEFINED && i < l; i++) {
3112
* Sets the sub-attribute value at the provided path on the
3113
* value object. Returns the modified value object, or
3114
* undefined if the path is invalid.
3118
* @param o The object on which to set the sub value.
3119
* @param path {Array} A path array, specifying the object traversal path
3120
* at which to set the sub value.
3121
* @param val {Any} The new value for the sub-attribute.
3122
* @return {Object} The modified object, with the new sub value set, or
3123
* undefined, if the path was invalid.
3125
O.setValue = function(o, path, val) {
3128
leafIdx = p.length - 1,
3132
for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3136
if (ref !== UNDEFINED) {
3147
* Returns `true` if the object has no enumerable properties of its own.
3150
* @param {Object} obj An object.
3151
* @return {Boolean} `true` if the object is empty.
3155
O.isEmpty = function (obj) {
3156
return !O.keys(Object(obj)).length;
3159
* The YUI module contains the components required for building the YUI seed
3160
* file. This includes the script loading mechanism, a simple queue, and the
3161
* core utilities for the library.
3163
* @submodule yui-base
3167
* YUI user agent detection.
3168
* Do not fork for a browser if it can be avoided. Use feature detection when
3169
* you can. Use the user agent as a last resort. For all fields listed
3170
* as @type float, UA stores a version number for the browser engine,
3171
* 0 otherwise. This value may or may not map to the version number of
3172
* the browser using the engine. The value is presented as a float so
3173
* that it can easily be used for boolean evaluation as well as for
3174
* looking for a particular range of versions. Because of this,
3175
* some of the granularity of the version info may be lost. The fields that
3176
* are @type string default to null. The API docs list the values that
3177
* these fields can have.
3183
* Static method on `YUI.Env` for parsing a UA string. Called at instantiation
3184
* to populate `Y.UA`.
3188
* @param {String} [subUA=navigator.userAgent] UA string to parse
3189
* @return {Object} The Y.UA object
3191
YUI.Env.parseUA = function(subUA) {
3193
var numberify = function(s) {
3195
return parseFloat(s.replace(/\./g, function() {
3196
return (c++ == 1) ? '' : '.';
3202
nav = win && win.navigator,
3207
* Internet Explorer version number or 0. Example: 6
3215
* Opera version number or 0. Example: 9.2
3223
* Gecko engine revision number. Will evaluate to 1 if Gecko
3224
* is detected but the revision could not be found. Other browsers
3225
* will be 0. Example: 1.8
3227
* Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
3228
* Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3229
* Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3230
* Firefox 3.0 <-- 1.9
3231
* Firefox 3.5 <-- 1.91
3240
* AppleWebKit version. KHTML browsers that are not WebKit browsers
3241
* will evaluate to 1, other browsers 0. Example: 418.9
3243
* Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3244
* latest available for Mac OSX 10.3.
3245
* Safari 2.0.2: 416 <-- hasOwnProperty introduced
3246
* Safari 2.0.4: 418 <-- preventDefault fixed
3247
* Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3248
* different versions of webkit
3249
* Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
3250
* updated, but not updated
3251
* to the latest patch.
3252
* Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native
3253
* SVG and many major issues fixed).
3254
* Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic
3255
* update from 2.x via the 10.4.11 OS patch.
3256
* Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
3257
* yahoo.com user agent hack removed.
3259
* http://en.wikipedia.org/wiki/Safari_version_history
3267
* Safari will be detected as webkit, but this property will also
3268
* be populated with the Safari version number
3276
* Chrome will be detected as webkit, but this property will also
3277
* be populated with the Chrome version number
3285
* The mobile property will be set to a string containing any relevant
3286
* user agent information when a modern mobile browser is detected.
3287
* Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3288
* devices with the WebKit-based browser, and Opera Mini.
3297
* Adobe AIR version number or 0. Only populated if webkit is detected.
3304
* Detects Apple iPad's OS version
3311
* Detects Apple iPhone's OS version
3318
* Detects Apples iPod's OS version
3325
* General truthy check for iPad, iPhone or iPod
3333
* Detects Googles Android OS version
3340
* Detects Kindle Silk
3347
* Detects Kindle Silk Acceleration
3354
* Detects Palms WebOS version
3362
* Google Caja version number or 0.
3366
caja: nav && nav.cajaVersion,
3369
* Set to true if the page appears to be in SSL
3377
* The operating system. Currently only detecting windows or macintosh
3386
* The Nodejs Version
3395
ua = subUA || nav && nav.userAgent,
3397
loc = win && win.location,
3399
href = loc && loc.href,
3404
* The User Agent string that was parsed
3405
* @property userAgent
3412
o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3416
if ((/windows|win32/i).test(ua)) {
3418
} else if ((/macintosh|mac_powerpc/i).test(ua)) {
3420
} else if ((/android/i).test(ua)) {
3422
} else if ((/symbos/i).test(ua)) {
3424
} else if ((/linux/i).test(ua)) {
3426
} else if ((/rhino/i).test(ua)) {
3430
// Modern KHTML browsers should qualify as Safari X-Grade
3431
if ((/KHTML/).test(ua)) {
3434
if ((/IEMobile|XBLWP7/).test(ua)) {
3435
o.mobile = 'windows';
3437
if ((/Fennec/).test(ua)) {
3440
// Modern WebKit browsers are at least X-Grade
3441
m = ua.match(/AppleWebKit\/([^\s]*)/);
3443
o.webkit = numberify(m[1]);
3444
o.safari = o.webkit;
3446
// Mobile browser check
3447
if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
3448
o.mobile = 'Apple'; // iPhone or iPod Touch
3450
m = ua.match(/OS ([^\s]*)/);
3452
m = numberify(m[1].replace('_', '.'));
3456
o.ipad = o.ipod = o.iphone = 0;
3458
m = ua.match(/iPad|iPod|iPhone/);
3460
o[m[0].toLowerCase()] = o.ios;
3463
m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3465
// Nokia N-series, webOS, ex: NokiaN95
3468
if (/webOS/.test(ua)) {
3470
m = ua.match(/webOS\/([^\s]*);/);
3472
o.webos = numberify(m[1]);
3475
if (/ Android/.test(ua)) {
3476
if (/Mobile/.test(ua)) {
3477
o.mobile = 'Android';
3479
m = ua.match(/Android ([^\s]*);/);
3481
o.android = numberify(m[1]);
3485
if (/Silk/.test(ua)) {
3486
m = ua.match(/Silk\/([^\s]*)\)/);
3488
o.silk = numberify(m[1]);
3491
o.android = 2.34; //Hack for desktop mode in Kindle
3494
if (/Accelerated=true/.test(ua)) {
3500
m = ua.match(/(Chrome|CrMo)\/([^\s]*)/);
3501
if (m && m[1] && m[2]) {
3502
o.chrome = numberify(m[2]); // Chrome
3503
o.safari = 0; //Reset safari back to 0
3504
if (m[1] === 'CrMo') {
3505
o.mobile = 'chrome';
3508
m = ua.match(/AdobeAIR\/([^\s]*)/);
3510
o.air = m[0]; // Adobe AIR 1.0 or better
3515
if (!o.webkit) { // not webkit
3516
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3517
if (/Opera/.test(ua)) {
3518
m = ua.match(/Opera[\s\/]([^\s]*)/);
3520
o.opera = numberify(m[1]);
3522
m = ua.match(/Version\/([^\s]*)/);
3524
o.opera = numberify(m[1]); // opera 10+
3527
if (/Opera Mobi/.test(ua)) {
3529
m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
3531
o.opera = numberify(m[1]);
3534
m = ua.match(/Opera Mini[^;]*/);
3537
o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3539
} else { // not opera or webkit
3540
m = ua.match(/MSIE\s([^;]*)/);
3542
o.ie = numberify(m[1]);
3543
} else { // not opera, webkit, or ie
3544
m = ua.match(/Gecko\/([^\s]*)/);
3546
o.gecko = 1; // Gecko detected, look for revision
3547
m = ua.match(/rv:([^\s\)]*)/);
3549
o.gecko = numberify(m[1]);
3557
//It was a parsed UA, do not assign the global value.
3560
if (typeof process == 'object') {
3562
if (process.versions && process.versions.node) {
3564
o.os = process.platform;
3565
o.nodejs = process.versions.node;
3577
Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3580
Performs a simple comparison between two version numbers, accounting for
3581
standard versioning logic such as the fact that "535.8" is a lower version than
3582
"535.24", even though a simple numerical comparison would indicate that it's
3583
greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
3584
considered equivalent.
3586
Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
3587
1 if _a_ is higher than _b_.
3589
Versions may be numbers or strings containing numbers and dots. For example,
3590
both `535` and `"535.8.10"` are acceptable. A version string containing
3591
non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
3593
@method compareVersions
3594
@param {Number|String} a First version number to compare.
3595
@param {Number|String} b Second version number to compare.
3596
@return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
3599
Y.UA.compareVersions = function (a, b) {
3600
var aPart, aParts, bPart, bParts, i, len;
3606
aParts = (a + '').split('.');
3607
bParts = (b + '').split('.');
3609
for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
3610
aPart = parseInt(aParts[i], 10);
3611
bPart = parseInt(bParts[i], 10);
3613
isNaN(aPart) && (aPart = 0);
3614
isNaN(bPart) && (bPart = 0);
3616
if (aPart < bPart) {
3620
if (aPart > bPart) {
3628
"anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
3629
"app": ["app-base","app-transitions","model","model-list","router","view"],
3630
"attribute": ["attribute-base","attribute-complex"],
3631
"autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
3632
"base": ["base-base","base-pluginhost","base-build"],
3633
"cache": ["cache-base","cache-offline","cache-plugin"],
3634
"collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
3635
"controller": ["router"],
3636
"dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
3637
"datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
3638
"datatable": ["datatable-core","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
3639
"datatable-deprecated": ["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"],
3640
"datatype": ["datatype-number","datatype-date","datatype-xml"],
3641
"datatype-date": ["datatype-date-parse","datatype-date-format"],
3642
"datatype-number": ["datatype-number-parse","datatype-number-format"],
3643
"datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
3644
"dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
3645
"dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
3646
"editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
3647
"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"],
3648
"event-custom": ["event-custom-base","event-custom-complex"],
3649
"event-gestures": ["event-flick","event-move"],
3650
"handlebars": ["handlebars-compiler"],
3651
"highlight": ["highlight-base","highlight-accentfold"],
3652
"history": ["history-base","history-hash","history-hash-ie","history-html5"],
3653
"io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
3654
"json": ["json-parse","json-stringify"],
3655
"loader": ["loader-base","loader-rollup","loader-yui3"],
3656
"node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
3657
"pluginhost": ["pluginhost-base","pluginhost-config"],
3658
"querystring": ["querystring-parse","querystring-stringify"],
3659
"recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
3660
"resize": ["resize-base","resize-proxy","resize-constrain"],
3661
"slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
3662
"text": ["text-accentfold","text-wordbreak"],
3663
"widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]