2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
9 The YUI module contains the components required for building the YUI seed file.
10 This includes the script loading mechanism, a simple queue, and the core
11 utilities for the library.
18 /*jshint eqeqeq: false*/
19 if (typeof YUI != 'undefined') {
24 The YUI global namespace object. This is the constructor for all YUI instances.
26 This is a self-instantiable factory function, meaning you don't need to precede
27 it with the `new` operator. You can invoke it directly like this:
29 YUI().use('*', function (Y) {
30 // Y is a new YUI instance.
33 But it also works like this:
37 The `YUI` constructor accepts an optional config object, like this:
42 }).use('node', function (Y) {
43 // Y.Node is ready to use.
46 See the API docs for the <a href="config.html">Config</a> class for the complete
47 list of supported configuration properties accepted by the YUI constuctor.
49 If a global `YUI` object is already defined, the existing YUI object will not be
50 overwritten, to ensure that defined namespaces are preserved.
52 Each YUI instance has full custom event support, but only if the event system is
59 @param {Object} [config]* Zero or more optional configuration objects. Config
60 values are stored in the `Y.config` property. See the
61 <a href="config.html">Config</a> docs for the list of supported properties.
66 var YUI = function() {
71 instanceOf = function(o, type) {
72 return (o && o.hasOwnProperty && (o instanceof type));
74 gconf = (typeof YUI_config !== 'undefined') && YUI_config;
76 if (!(instanceOf(Y, YUI))) {
79 // set up the core environment
83 Master configuration that might span multiple contexts in a non-
84 browser environment. It is applied first to all instances in all
93 YUI().use('node', function (Y) {
94 // debug files used here
99 }).use('node', function (Y) {
100 // min files used here
103 @property {Object} GlobalConfig
107 if (YUI.GlobalConfig) {
108 Y.applyConfig(YUI.GlobalConfig);
112 Page-level config applied to all YUI instances created on the
113 current page. This is applied after `YUI.GlobalConfig` and before
114 any instance-level configuration.
118 // Single global var to include before YUI seed file
123 YUI().use('node', function (Y) {
124 // debug files used here
129 }).use('node', function (Y) {
130 // min files used here
133 @property {Object} YUI_config
137 Y.applyConfig(gconf);
140 // bind the specified additional modules for this instance
147 // Each instance can accept one or more configuration objects.
148 // These are applied after YUI.GlobalConfig and YUI_Config,
149 // overriding values set in those config files if there is a
150 // matching property.
152 Y.applyConfig(args[i]);
158 Y.instanceOf = instanceOf;
168 BASE = 'http://yui.yahooapis.com/',
170 These CSS class names can't be generated by
171 getClassName since it is not available at the
172 time they are being used.
174 DOC_LABEL = 'yui3-js-enabled',
175 CSS_STAMP_EL = 'yui3-css-stamp',
176 NOOP = function() {},
177 SLICE = Array.prototype.slice,
178 APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo
179 'io.xdrResponse': 1, // can call. this should
180 'SWF.eventHandler': 1 }, // be done at build time
181 hasWin = (typeof window != 'undefined'),
182 win = (hasWin) ? window : null,
183 doc = (hasWin) ? win.document : null,
184 docEl = doc && doc.documentElement,
185 docClass = docEl && docEl.className,
187 time = new Date().getTime(),
188 add = function(el, type, fn, capture) {
189 if (el && el.addEventListener) {
190 el.addEventListener(type, fn, capture);
191 } else if (el && el.attachEvent) {
192 el.attachEvent('on' + type, fn);
195 remove = function(el, type, fn, capture) {
196 if (el && el.removeEventListener) {
197 // this can throw an uncaught exception in FF
199 el.removeEventListener(type, fn, capture);
201 } else if (el && el.detachEvent) {
202 el.detachEvent('on' + type, fn);
205 handleLoad = function() {
206 YUI.Env.windowLoaded = true;
207 YUI.Env.DOMReady = true;
209 remove(window, 'load', handleLoad);
212 getLoader = function(Y, o) {
213 var loader = Y.Env._loader,
214 lCore = [ 'loader-base' ],
219 //loader._config(Y.config);
220 loader.ignoreRegistered = false;
223 loader.required = [];
224 loader.loadType = null;
226 loader = new Y.Loader(Y.config);
227 Y.Env._loader = loader;
229 if (mods && mods.loader) {
230 lCore = [].concat(lCore, YUI.Env.loaderExtras);
232 YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore));
237 clobber = function(r, s) {
239 if (s.hasOwnProperty(i)) {
245 ALREADY_DONE = { success: true };
247 // Stamp the documentElement (HTML) with a class of "yui-loaded" to
248 // enable styles that need to key off of JS being enabled.
249 if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
253 docClass += DOC_LABEL;
254 docEl.className = docClass;
257 if (VERSION.indexOf('@') > -1) {
258 VERSION = '3.5.0'; // dev time hack for cdn test
263 Applies a new configuration object to the config of this YUI instance. This
264 will merge new group/module definitions, and will also update the loader
265 cache if necessary. Updating `Y.config` directly will not update the cache.
268 @param {Object} o the configuration object.
271 applyConfig: function(o) {
278 config = this.config,
279 mods = config.modules,
280 groups = config.groups,
281 aliases = config.aliases,
282 loader = this.Env._loader;
285 if (o.hasOwnProperty(name)) {
287 if (mods && name == 'modules') {
289 } else if (aliases && name == 'aliases') {
290 clobber(aliases, attr);
291 } else if (groups && name == 'groups') {
292 clobber(groups, attr);
293 } else if (name == 'win') {
294 config[name] = (attr && attr.contentWindow) || attr;
295 config.doc = config[name] ? config[name].document : null;
296 } else if (name == '_yuid') {
311 Old way to apply a config to this instance (calls `applyConfig` under the
316 @param {Object} o The config to apply
318 _config: function(o) {
323 Initializes this YUI instance.
336 The version number of this YUI instance.
338 This value is typically updated by a script when a YUI release is built,
339 so it may not reflect the correct version number when YUI is run from
340 the development source tree.
342 @property {String} version
349 loaderExtras: ['loader-rollup', 'loader-yui3'],
350 mods: {}, // flat module map
351 versions: {}, // version module map
353 cdn: BASE + VERSION + '/build/',
354 // bootstrapped: false,
365 // I'll start at the \b(yui).
366 // 1. Look in the test string for "yui" or
367 // "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it
368 // can't match "foyui" or "i_heart_yui". This can be anywhere in the string.
369 // 2. After #1 must come a forward slash followed by the string matched in #1, so
370 // "yui-base/yui-base" or "yui-pants/yui-pants".
371 // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
372 // so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
373 // 4. This is followed by ".js", so "yui/yui.js".
374 // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
375 // then capture the junk between the LAST "&" and the string in 1-4. So
376 // "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
377 // will capture "3.3.0/build/"
381 // (?:[^&]*&) followed by 0..n characters followed by an &
382 // * in fact, find as many sets of characters followed by a & as you can
383 // ([^&]*) capture the stuff after the last & in \1
384 // )? but it's ok if all this ?junk&more_junk stuff isn't even there
385 // \b( after a word break find either the string
386 // yui(?:-\w+)? "yui" optionally followed by a -, then more characters
387 // ) and store the yui-* string in \2
388 // \/\2 then comes a / followed by the yui-* string in \2
389 // (?:-(min|debug))? optionally followed by "-min" or "-debug"
390 // .js and ending in ".js"
391 _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
392 parseBasePath: function(src, pattern) {
393 var match = src.match(pattern),
397 path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
399 // this is to set up the path to the loader. The file
400 // filter for loader should match the yui include.
403 // extract correct path for mixed combo urls
404 // http://yuilibrary.com/projects/yui3/ticket/2528423
406 path += '?' + match[1];
415 getBase: G_ENV && G_ENV.getBase ||
417 var nodes = (doc && doc.getElementsByTagName('script')) || [],
418 path = Env.cdn, parsed,
421 for (i = 0, len = nodes.length; i < len; ++i) {
424 parsed = Y.Env.parseBasePath(src, pattern);
426 filter = parsed.filter;
441 Env._loaded[VERSION] = {};
443 if (G_ENV && Y !== YUI) {
444 Env._yidx = ++G_ENV._yidx;
445 Env._guidp = ('yui_' + VERSION + '_' +
446 Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_');
447 } else if (YUI._YUI) {
449 G_ENV = YUI._YUI.Env;
450 Env._yidx += G_ENV._yidx;
451 Env._uidx += G_ENV._uidx;
453 for (prop in G_ENV) {
454 if (!(prop in Env)) {
455 Env[prop] = G_ENV[prop];
469 // configuration defaults
470 Y.config = Y.config || {
477 useBrowserConsole: true,
480 global: Function('return this')()
483 //Register the CSS stamp element
484 if (doc && !doc.getElementById(CSS_STAMP_EL)) {
485 el = doc.createElement('div');
486 el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
487 YUI.Env.cssStampEl = el.firstChild;
489 doc.body.appendChild(YUI.Env.cssStampEl);
491 docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
493 } else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) {
494 YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL);
497 Y.config.lang = Y.config.lang || 'en-US';
499 Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
501 if (!filter || (!('mindebug').indexOf(filter))) {
504 filter = (filter) ? '-' + filter : filter;
505 Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
510 Finishes the instance setup. Attaches whatever YUI modules were defined
511 at the time that this instance was created.
520 extras = Y.config.core || [].concat(YUI.Env.core); //Clone it..
522 for (i = 0; i < extras.length; i++) {
523 if (mods[extras[i]]) {
524 core.push(extras[i]);
528 Y._attach(['yui-base']);
538 Executes the named method on the specified YUI instance if that method is
542 @param {String} id YUI instance id.
543 @param {String} method Name of the method to execute. For example:
545 @param {Array} args Arguments to apply to the method.
546 @return {Mixed} Return value from the applied method, or `null` if the
547 specified instance was not found or the method was not whitelisted.
549 applyTo: function(id, method, args) {
550 if (!(method in APPLY_TO_AUTH)) {
551 this.log(method + ': applyTo not allowed', 'warn', 'yui');
555 var instance = instances[id], nest, m, i;
557 nest = method.split('.');
559 for (i = 0; i < nest.length; i = i + 1) {
562 this.log('applyTo not found: ' + method, 'warn', 'yui');
565 return m && m.apply(instance, args);
572 Registers a YUI module and makes it available for use in a `YUI().use()` call or
573 as a dependency for other modules.
575 The easiest way to create a first-class YUI module is to use
576 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
579 Shifter will automatically wrap your module code in a `YUI.add()` call along
580 with any configuration info required for the module.
584 YUI.add('davglass', function (Y) {
585 Y.davglass = function () {
588 requires: ['harley-davidson', 'mt-dew']
592 @param {String} name Module name.
593 @param {Function} fn Function containing module code. This function will be
594 executed whenever the module is attached to a specific YUI instance.
596 @param {YUI} fn.Y The YUI instance to which this module is attached.
597 @param {String} fn.name Name of the module
599 @param {String} version Module version number. This is currently used only for
600 informational purposes, and is not used internally by YUI.
602 @param {Object} [config] Module config.
603 @param {Array} [config.requires] Array of other module names that must be
604 attached before this module can be attached.
605 @param {Array} [config.optional] Array of optional module names that should
606 be attached before this module is attached if they've already been
607 loaded. If the `loadOptional` YUI option is `true`, optional modules
608 that have not yet been loaded will be loaded just as if they were hard
610 @param {Array} [config.use] Array of module names that are included within
611 or otherwise provided by this module, and which should be attached
612 automatically when this module is attached. This makes it possible to
613 create "virtual rollup" modules that simply attach a collection of other
614 modules or submodules.
616 @return {YUI} This YUI instance.
618 add: function(name, fn, version, details) {
619 details = details || {};
627 //Instance hash so we don't apply it to the same instance twice
630 i, versions = env.versions;
632 env.mods[name] = mod;
633 versions[version] = versions[version] || {};
634 versions[version][name] = mod;
636 for (i in instances) {
637 if (instances.hasOwnProperty(i)) {
639 if (!applied[inst.id]) {
640 applied[inst.id] = true;
641 loader = inst.Env._loader;
643 if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
644 loader.addModule(details, name);
655 Executes the callback function associated with each required module,
656 attaching the module to this YUI instance.
659 @param {Array} r The array of modules to attach
660 @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
664 _attach: function(r, moot) {
665 var i, name, mod, details, req, use, after,
667 aliases = YUI.Env.aliases,
669 cache = YUI.Env._renderedMods,
670 loader = Y.Env._loader,
671 done = Y.Env._attached,
672 len = r.length, loader, def, go,
675 //Check for conditional modules (in a second+ instance) and add their requirements
676 //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
677 for (i = 0; i < len; i++) {
681 if (loader && loader.conditions[name]) {
682 for (j in loader.conditions[name]) {
683 if (loader.conditions[name].hasOwnProperty(j)) {
684 def = loader.conditions[name][j];
685 go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
696 for (i = 0; i < len; i++) {
701 if (aliases && aliases[name] && !mod) {
702 Y._attach(aliases[name]);
706 if (loader && loader.moduleInfo[name]) {
707 mod = loader.moduleInfo[name];
712 //if (!loader || !loader.moduleInfo[name]) {
713 //if ((!loader || !loader.moduleInfo[name]) && !moot) {
715 if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
716 Y.Env._missed.push(name);
717 Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
718 Y.message('NOT loaded: ' + name, 'warn', 'yui');
723 //Don't like this, but in case a mod was asked for once, then we fetch it
724 //We need to remove it from the missed list ^davglass
725 for (j = 0; j < Y.Env._missed.length; j++) {
726 if (Y.Env._missed[j] === name) {
727 Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
728 Y.Env._missed.splice(j, 1);
732 If it's a temp module, we need to redo it's requirements if it's already loaded
733 since it may have been loaded by another instance and it's dependencies might
734 have been redefined inside the fetched file.
736 if (loader && cache && cache[name] && cache[name].temp) {
737 loader.getRequires(cache[name]);
739 for (j in loader.moduleInfo[name].expanded_map) {
740 if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
747 details = mod.details;
748 req = details.requires;
750 after = details.after;
751 //Force Intl load if there is a language (Loader logic) @todo fix this shit
758 for (j = 0; j < req.length; j++) {
760 if (!Y._attach(req)) {
769 for (j = 0; j < after.length; j++) {
770 if (!done[after[j]]) {
771 if (!Y._attach(after, true)) {
780 if (Y.config.throwFail) {
786 Y.error('Attach error: ' + name, e, name);
793 for (j = 0; j < use.length; j++) {
795 if (!Y._attach(use)) {
813 Delays the `use` callback until another event has taken place such as
814 `window.onload`, `domready`, `contentready`, or `available`.
817 @method _delayCallback
818 @param {Function} cb The original `use` callback.
819 @param {String|Object} until Either an event name ('load', 'domready', etc.)
820 or an object containing event/args keys for contentready/available.
823 _delayCallback: function(cb, until) {
826 mod = ['event-base'];
828 until = (Y.Lang.isObject(until) ? until : { event: until });
830 if (until.event === 'load') {
831 mod.push('event-synthetic');
835 var args = arguments;
836 Y._use(mod, function() {
837 Y.on(until.event, function() {
838 args[1].delayUntil = until.event;
846 Attaches one or more modules to this YUI instance. When this is executed,
847 the requirements of the desired modules are analyzed, and one of several
851 * All required modules have already been loaded, and just need to be
852 attached to this YUI instance. In this case, the `use()` callback will
853 be executed synchronously after the modules are attached.
855 * One or more modules have not yet been loaded, or the Get utility is not
856 available, or the `bootstrap` config option is `false`. In this case,
857 a warning is issued indicating that modules are missing, but all
858 available modules will still be attached and the `use()` callback will
859 be executed synchronously.
861 * One or more modules are missing and the Loader is not available but the
862 Get utility is, and `bootstrap` is not `false`. In this case, the Get
863 utility will be used to load the Loader, and we will then proceed to
866 * One or more modules are missing and the Loader is available. In this
867 case, the Loader will be used to resolve the dependency tree for the
868 missing modules and load them and their dependencies. When the Loader is
869 finished loading modules, the `use()` callback will be executed
874 // Loads and attaches dd and its dependencies.
875 YUI().use('dd', function (Y) {
879 // Loads and attaches dd and node as well as all of their dependencies.
880 YUI().use(['dd', 'node'], function (Y) {
884 // Attaches all modules that have already been loaded.
885 YUI().use('*', function (Y) {
889 // Attaches a gallery module.
890 YUI().use('gallery-yql', function (Y) {
894 // Attaches a YUI 2in3 module.
895 YUI().use('yui2-datatable', function (Y) {
900 @param {String|Array} modules* One or more module names to attach.
901 @param {Function} [callback] Callback function to be executed once all
902 specified modules and their dependencies have been attached.
903 @param {YUI} callback.Y The YUI instance created for this sandbox.
904 @param {Object} callback.status Object containing `success`, `msg` and
909 var args = SLICE.call(arguments, 0),
910 callback = args[args.length - 1],
917 // The last argument supplied to use can be a load complete callback
918 if (Y.Lang.isFunction(callback)) {
920 if (Y.config.delayUntil) {
921 callback = Y._delayCallback(callback, Y.config.delayUntil);
926 if (Y.Lang.isArray(args[0])) {
930 if (Y.config.cacheUse) {
931 while ((name = args[i++])) {
932 if (!Env._attached[name]) {
941 Y._notify(callback, ALREADY_DONE, args);
947 Y._useQueue = Y._useQueue || new Y.Queue();
948 Y._useQueue.add([args, callback]);
950 Y._use(args, function(Y, response) {
951 Y._notify(callback, response, args);
959 Handles Loader notifications about attachment/load errors.
962 @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
963 @param {Object} response Response returned from Loader.
964 @param {Array} args Arguments passed from Loader.
967 _notify: function(callback, response, args) {
968 if (!response.success && this.config.loadErrorFn) {
969 this.config.loadErrorFn.call(this, this, callback, response, args);
970 } else if (callback) {
971 if (this.Env._missed && this.Env._missed.length) {
972 response.msg = 'Missing modules: ' + this.Env._missed.join();
973 response.success = false;
975 if (this.config.throwFail) {
976 callback(this, response);
979 callback(this, response);
981 this.error('use callback error', e, args);
988 Called from the `use` method queue to ensure that only one set of loading
989 logic is performed at a time.
992 @param {String} args* One or more modules to attach.
993 @param {Function} [callback] Function to call once all required modules have
997 _use: function(args, callback) {
1000 this._attach(['yui-base']);
1003 var len, loader, handleBoot,
1009 aliases = G_ENV.aliases,
1010 queue = G_ENV._loaderQueue,
1014 boot = config.bootstrap,
1019 fetchCSS = config.fetchCSS,
1020 process = function(names, skip) {
1022 var i = 0, a = [], name, len, m, req, use;
1024 if (!names.length) {
1030 for (i = 0; i < len; i++) {
1031 if (aliases[names[i]] && !mods[names[i]]) {
1032 a = [].concat(a, aliases[names[i]]);
1042 for (i = 0; i < len; i++) {
1048 // only attach a module once
1059 req = m.details.requires;
1060 use = m.details.use;
1062 // CSS files don't register themselves, see if it has
1064 if (!G_ENV._loaded[VERSION][name]) {
1067 used[name] = true; // probably css
1071 // make sure requirements are attached
1072 if (req && req.length) {
1076 // make sure we grab the submodule dependencies too
1077 if (use && use.length) {
1084 handleLoader = function(fromLoader) {
1085 var response = fromLoader || {
1091 data = response.data;
1096 origMissing = missing;
1100 redo = missing.length;
1102 if ([].concat(missing).sort().join() ==
1103 origMissing.sort().join()) {
1111 Y._use(missing, function() {
1112 if (Y._attach(data)) {
1113 Y._notify(callback, response, data);
1118 ret = Y._attach(data);
1121 Y._notify(callback, response, args);
1125 if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
1126 Y._use.apply(Y, Y._useQueue.next());
1132 // YUI().use('*'); // bind everything available
1133 if (firstArg === '*') {
1136 if (mods.hasOwnProperty(i)) {
1140 ret = Y._attach(args);
1147 if ((mods.loader || mods['loader-base']) && !Y.Loader) {
1148 Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
1152 // use loader to expand dependencies and sort the
1153 // requirements if it is available.
1154 if (boot && Y.Loader && args.length) {
1155 loader = getLoader(Y);
1156 loader.require(args);
1157 loader.ignoreRegistered = true;
1158 loader._boot = true;
1159 loader.calculate(null, (fetchCSS) ? null : 'js');
1160 args = loader.sorted;
1161 loader._boot = false;
1166 len = missing.length;
1170 missing = YArray.dedupe(missing);
1171 len = missing.length;
1176 if (boot && len && Y.Loader) {
1178 loader = getLoader(Y);
1179 loader.onEnd = handleLoader;
1182 loader.ignoreRegistered = false;
1183 loader.require(missing);
1184 loader.insert(null, (fetchCSS) ? null : 'js');
1186 } else if (boot && len && Y.Get && !Env.bootstrapped) {
1190 handleBoot = function() {
1192 queue.running = false;
1193 Env.bootstrapped = true;
1194 G_ENV._bootstrapping = false;
1195 if (Y._attach(['loader'])) {
1196 Y._use(args, callback);
1200 if (G_ENV._bootstrapping) {
1201 queue.add(handleBoot);
1203 G_ENV._bootstrapping = true;
1204 Y.Get.script(config.base + config.loaderPath, {
1210 ret = Y._attach(args);
1221 Utility method for safely creating namespaces if they don't already exist.
1222 May be called statically on the YUI global object or as a method on a YUI
1225 When called statically, a namespace will be created on the YUI global
1228 // Create `YUI.your.namespace.here` as nested objects, preserving any
1229 // objects that already exist instead of overwriting them.
1230 YUI.namespace('your.namespace.here');
1232 When called as a method on a YUI instance, a namespace will be created on
1235 // Creates `Y.property.package`.
1236 Y.namespace('property.package');
1238 Dots in the input string cause `namespace` to create nested objects for each
1239 token. If any part of the requested namespace already exists, the current
1240 object will be left in place and will not be overwritten. This allows
1241 multiple calls to `namespace` to preserve existing namespaced properties.
1243 If the first token in the namespace string is "YAHOO", that token is
1244 discarded. This is legacy behavior for backwards compatibility with YUI 2.
1246 Be careful with namespace tokens. Reserved words may work in some browsers
1247 and not others. For instance, the following will fail in some browsers
1248 because the supported version of JavaScript reserves the word "long":
1250 Y.namespace('really.long.nested.namespace');
1252 Note: If you pass multiple arguments to create multiple namespaces, only the
1253 last one created is returned from this function.
1256 @param {String} namespace* One or more namespaces to create.
1257 @return {Object} Reference to the last namespace object created.
1259 namespace: function() {
1260 var a = arguments, o, i = 0, j, d, arg;
1262 for (; i < a.length; i++) {
1263 o = this; //Reset base object per argument or it will get reused from the last
1265 if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1266 d = arg.split(PERIOD);
1267 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1268 o[d[j]] = o[d[j]] || {};
1272 o[arg] = o[arg] || {};
1273 o = o[arg]; //Reset base object to the new object so it's returned
1279 // this is replaced if the log module is included
1282 // this is replaced if the dump module is included
1283 dump: function (o) { return ''+o; },
1288 The reporting mechanism is controlled by the `throwFail` configuration
1289 attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
1290 truthy, a JS exception is thrown.
1292 If an `errorFn` is specified in the config it must return `true` to indicate
1293 that the exception was handled and keep it from being thrown.
1296 @param {String} msg Error message.
1297 @param {Error|String} [e] JavaScript error object or an error string.
1298 @param {String} [src] Source of the error (such as the name of the module in
1299 which the error occurred).
1302 error: function(msg, e, src) {
1303 //TODO Add check for window.onerror here
1307 if (Y.config.errorFn) {
1308 ret = Y.config.errorFn.apply(Y, arguments);
1312 throw (e || new Error(msg));
1314 Y.message(msg, 'error', ''+src); // don't scrub this one
1321 Generates an id string that is unique among all YUI instances in this
1325 @param {String} [pre] Prefix.
1326 @return {String} Unique id.
1328 guid: function(pre) {
1329 var id = this.Env._guidp + '_' + (++this.Env._uidx);
1330 return (pre) ? (pre + id) : id;
1334 Returns a unique id associated with the given object and (if *readOnly* is
1335 falsy) stamps the object with that id so it can be identified in the future.
1337 Stamping an object involves adding a `_yuid` property to it that contains
1338 the object's id. One exception to this is that in Internet Explorer, DOM
1339 nodes have a `uniqueID` property that contains a browser-generated unique
1340 id, which will be used instead of a YUI-generated id when available.
1343 @param {Object} o Object to stamp.
1344 @param {Boolean} readOnly If truthy and the given object has not already
1345 been stamped, the object will not be modified and `null` will be
1347 @return {String} Object's unique id, or `null` if *readOnly* was truthy and
1348 the given object was not already stamped.
1350 stamp: function(o, readOnly) {
1356 // IE generates its own unique ID for dom nodes
1357 // The uniqueID property of a document node returns a new ID
1358 if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1361 uid = (typeof o === 'string') ? o : o._yuid;
1378 Destroys this YUI instance.
1383 destroy: function() {
1388 delete instances[Y.id];
1394 Safe `instanceof` wrapper that works around a memory leak in IE when the
1395 object being tested is `window` or `document`.
1397 Unless you are testing objects that may be `window` or `document`, you
1398 should use the native `instanceof` operator instead of this method.
1401 @param {Object} o Object to check.
1402 @param {Object} type Class to check against.
1407 YUI.prototype = proto;
1409 // inheritance utilities are not available yet
1410 for (prop in proto) {
1411 if (proto.hasOwnProperty(prop)) {
1412 YUI[prop] = proto[prop];
1417 Applies a configuration to all YUI instances in this execution context.
1419 The main use case for this method is in "mashups" where several third-party
1420 scripts need to write to a global YUI config, but cannot share a single
1421 centrally-managed config object. This way they can all call
1422 `YUI.applyConfig({})` instead of overwriting the single global config.
1429 fullpath: './davglass.js'
1437 fullpath: './foo.js'
1442 YUI().use('davglass', function (Y) {
1443 // Module davglass will be available here.
1447 @param {Object} o Configuration object to apply.
1451 YUI.applyConfig = function(o) {
1455 //If there is a GlobalConfig, apply it first to set the defaults
1456 if (YUI.GlobalConfig) {
1457 this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1459 //Apply this config to it
1460 this.prototype.applyConfig.call(this, o);
1461 //Reset GlobalConfig to the combined config
1462 YUI.GlobalConfig = this.config;
1465 // set up the environment
1469 // add a window load event at load time so we can capture
1470 // the case where it fires before dynamic loading is
1472 add(window, 'load', handleLoad);
1478 YUI.Env.remove = remove;
1481 // Support the CommonJS method for exporting our single global
1482 if (typeof exports == 'object') {
1485 * Set a method to be called when `Get.script` is called in Node.js
1486 * `Get` will open the file, then pass it's content and it's path
1487 * to this method before attaching it. Commonly used for code coverage
1488 * instrumentation. <strong>Calling this multiple times will only
1489 * attach the last hook method</strong>. This method is only
1490 * available in Node.js.
1491 * @method setLoadHook
1493 * @param {Function} fn The function to set
1494 * @param {String} fn.data The content of the file
1495 * @param {String} fn.path The file path of the file
1497 YUI.setLoadHook = function(fn) {
1498 YUI._getLoadHook = fn;
1501 * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
1502 * @method _getLoadHook
1504 * @param {String} data The content of the file
1505 * @param {String} path The file path of the file
1507 YUI._getLoadHook = null;
1510 YUI.Env[VERSION] = {};
1515 Config object that contains all of the configuration options for
1516 this `YUI` instance.
1518 This object is supplied by the implementer when instantiating YUI. Some
1519 properties have default values if they are not supplied by the implementer.
1521 This object should not be updated directly because some values are cached. Use
1522 `applyConfig()` to update the config object on a YUI instance that has already
1530 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
1531 if they're needed to load additional dependencies and aren't already available.
1533 Setting this to `false` will prevent YUI from automatically loading the Loader
1534 and module metadata, so you will need to manually ensure that they're available
1535 or handle dependency resolution yourself.
1537 @property {Boolean} bootstrap
1543 @property {Object} aliases
1547 A hash of module group definitions.
1549 For each group you can specify a list of modules and the base path and
1550 combo spec to use when dynamically loading the modules.
1556 // specify whether or not this group has a combo service
1559 // The comboSeperator to use with this group's combo handler
1562 // The maxURLLength for this server
1565 // the base path for non-combo paths
1566 base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1568 // the path to the combo service
1569 comboBase: 'http://yui.yahooapis.com/combo?',
1571 // a fragment to prepend to the path attribute when
1572 // when building combo urls
1573 root: '2.8.0r4/build/',
1575 // the module definitions
1578 path: "yahoo-dom-event/yahoo-dom-event.js"
1581 path: "animation/animation.js",
1582 requires: ['yui2_yde']
1588 @property {Object} groups
1592 Path to the Loader JS file, relative to the `base` path.
1594 This is used to dynamically bootstrap the Loader when it's needed and isn't yet
1597 @property {String} loaderPath
1598 @default "loader/loader-min.js"
1602 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
1603 `false` to prevent YUI from loading any CSS, or set it to the string `"force"`
1604 to force CSS dependencies to be loaded even if their associated JS modules are
1607 @property {Boolean|String} fetchCSS
1612 Default gallery version used to build gallery module urls.
1614 @property {String} gallery
1619 Default YUI 2 version used to build YUI 2 module urls.
1621 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
1622 `2in3` config for pulling different revisions of the wrapped YUI 2 modules.
1624 @property {String} yui2
1630 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
1632 @property {String} 2in3
1638 Alternate console log function that should be used in environments without a
1639 supported native console. This function is executed with the YUI instance as its
1642 @property {Function} logFn
1647 The minimum log level to log messages for. Log levels are defined
1648 incrementally. Messages greater than or equal to the level specified will
1649 be shown. All others will be discarded. The order of log levels in
1650 increasing priority is:
1657 @property {String} logLevel
1663 Callback to execute when `Y.error()` is called. It receives the error message
1664 and a JavaScript error object if one was provided.
1666 This function is executed with the YUI instance as its `this` object.
1668 Returning `true` from this function will prevent an exception from being thrown.
1670 @property {Function} errorFn
1671 @param {String} errorFn.msg Error message
1672 @param {Object} [errorFn.err] Error object (if one was provided).
1677 A callback to execute when Loader fails to load one or more resources.
1679 This could be because of a script load failure. It could also be because a
1680 module fails to register itself when the `requireRegistration` config is `true`.
1682 If this function is defined, the `use()` callback will only be called when the
1683 loader succeeds. Otherwise, `use()` will always executes unless there was a
1684 JavaScript error when attaching a module.
1686 @property {Function} loadErrorFn
1691 If `true`, Loader will expect all loaded scripts to be first-class YUI modules
1692 that register themselves with the YUI global, and will trigger a failure if a
1693 loaded script does not register a YUI module.
1695 @property {Boolean} requireRegistration
1701 Cache serviced use() requests.
1703 @property {Boolean} cacheUse
1706 @deprecated No longer used.
1710 Whether or not YUI should use native ES5 functionality when available for
1711 features like `Y.Array.each()`, `Y.Object()`, etc.
1713 When `false`, YUI will always use its own fallback implementations instead of
1714 relying on ES5 functionality, even when ES5 functionality is available.
1716 @property {Boolean} useNativeES5
1722 * Leverage native JSON stringify if the browser has a native
1723 * implementation. In general, this is a good idea. See the Known Issues
1724 * section in the JSON user guide for caveats. The default value is true
1725 * for browsers with native JSON support.
1727 * @property useNativeJSONStringify
1734 * Leverage native JSON parse if the browser has a native implementation.
1735 * In general, this is a good idea. See the Known Issues section in the
1736 * JSON user guide for caveats. The default value is true for browsers with
1737 * native JSON support.
1739 * @property useNativeJSONParse
1746 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
1748 @property {Object|String} delayUntil
1752 You can use `load` or `domready` strings by default:
1755 delayUntil: 'domready'
1757 // This will not execute until 'domeready' occurs.
1760 Or you can delay until a node is available (with `available` or `contentready`):
1768 // This will not execute until a node matching the selector "#foo" is
1769 // available in the DOM.
1773 YUI.add('yui-base', function (Y, NAME) {
1778 * @submodule yui-base
1781 * The YUI module contains the components required for building the YUI
1782 * seed file. This includes the script loading mechanism, a simple queue,
1783 * and the core utilities for the library.
1785 * @submodule yui-base
1789 * Provides core language utilites and extensions used throughout YUI.
1795 var L = Y.Lang || (Y.Lang = {}),
1797 STRING_PROTO = String.prototype,
1798 TOSTRING = Object.prototype.toString,
1801 'undefined' : 'undefined',
1802 'number' : 'number',
1803 'boolean' : 'boolean',
1804 'string' : 'string',
1805 '[object Function]': 'function',
1806 '[object RegExp]' : 'regexp',
1807 '[object Array]' : 'array',
1808 '[object Date]' : 'date',
1809 '[object Error]' : 'error'
1812 SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
1814 WHITESPACE = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF",
1815 WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+",
1816 TRIM_LEFT_REGEX = new RegExp("^" + WHITESPACE_CLASS),
1817 TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"),
1818 TRIMREGEX = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"),
1820 NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i;
1822 // -- Protected Methods --------------------------------------------------------
1825 Returns `true` if the given function appears to be implemented in native code,
1826 `false` otherwise. Will always return `false` -- even in ES5-capable browsers --
1827 if the `useNativeES5` YUI config option is set to `false`.
1829 This isn't guaranteed to be 100% accurate and won't work for anything other than
1830 functions, but it can be useful for determining whether a function like
1831 `Array.prototype.forEach` is native or a JS shim provided by another library.
1833 There's a great article by @kangax discussing certain flaws with this technique:
1834 <http://perfectionkills.com/detecting-built-in-host-methods/>
1836 While his points are valid, it's still possible to benefit from this function
1837 as long as it's used carefully and sparingly, and in such a way that false
1838 negatives have minimal consequences. It's used internally to avoid using
1839 potentially broken non-native ES5 shims that have been added to the page by
1843 @param {Function} fn Function to test.
1844 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
1849 L._isNative = function (fn) {
1850 return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
1853 // -- Public Methods -----------------------------------------------------------
1856 * Determines whether or not the provided item is an array.
1858 * Returns `false` for array-like collections such as the function `arguments`
1859 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
1860 * test for an array-like collection.
1863 * @param o The object to test.
1864 * @return {boolean} true if o is an array.
1867 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
1868 return L.type(o) === 'array';
1872 * Determines whether or not the provided item is a boolean.
1875 * @param o The object to test.
1876 * @return {boolean} true if o is a boolean.
1878 L.isBoolean = function(o) {
1879 return typeof o === 'boolean';
1883 * Determines whether or not the supplied item is a date instance.
1886 * @param o The object to test.
1887 * @return {boolean} true if o is a date.
1889 L.isDate = function(o) {
1890 return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
1895 * Determines whether or not the provided item is a function.
1896 * Note: Internet Explorer thinks certain functions are objects:
1900 * var obj = document.createElement("object");
1901 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
1903 * var input = document.createElement("input"); // append to body
1904 * Y.Lang.isFunction(input.focus) // reports false in IE
1908 * You will have to implement additional tests if these functions
1912 * @method isFunction
1914 * @param o The object to test.
1915 * @return {boolean} true if o is a function.
1917 L.isFunction = function(o) {
1918 return L.type(o) === 'function';
1922 * Determines whether or not the provided item is null.
1925 * @param o The object to test.
1926 * @return {boolean} true if o is null.
1928 L.isNull = function(o) {
1933 * Determines whether or not the provided item is a legal number.
1936 * @param o The object to test.
1937 * @return {boolean} true if o is a number.
1939 L.isNumber = function(o) {
1940 return typeof o === 'number' && isFinite(o);
1944 * Determines whether or not the provided item is of type object
1945 * or function. Note that arrays are also objects, so
1946 * <code>Y.Lang.isObject([]) === true</code>.
1949 * @param o The object to test.
1950 * @param failfn {boolean} fail if the input is a function.
1951 * @return {boolean} true if o is an object.
1952 * @see isPlainObject
1954 L.isObject = function(o, failfn) {
1956 return (o && (t === 'object' ||
1957 (!failfn && (t === 'function' || L.isFunction(o))))) || false;
1961 * Determines whether or not the provided value is a regexp.
1964 * @param value The value or object to test.
1965 * @return {boolean} true if value is a regexp.
1967 L.isRegExp = function(value) {
1968 return L.type(value) === 'regexp';
1972 * Determines whether or not the provided item is a string.
1975 * @param o The object to test.
1976 * @return {boolean} true if o is a string.
1978 L.isString = function(o) {
1979 return typeof o === 'string';
1983 * Determines whether or not the provided item is undefined.
1984 * @method isUndefined
1986 * @param o The object to test.
1987 * @return {boolean} true if o is undefined.
1989 L.isUndefined = function(o) {
1990 return typeof o === 'undefined';
1994 * A convenience method for detecting a legitimate non-null value.
1995 * Returns false for null/undefined/NaN, true for other values,
1996 * including 0/false/''
1999 * @param o The item to test.
2000 * @return {boolean} true if it is not null/undefined/NaN || false.
2002 L.isValue = function(o) {
2009 case 'null': // fallthru
2019 * Returns the current time in milliseconds.
2022 * @return {Number} Current time in milliseconds.
2026 L.now = Date.now || function () {
2027 return new Date().getTime();
2031 * Lightweight version of <code>Y.substitute</code>. Uses the same template
2032 * structure as <code>Y.substitute</code>, but doesn't support recursion,
2033 * auto-object coersion, or formats.
2035 * @param {string} s String to be modified.
2036 * @param {object} o Object containing replacement values.
2037 * @return {string} the substitute result.
2041 L.sub = function(s, o) {
2042 return s.replace ? s.replace(SUBREGEX, function (match, key) {
2043 return L.isUndefined(o[key]) ? match : o[key];
2048 * Returns a string without any leading or trailing whitespace. If
2049 * the input is not a string, the input will be returned untouched.
2052 * @param s {string} the string to trim.
2053 * @return {string} the trimmed string.
2055 L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) {
2056 return s && s.trim ? s.trim() : s;
2059 return s.replace(TRIMREGEX, '');
2066 * Returns a string without any leading whitespace.
2069 * @param s {string} the string to trim.
2070 * @return {string} the trimmed string.
2072 L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) {
2073 return s.trimLeft();
2075 return s.replace(TRIM_LEFT_REGEX, '');
2079 * Returns a string without any trailing whitespace.
2082 * @param s {string} the string to trim.
2083 * @return {string} the trimmed string.
2085 L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) {
2086 return s.trimRight();
2088 return s.replace(TRIM_RIGHT_REGEX, '');
2092 Returns one of the following strings, representing the type of the item passed
2109 * `typeof HTMLElementCollection` returns function in Safari, but
2110 `Y.Lang.type()` reports "object", which could be a good thing --
2111 but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2114 @param o the item to test.
2115 @return {string} the detected type.
2118 L.type = function(o) {
2119 return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2127 Native = Array.prototype,
2129 hasOwn = Object.prototype.hasOwnProperty;
2132 Provides utility methods for working with arrays. Additional array helpers can
2133 be found in the `collection` and `array-extras` modules.
2135 `Y.Array(thing)` returns a native array created from _thing_. Depending on
2136 _thing_'s type, one of the following will happen:
2138 * Arrays are returned unmodified unless a non-zero _startIndex_ is
2140 * Array-like collections (see `Array.test()`) are converted to arrays.
2141 * For everything else, a new array is created with _thing_ as the sole
2144 Note: elements that are also collections, such as `<form>` and `<select>`
2145 elements, are not automatically converted to arrays. To force a conversion,
2146 pass `true` as the value of the _force_ parameter.
2150 @param {Any} thing The thing to arrayify.
2151 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2152 collection, a subset of items starting at the specified index will be
2154 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2155 array-like collection no matter what.
2156 @return {Array} A native array created from _thing_, according to the rules
2159 function YArray(thing, startIndex, force) {
2162 /*jshint expr: true*/
2163 startIndex || (startIndex = 0);
2165 if (force || YArray.test(thing)) {
2166 // IE throws when trying to slice HTMLElement collections.
2168 return Native.slice.call(thing, startIndex);
2172 for (len = thing.length; startIndex < len; ++startIndex) {
2173 result.push(thing[startIndex]);
2186 Dedupes an array of strings, returning an array that's guaranteed to contain
2187 only one copy of a given string.
2189 This method differs from `Array.unique()` in that it's optimized for use only
2190 with arrays consisting entirely of strings or entirely of numbers, whereas
2191 `unique` may be used with other value types (but is slower).
2193 Using `dedupe()` with values other than strings or numbers, or with arrays
2194 containing a mix of strings and numbers, may result in unexpected behavior.
2197 @param {String[]|Number[]} array Array of strings or numbers to dedupe.
2198 @return {Array} Copy of _array_ containing no duplicate values.
2202 YArray.dedupe = Lang._isNative(Object.create) ? function (array) {
2203 var hash = Object.create(null),
2207 for (i = 0, len = array.length; i < len; ++i) {
2217 } : function (array) {
2222 for (i = 0, len = array.length; i < len; ++i) {
2225 if (!hasOwn.call(hash, item)) {
2235 Executes the supplied function on each item in the array. This method wraps
2236 the native ES5 `Array.forEach()` method if available.
2239 @param {Array} array Array to iterate.
2240 @param {Function} fn Function to execute on each item in the array. The function
2241 will receive the following arguments:
2242 @param {Any} fn.item Current array item.
2243 @param {Number} fn.index Current array index.
2244 @param {Array} fn.array Array being iterated.
2245 @param {Object} [thisObj] `this` object to use when calling _fn_.
2246 @return {YUI} The YUI instance.
2249 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2250 Native.forEach.call(array || [], fn, thisObj || Y);
2252 } : function (array, fn, thisObj) {
2253 for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2255 fn.call(thisObj || Y, array[i], i, array);
2270 Returns an object using the first array as keys and the second as values. If
2271 the second array is not provided, or if it doesn't contain the same number of
2272 values as the first array, then `true` will be used in place of the missing
2277 Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2278 // => {a: 'foo', b: 'bar', c: true}
2281 @param {String[]} keys Array of strings to use as keys.
2282 @param {Array} [values] Array to use as values.
2283 @return {Object} Hash using the first array as keys and the second as values.
2286 YArray.hash = function (keys, values) {
2288 vlen = (values && values.length) || 0,
2291 for (i = 0, len = keys.length; i < len; ++i) {
2293 hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2301 Returns the index of the first item in the array that's equal (using a strict
2302 equality check) to the specified _value_, or `-1` if the value isn't found.
2304 This method wraps the native ES5 `Array.indexOf()` method if available.
2307 @param {Array} array Array to search.
2308 @param {Any} value Value to search for.
2309 @param {Number} [from=0] The index at which to begin the search.
2310 @return {Number} Index of the item strictly equal to _value_, or `-1` if not
2314 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2315 return Native.indexOf.call(array, value, from);
2316 } : function (array, value, from) {
2317 // http://es5.github.com/#x15.4.4.14
2318 var len = array.length;
2321 from = (from > 0 || -1) * Math.floor(Math.abs(from));
2331 for (; from < len; ++from) {
2332 if (from in array && array[from] === value) {
2341 Numeric sort convenience function.
2343 The native `Array.prototype.sort()` function converts values to strings and
2344 sorts them in lexicographic order, which is unsuitable for sorting numeric
2345 values. Provide `Array.numericSort` as a custom sort function when you want
2346 to sort values in numeric order.
2350 [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2351 // => [4, 8, 15, 16, 23, 42]
2354 @param {Number} a First value to compare.
2355 @param {Number} b Second value to compare.
2356 @return {Number} Difference between _a_ and _b_.
2359 YArray.numericSort = function (a, b) {
2364 Executes the supplied function on each item in the array. Returning a truthy
2365 value from the function will stop the processing of remaining items.
2368 @param {Array} array Array to iterate over.
2369 @param {Function} fn Function to execute on each item. The function will receive
2370 the following arguments:
2371 @param {Any} fn.value Current array item.
2372 @param {Number} fn.index Current array index.
2373 @param {Array} fn.array Array being iterated over.
2374 @param {Object} [thisObj] `this` object to use when calling _fn_.
2375 @return {Boolean} `true` if the function returns a truthy value on any of the
2376 items in the array; `false` otherwise.
2379 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2380 return Native.some.call(array, fn, thisObj);
2381 } : function (array, fn, thisObj) {
2382 for (var i = 0, len = array.length; i < len; ++i) {
2383 if (i in array && fn.call(thisObj, array[i], i, array)) {
2392 Evaluates _obj_ to determine if it's an array, an array-like collection, or
2393 something else. This is useful when working with the function `arguments`
2394 collection and `HTMLElement` collections.
2396 Note: This implementation doesn't consider elements that are also
2397 collections, such as `<form>` and `<select>`, to be array-like.
2400 @param {Object} obj Object to test.
2401 @return {Number} A number indicating the results of the test:
2403 * 0: Neither an array nor an array-like collection.
2405 * 2: Array-like collection.
2409 YArray.test = function (obj) {
2412 if (Lang.isArray(obj)) {
2414 } else if (Lang.isObject(obj)) {
2416 // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
2417 // or functions without apply/call (Safari
2418 // HTMLElementCollection bug).
2419 if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
2428 * The YUI module contains the components required for building the YUI
2429 * seed file. This includes the script loading mechanism, a simple queue,
2430 * and the core utilities for the library.
2432 * @submodule yui-base
2436 * A simple FIFO queue. Items are added to the Queue with add(1..n items) and
2437 * removed using next().
2441 * @param {MIXED} item* 0..n items to seed the queue.
2445 this.add.apply(this, arguments);
2450 * Initialize the queue
2457 * The collection of enqueued items
2467 * Get the next item in the queue. FIFO support
2470 * @return {MIXED} the next item in the queue.
2473 return this._q.shift();
2477 * Get the last in the queue. LIFO support.
2480 * @return {MIXED} the last item in the queue.
2483 return this._q.pop();
2487 * Add 0..n items to the end of the queue.
2490 * @param {MIXED} item* 0..n items.
2491 * @return {object} this queue.
2494 this._q.push.apply(this._q, arguments);
2500 * Returns the current number of queued items.
2503 * @return {Number} The size.
2506 return this._q.length;
2512 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2515 The YUI module contains the components required for building the YUI seed file.
2516 This includes the script loading mechanism, a simple queue, and the core
2517 utilities for the library.
2523 var CACHED_DELIMITER = '__',
2525 hasOwn = Object.prototype.hasOwnProperty,
2526 isObject = Y.Lang.isObject;
2529 Returns a wrapper for a function which caches the return value of that function,
2530 keyed off of the combined string representation of the argument values provided
2531 when the wrapper is called.
2533 Calling this function again with the same arguments will return the cached value
2534 rather than executing the wrapped function.
2536 Note that since the cache is keyed off of the string representation of arguments
2537 passed to the wrapper function, arguments that aren't strings and don't provide
2538 a meaningful `toString()` method may result in unexpected caching behavior. For
2539 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2540 string `[object Object]` when used as a cache key.
2543 @param {Function} source The function to memoize.
2544 @param {Object} [cache={}] Object in which to store cached values. You may seed
2545 this object with pre-existing cached values if desired.
2546 @param {any} [refetch] If supplied, this value is compared with the cached value
2547 using a `==` comparison. If the values are equal, the wrapped function is
2548 executed again even though a cached value exists.
2549 @return {Function} Wrapped function.
2552 Y.cached = function (source, cache, refetch) {
2553 /*jshint expr: true*/
2554 cache || (cache = {});
2556 return function (arg) {
2557 var key = arguments.length > 1 ?
2558 Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2561 /*jshint eqeqeq: false*/
2562 if (!(key in cache) || (refetch && cache[key] == refetch)) {
2563 cache[key] = source.apply(source, arguments);
2571 Returns the `location` object from the window/frame in which this YUI instance
2572 operates, or `undefined` when executing in a non-browser environment
2575 It is _not_ recommended to hold references to the `window.location` object
2576 outside of the scope of a function in which its properties are being accessed or
2577 its methods are being called. This is because of a nasty bug/issue that exists
2578 in both Safari and MobileSafari browsers:
2579 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
2582 @return {location} The `location` object from the window/frame in which this YUI
2586 Y.getLocation = function () {
2587 // It is safer to look this up every time because yui-base is attached to a
2588 // YUI instance before a user's config is applied; i.e. `Y.config.win` does
2589 // not point the correct window object when this file is loaded.
2590 var win = Y.config.win;
2592 // It is not safe to hold a reference to the `location` object outside the
2593 // scope in which it is being used. The WebKit engine used in Safari and
2594 // MobileSafari will "disconnect" the `location` object from the `window`
2595 // when a page is restored from back/forward history cache.
2596 return win && win.location;
2600 Returns a new object containing all of the properties of all the supplied
2601 objects. The properties from later objects will overwrite those in earlier
2604 Passing in a single object will create a shallow copy of it. For a deep copy,
2608 @param {Object} objects* One or more objects to merge.
2609 @return {Object} A new merged object.
2611 Y.merge = function () {
2613 len = arguments.length,
2618 for (; i < len; ++i) {
2622 if (hasOwn.call(obj, key)) {
2623 result[key] = obj[key];
2632 Mixes _supplier_'s properties into _receiver_.
2634 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
2635 shadowed unless the _overwrite_ parameter is `true`, and will not be merged
2636 unless the _merge_ parameter is `true`.
2638 In the default mode (0), only properties the supplier owns are copied (prototype
2639 properties are not copied). The following copying modes are available:
2641 * `0`: _Default_. Object to object.
2642 * `1`: Prototype to prototype.
2643 * `2`: Prototype to prototype and object to object.
2644 * `3`: Prototype to object.
2645 * `4`: Object to prototype.
2648 @param {Function|Object} receiver The object or function to receive the mixed
2650 @param {Function|Object} supplier The object or function supplying the
2651 properties to be mixed.
2652 @param {Boolean} [overwrite=false] If `true`, properties that already exist
2653 on the receiver will be overwritten with properties from the supplier.
2654 @param {String[]} [whitelist] An array of property names to copy. If
2655 specified, only the whitelisted properties will be copied, and all others
2657 @param {Number} [mode=0] Mix mode to use. See above for available modes.
2658 @param {Boolean} [merge=false] If `true`, objects and arrays that already
2659 exist on the receiver will have the corresponding object/array from the
2660 supplier merged into them, rather than being skipped or overwritten. When
2661 both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
2662 @return {Function|Object|YUI} The receiver, or the YUI instance if the
2663 specified receiver is falsy.
2665 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
2666 var alwaysOverwrite, exists, from, i, key, len, to;
2668 // If no supplier is given, we return the receiver. If no receiver is given,
2669 // we return Y. Returning Y doesn't make much sense to me, but it's
2670 // grandfathered in for backcompat reasons.
2671 if (!receiver || !supplier) {
2672 return receiver || Y;
2676 // In mode 2 (prototype to prototype and object to object), we recurse
2677 // once to do the proto to proto mix. The object to object mix will be
2678 // handled later on.
2680 Y.mix(receiver.prototype, supplier.prototype, overwrite,
2681 whitelist, 0, merge);
2684 // Depending on which mode is specified, we may be copying from or to
2685 // the prototypes of the supplier and receiver.
2686 from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
2687 to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
2689 // If either the supplier or receiver doesn't actually have a
2690 // prototype property, then we could end up with an undefined `from`
2691 // or `to`. If that happens, we abort and return the receiver.
2700 // If `overwrite` is truthy and `merge` is falsy, then we can skip a
2701 // property existence check on each iteration and save some time.
2702 alwaysOverwrite = overwrite && !merge;
2705 for (i = 0, len = whitelist.length; i < len; ++i) {
2708 // We call `Object.prototype.hasOwnProperty` instead of calling
2709 // `hasOwnProperty` on the object itself, since the object's
2710 // `hasOwnProperty` method may have been overridden or removed.
2711 // Also, some native objects don't implement a `hasOwnProperty`
2713 if (!hasOwn.call(from, key)) {
2717 // The `key in to` check here is (sadly) intentional for backwards
2718 // compatibility reasons. It prevents undesired shadowing of
2719 // prototype members on `to`.
2720 exists = alwaysOverwrite ? false : key in to;
2722 if (merge && exists && isObject(to[key], true)
2723 && isObject(from[key], true)) {
2724 // If we're in merge mode, and the key is present on both
2725 // objects, and the value on both objects is either an object or
2726 // an array (but not a function), then we recurse to merge the
2727 // `from` value into the `to` value instead of overwriting it.
2729 // Note: It's intentional that the whitelist isn't passed to the
2730 // recursive call here. This is legacy behavior that lots of
2731 // code still depends on.
2732 Y.mix(to[key], from[key], overwrite, null, 0, merge);
2733 } else if (overwrite || !exists) {
2734 // We're not in merge mode, so we'll only copy the `from` value
2735 // to the `to` value if we're in overwrite mode or if the
2736 // current key doesn't exist on the `to` object.
2737 to[key] = from[key];
2742 // The code duplication here is for runtime performance reasons.
2743 // Combining whitelist and non-whitelist operations into a single
2744 // loop or breaking the shared logic out into a function both result
2745 // in worse performance, and Y.mix is critical enough that the byte
2746 // tradeoff is worth it.
2747 if (!hasOwn.call(from, key)) {
2751 // The `key in to` check here is (sadly) intentional for backwards
2752 // compatibility reasons. It prevents undesired shadowing of
2753 // prototype members on `to`.
2754 exists = alwaysOverwrite ? false : key in to;
2756 if (merge && exists && isObject(to[key], true)
2757 && isObject(from[key], true)) {
2758 Y.mix(to[key], from[key], overwrite, null, 0, merge);
2759 } else if (overwrite || !exists) {
2760 to[key] = from[key];
2764 // If this is an IE browser with the JScript enumeration bug, force
2765 // enumeration of the buggy properties by making a recursive call with
2766 // the buggy properties as the whitelist.
2767 if (Y.Object._hasEnumBug) {
2768 Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
2775 * The YUI module contains the components required for building the YUI
2776 * seed file. This includes the script loading mechanism, a simple queue,
2777 * and the core utilities for the library.
2779 * @submodule yui-base
2783 * Adds utilities to the YUI instance for working with objects.
2789 hasOwn = Object.prototype.hasOwnProperty,
2791 UNDEFINED, // <-- Note the comma. We're still declaring vars.
2794 * Returns a new object that uses _obj_ as its prototype. This method wraps the
2795 * native ES5 `Object.create()` method if available, but doesn't currently
2796 * pass through `Object.create()`'s second argument (properties) in order to
2797 * ensure compatibility with older browsers.
2800 * @param {Object} obj Prototype object.
2801 * @return {Object} New object using _obj_ as its prototype.
2804 O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
2805 // We currently wrap the native Object.create instead of simply aliasing it
2806 // to ensure consistency with our fallback shim, which currently doesn't
2807 // support Object.create()'s second argument (properties). Once we have a
2808 // safe fallback for the properties arg, we can stop wrapping
2810 return Object.create(obj);
2812 // Reusable constructor function for the Object.create() shim.
2816 return function (obj) {
2823 * Property names that IE doesn't enumerate in for..in loops, even when they
2824 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
2825 * manually enumerate these properties.
2827 * @property _forceEnum
2832 forceEnum = O._forceEnum = [
2835 'propertyIsEnumerable',
2842 * `true` if this browser has the JScript enumeration bug that prevents
2843 * enumeration of the properties named in the `_forceEnum` array, `false`
2847 * - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
2848 * - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
2850 * @property _hasEnumBug
2855 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
2858 * `true` if this browser incorrectly considers the `prototype` property of
2859 * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x.
2861 * @property _hasProtoEnumBug
2866 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
2869 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
2870 * exists only on _obj_'s prototype. This is essentially a safer version of
2871 * `obj.hasOwnProperty()`.
2874 * @param {Object} obj Object to test.
2875 * @param {String} key Property name to look for.
2876 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2879 owns = O.owns = function (obj, key) {
2880 return !!obj && hasOwn.call(obj, key);
2881 }; // <-- End of var declarations.
2884 * Alias for `owns()`.
2887 * @param {Object} obj Object to test.
2888 * @param {String} key Property name to look for.
2889 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2895 * Returns an array containing the object's enumerable keys. Does not include
2896 * prototype keys or non-enumerable keys.
2898 * Note that keys are returned in enumeration order (that is, in the same order
2899 * that they would be enumerated by a `for-in` loop), which may not be the same
2900 * as the order in which they were defined.
2902 * This method is an alias for the native ES5 `Object.keys()` method if
2903 * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of
2904 * `Object.keys()` have an inconsistency as they consider `prototype` to be
2905 * enumerable, so a non-native shim is used to rectify the difference.
2909 * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
2910 * // => ['a', 'b', 'c']
2913 * @param {Object} obj An object.
2914 * @return {String[]} Array of keys.
2917 O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) {
2918 if (!Lang.isObject(obj)) {
2919 throw new TypeError('Object.keys called on a non-object');
2925 if (hasProtoEnumBug && typeof obj === 'function') {
2927 if (owns(obj, key) && key !== 'prototype') {
2933 if (owns(obj, key)) {
2940 for (i = 0, len = forceEnum.length; i < len; ++i) {
2943 if (owns(obj, key)) {
2953 * Returns an array containing the values of the object's enumerable keys.
2955 * Note that values are returned in enumeration order (that is, in the same
2956 * order that they would be enumerated by a `for-in` loop), which may not be the
2957 * same as the order in which they were defined.
2961 * Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
2962 * // => ['foo', 'bar', 'baz']
2965 * @param {Object} obj An object.
2966 * @return {Array} Array of values.
2969 O.values = function (obj) {
2970 var keys = O.keys(obj),
2975 for (; i < len; ++i) {
2976 values.push(obj[keys[i]]);
2983 * Returns the number of enumerable keys owned by an object.
2986 * @param {Object} obj An object.
2987 * @return {Number} The object's size.
2990 O.size = function (obj) {
2992 return O.keys(obj).length;
2994 return 0; // Legacy behavior for non-objects.
2999 * Returns `true` if the object owns an enumerable property with the specified
3003 * @param {Object} obj An object.
3004 * @param {any} value The value to search for.
3005 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3008 O.hasValue = function (obj, value) {
3009 return Y.Array.indexOf(O.values(obj), value) > -1;
3013 * Executes a function on each enumerable property in _obj_. The function
3014 * receives the value, the key, and the object itself as parameters (in that
3017 * By default, only properties owned by _obj_ are enumerated. To include
3018 * prototype properties, set the _proto_ parameter to `true`.
3021 * @param {Object} obj Object to enumerate.
3022 * @param {Function} fn Function to execute on each enumerable property.
3023 * @param {mixed} fn.value Value of the current property.
3024 * @param {String} fn.key Key of the current property.
3025 * @param {Object} fn.obj Object being enumerated.
3026 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3027 * @param {Boolean} [proto=false] Include prototype properties.
3028 * @return {YUI} the YUI instance.
3032 O.each = function (obj, fn, thisObj, proto) {
3036 if (proto || owns(obj, key)) {
3037 fn.call(thisObj || Y, obj[key], key, obj);
3045 * Executes a function on each enumerable property in _obj_, but halts if the
3046 * function returns a truthy value. The function receives the value, the key,
3047 * and the object itself as paramters (in that order).
3049 * By default, only properties owned by _obj_ are enumerated. To include
3050 * prototype properties, set the _proto_ parameter to `true`.
3053 * @param {Object} obj Object to enumerate.
3054 * @param {Function} fn Function to execute on each enumerable property.
3055 * @param {mixed} fn.value Value of the current property.
3056 * @param {String} fn.key Key of the current property.
3057 * @param {Object} fn.obj Object being enumerated.
3058 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3059 * @param {Boolean} [proto=false] Include prototype properties.
3060 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3061 * `false` otherwise.
3064 O.some = function (obj, fn, thisObj, proto) {
3068 if (proto || owns(obj, key)) {
3069 if (fn.call(thisObj || Y, obj[key], key, obj)) {
3079 * Retrieves the sub value at the provided path,
3080 * from the value object provided.
3084 * @param o The object from which to extract the property value.
3085 * @param path {Array} A path array, specifying the object traversal path
3086 * from which to obtain the sub value.
3087 * @return {Any} The value stored in the path, undefined if not found,
3088 * undefined if the source is not an object. Returns the source object
3089 * if an empty path is provided.
3091 O.getValue = function(o, path) {
3092 if (!Lang.isObject(o)) {
3100 for (i = 0; o !== UNDEFINED && i < l; i++) {
3108 * Sets the sub-attribute value at the provided path on the
3109 * value object. Returns the modified value object, or
3110 * undefined if the path is invalid.
3114 * @param o The object on which to set the sub value.
3115 * @param path {Array} A path array, specifying the object traversal path
3116 * at which to set the sub value.
3117 * @param val {Any} The new value for the sub-attribute.
3118 * @return {Object} The modified object, with the new sub value set, or
3119 * undefined, if the path was invalid.
3121 O.setValue = function(o, path, val) {
3124 leafIdx = p.length - 1,
3128 for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3132 if (ref !== UNDEFINED) {
3143 * Returns `true` if the object has no enumerable properties of its own.
3146 * @param {Object} obj An object.
3147 * @return {Boolean} `true` if the object is empty.
3151 O.isEmpty = function (obj) {
3152 return !O.keys(Object(obj)).length;
3155 * The YUI module contains the components required for building the YUI seed
3156 * file. This includes the script loading mechanism, a simple queue, and the
3157 * core utilities for the library.
3159 * @submodule yui-base
3163 * YUI user agent detection.
3164 * Do not fork for a browser if it can be avoided. Use feature detection when
3165 * you can. Use the user agent as a last resort. For all fields listed
3166 * as @type float, UA stores a version number for the browser engine,
3167 * 0 otherwise. This value may or may not map to the version number of
3168 * the browser using the engine. The value is presented as a float so
3169 * that it can easily be used for boolean evaluation as well as for
3170 * looking for a particular range of versions. Because of this,
3171 * some of the granularity of the version info may be lost. The fields that
3172 * are @type string default to null. The API docs list the values that
3173 * these fields can have.
3179 * Static method on `YUI.Env` for parsing a UA string. Called at instantiation
3180 * to populate `Y.UA`.
3184 * @param {String} [subUA=navigator.userAgent] UA string to parse
3185 * @return {Object} The Y.UA object
3187 YUI.Env.parseUA = function(subUA) {
3189 var numberify = function(s) {
3191 return parseFloat(s.replace(/\./g, function() {
3192 return (c++ === 1) ? '' : '.';
3198 nav = win && win.navigator,
3203 * Internet Explorer version number or 0. Example: 6
3211 * Opera version number or 0. Example: 9.2
3219 * Gecko engine revision number. Will evaluate to 1 if Gecko
3220 * is detected but the revision could not be found. Other browsers
3221 * will be 0. Example: 1.8
3223 * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
3224 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3225 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3226 * Firefox 3.0 <-- 1.9
3227 * Firefox 3.5 <-- 1.91
3236 * AppleWebKit version. KHTML browsers that are not WebKit browsers
3237 * will evaluate to 1, other browsers 0. Example: 418.9
3239 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3240 * latest available for Mac OSX 10.3.
3241 * Safari 2.0.2: 416 <-- hasOwnProperty introduced
3242 * Safari 2.0.4: 418 <-- preventDefault fixed
3243 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3244 * different versions of webkit
3245 * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
3246 * updated, but not updated
3247 * to the latest patch.
3248 * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native
3249 * SVG and many major issues fixed).
3250 * Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic
3251 * update from 2.x via the 10.4.11 OS patch.
3252 * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
3253 * yahoo.com user agent hack removed.
3255 * http://en.wikipedia.org/wiki/Safari_version_history
3263 * Safari will be detected as webkit, but this property will also
3264 * be populated with the Safari version number
3272 * Chrome will be detected as webkit, but this property will also
3273 * be populated with the Chrome version number
3281 * The mobile property will be set to a string containing any relevant
3282 * user agent information when a modern mobile browser is detected.
3283 * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3284 * devices with the WebKit-based browser, and Opera Mini.
3293 * Adobe AIR version number or 0. Only populated if webkit is detected.
3300 * PhantomJS version number or 0. Only populated if webkit is detected.
3302 * @property phantomjs
3307 * Detects Apple iPad's OS version
3314 * Detects Apple iPhone's OS version
3321 * Detects Apples iPod's OS version
3328 * General truthy check for iPad, iPhone or iPod
3336 * Detects Googles Android OS version
3343 * Detects Kindle Silk
3350 * Detects Kindle Silk Acceleration
3357 * Detects Palms WebOS version
3365 * Google Caja version number or 0.
3369 caja: nav && nav.cajaVersion,
3372 * Set to true if the page appears to be in SSL
3380 * The operating system. Currently only detecting windows or macintosh
3389 * The Nodejs Version
3397 * Window8/IE10 Application host environment
3402 winjs: !!((typeof Windows !== "undefined") && Windows.System),
3404 * Are touch/msPointer events available on this device
3405 * @property touchEnabled
3412 ua = subUA || nav && nav.userAgent,
3414 loc = win && win.location,
3416 href = loc && loc.href,
3421 * The User Agent string that was parsed
3422 * @property userAgent
3429 o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3433 if ((/windows|win32/i).test(ua)) {
3435 } else if ((/macintosh|mac_powerpc/i).test(ua)) {
3437 } else if ((/android/i).test(ua)) {
3439 } else if ((/symbos/i).test(ua)) {
3441 } else if ((/linux/i).test(ua)) {
3443 } else if ((/rhino/i).test(ua)) {
3447 // Modern KHTML browsers should qualify as Safari X-Grade
3448 if ((/KHTML/).test(ua)) {
3451 if ((/IEMobile|XBLWP7/).test(ua)) {
3452 o.mobile = 'windows';
3454 if ((/Fennec/).test(ua)) {
3457 // Modern WebKit browsers are at least X-Grade
3458 m = ua.match(/AppleWebKit\/([^\s]*)/);
3460 o.webkit = numberify(m[1]);
3461 o.safari = o.webkit;
3463 if (/PhantomJS/.test(ua)) {
3464 m = ua.match(/PhantomJS\/([^\s]*)/);
3466 o.phantomjs = numberify(m[1]);
3470 // Mobile browser check
3471 if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
3472 o.mobile = 'Apple'; // iPhone or iPod Touch
3474 m = ua.match(/OS ([^\s]*)/);
3476 m = numberify(m[1].replace('_', '.'));
3480 o.ipad = o.ipod = o.iphone = 0;
3482 m = ua.match(/iPad|iPod|iPhone/);
3484 o[m[0].toLowerCase()] = o.ios;
3487 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3489 // Nokia N-series, webOS, ex: NokiaN95
3492 if (/webOS/.test(ua)) {
3494 m = ua.match(/webOS\/([^\s]*);/);
3496 o.webos = numberify(m[1]);
3499 if (/ Android/.test(ua)) {
3500 if (/Mobile/.test(ua)) {
3501 o.mobile = 'Android';
3503 m = ua.match(/Android ([^\s]*);/);
3505 o.android = numberify(m[1]);
3509 if (/Silk/.test(ua)) {
3510 m = ua.match(/Silk\/([^\s]*)\)/);
3512 o.silk = numberify(m[1]);
3515 o.android = 2.34; //Hack for desktop mode in Kindle
3518 if (/Accelerated=true/.test(ua)) {
3524 m = ua.match(/OPR\/(\d+\.\d+)/);
3527 // Opera 15+ with Blink (pretends to be both Chrome and Safari)
3528 o.opera = numberify(m[1]);
3530 m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
3532 if (m && m[1] && m[2]) {
3533 o.chrome = numberify(m[2]); // Chrome
3534 o.safari = 0; //Reset safari back to 0
3535 if (m[1] === 'CrMo') {
3536 o.mobile = 'chrome';
3539 m = ua.match(/AdobeAIR\/([^\s]*)/);
3541 o.air = m[0]; // Adobe AIR 1.0 or better
3547 if (!o.webkit) { // not webkit
3548 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3549 if (/Opera/.test(ua)) {
3550 m = ua.match(/Opera[\s\/]([^\s]*)/);
3552 o.opera = numberify(m[1]);
3554 m = ua.match(/Version\/([^\s]*)/);
3556 o.opera = numberify(m[1]); // opera 10+
3559 if (/Opera Mobi/.test(ua)) {
3561 m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
3563 o.opera = numberify(m[1]);
3566 m = ua.match(/Opera Mini[^;]*/);
3569 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3571 } else { // not opera or webkit
3572 m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/);
3574 if (m && (m[1] || m[2])) {
3575 o.ie = numberify(m[1] || m[2]);
3576 } else { // not opera, webkit, or ie
3577 m = ua.match(/Gecko\/([^\s]*)/);
3580 o.gecko = 1; // Gecko detected, look for revision
3581 m = ua.match(/rv:([^\s\)]*)/);
3583 o.gecko = numberify(m[1]);
3584 if (/Mobile|Tablet/.test(ua)) {
3594 //Check for known properties to tell if touch events are enabled on this device or if
3595 //the number of MSPointer touchpoints on this device is greater than 0.
3596 if (win && nav && !(o.chrome && o.chrome < 6)) {
3597 o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
3600 //It was a parsed UA, do not assign the global value.
3603 if (typeof process === 'object') {
3605 if (process.versions && process.versions.node) {
3607 o.os = process.platform;
3608 o.nodejs = numberify(process.versions.node);
3620 Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3623 Performs a simple comparison between two version numbers, accounting for
3624 standard versioning logic such as the fact that "535.8" is a lower version than
3625 "535.24", even though a simple numerical comparison would indicate that it's
3626 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
3627 considered equivalent.
3629 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
3630 1 if _a_ is higher than _b_.
3632 Versions may be numbers or strings containing numbers and dots. For example,
3633 both `535` and `"535.8.10"` are acceptable. A version string containing
3634 non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
3636 @method compareVersions
3637 @param {Number|String} a First version number to compare.
3638 @param {Number|String} b Second version number to compare.
3639 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
3642 Y.UA.compareVersions = function (a, b) {
3643 var aPart, aParts, bPart, bParts, i, len;
3649 aParts = (a + '').split('.');
3650 bParts = (b + '').split('.');
3652 for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
3653 aPart = parseInt(aParts[i], 10);
3654 bPart = parseInt(bParts[i], 10);
3656 /*jshint expr: true*/
3657 isNaN(aPart) && (aPart = 0);
3658 isNaN(bPart) && (bPart = 0);
3660 if (aPart < bPart) {
3664 if (aPart > bPart) {
3672 "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
3673 "anim-shape-transform": ["anim-shape"],
3674 "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"],
3675 "attribute": ["attribute-base","attribute-complex"],
3676 "attribute-events": ["attribute-observable"],
3677 "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
3678 "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
3679 "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
3680 "base": ["base-base","base-pluginhost","base-build"],
3681 "cache": ["cache-base","cache-offline","cache-plugin"],
3682 "charts": ["charts-base"],
3683 "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
3684 "color": ["color-base","color-hsl","color-harmony"],
3685 "controller": ["router"],
3686 "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
3687 "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
3688 "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
3689 "datatype": ["datatype-date","datatype-number","datatype-xml"],
3690 "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
3691 "datatype-number": ["datatype-number-parse","datatype-number-format"],
3692 "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
3693 "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
3694 "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
3695 "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
3696 "event": ["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],
3697 "event-custom": ["event-custom-base","event-custom-complex"],
3698 "event-gestures": ["event-flick","event-move"],
3699 "handlebars": ["handlebars-compiler"],
3700 "highlight": ["highlight-base","highlight-accentfold"],
3701 "history": ["history-base","history-hash","history-hash-ie","history-html5"],
3702 "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
3703 "json": ["json-parse","json-stringify"],
3704 "loader": ["loader-base","loader-rollup","loader-yui3"],
3705 "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
3706 "pluginhost": ["pluginhost-base","pluginhost-config"],
3707 "querystring": ["querystring-parse","querystring-stringify"],
3708 "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
3709 "resize": ["resize-base","resize-proxy","resize-constrain"],
3710 "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
3711 "template": ["template-base","template-micro"],
3712 "text": ["text-accentfold","text-wordbreak"],
3713 "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]