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']);
535 // Y.log(Y.id + ' initialized', 'info', 'yui');
539 Executes the named method on the specified YUI instance if that method is
543 @param {String} id YUI instance id.
544 @param {String} method Name of the method to execute. For example:
546 @param {Array} args Arguments to apply to the method.
547 @return {Mixed} Return value from the applied method, or `null` if the
548 specified instance was not found or the method was not whitelisted.
550 applyTo: function(id, method, args) {
551 if (!(method in APPLY_TO_AUTH)) {
552 this.log(method + ': applyTo not allowed', 'warn', 'yui');
556 var instance = instances[id], nest, m, i;
558 nest = method.split('.');
560 for (i = 0; i < nest.length; i = i + 1) {
563 this.log('applyTo not found: ' + method, 'warn', 'yui');
566 return m && m.apply(instance, args);
573 Registers a YUI module and makes it available for use in a `YUI().use()` call or
574 as a dependency for other modules.
576 The easiest way to create a first-class YUI module is to use
577 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
580 Shifter will automatically wrap your module code in a `YUI.add()` call along
581 with any configuration info required for the module.
585 YUI.add('davglass', function (Y) {
586 Y.davglass = function () {
587 Y.log('Dav was here!');
590 requires: ['harley-davidson', 'mt-dew']
594 @param {String} name Module name.
595 @param {Function} fn Function containing module code. This function will be
596 executed whenever the module is attached to a specific YUI instance.
598 @param {YUI} fn.Y The YUI instance to which this module is attached.
599 @param {String} fn.name Name of the module
601 @param {String} version Module version number. This is currently used only for
602 informational purposes, and is not used internally by YUI.
604 @param {Object} [config] Module config.
605 @param {Array} [config.requires] Array of other module names that must be
606 attached before this module can be attached.
607 @param {Array} [config.optional] Array of optional module names that should
608 be attached before this module is attached if they've already been
609 loaded. If the `loadOptional` YUI option is `true`, optional modules
610 that have not yet been loaded will be loaded just as if they were hard
612 @param {Array} [config.use] Array of module names that are included within
613 or otherwise provided by this module, and which should be attached
614 automatically when this module is attached. This makes it possible to
615 create "virtual rollup" modules that simply attach a collection of other
616 modules or submodules.
618 @return {YUI} This YUI instance.
620 add: function(name, fn, version, details) {
621 details = details || {};
629 //Instance hash so we don't apply it to the same instance twice
632 i, versions = env.versions;
634 env.mods[name] = mod;
635 versions[version] = versions[version] || {};
636 versions[version][name] = mod;
638 for (i in instances) {
639 if (instances.hasOwnProperty(i)) {
641 if (!applied[inst.id]) {
642 applied[inst.id] = true;
643 loader = inst.Env._loader;
645 if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
646 loader.addModule(details, name);
657 Executes the callback function associated with each required module,
658 attaching the module to this YUI instance.
661 @param {Array} r The array of modules to attach
662 @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
666 _attach: function(r, moot) {
667 var i, name, mod, details, req, use, after,
669 aliases = YUI.Env.aliases,
671 cache = YUI.Env._renderedMods,
672 loader = Y.Env._loader,
673 done = Y.Env._attached,
674 len = r.length, loader, def, go,
677 //Check for conditional modules (in a second+ instance) and add their requirements
678 //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
679 for (i = 0; i < len; i++) {
683 if (loader && loader.conditions[name]) {
684 for (j in loader.conditions[name]) {
685 if (loader.conditions[name].hasOwnProperty(j)) {
686 def = loader.conditions[name][j];
687 go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
698 for (i = 0; i < len; i++) {
703 if (aliases && aliases[name] && !mod) {
704 Y._attach(aliases[name]);
708 if (loader && loader.moduleInfo[name]) {
709 mod = loader.moduleInfo[name];
713 // Y.log('no js def for: ' + name, 'info', 'yui');
715 //if (!loader || !loader.moduleInfo[name]) {
716 //if ((!loader || !loader.moduleInfo[name]) && !moot) {
718 if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
719 Y.Env._missed.push(name);
720 Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
721 Y.message('NOT loaded: ' + name, 'warn', 'yui');
726 //Don't like this, but in case a mod was asked for once, then we fetch it
727 //We need to remove it from the missed list ^davglass
728 for (j = 0; j < Y.Env._missed.length; j++) {
729 if (Y.Env._missed[j] === name) {
730 Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
731 Y.Env._missed.splice(j, 1);
735 If it's a temp module, we need to redo it's requirements if it's already loaded
736 since it may have been loaded by another instance and it's dependencies might
737 have been redefined inside the fetched file.
739 if (loader && cache && cache[name] && cache[name].temp) {
740 loader.getRequires(cache[name]);
742 for (j in loader.moduleInfo[name].expanded_map) {
743 if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
750 details = mod.details;
751 req = details.requires;
753 after = details.after;
754 //Force Intl load if there is a language (Loader logic) @todo fix this shit
761 for (j = 0; j < req.length; j++) {
763 if (!Y._attach(req)) {
772 for (j = 0; j < after.length; j++) {
773 if (!done[after[j]]) {
774 if (!Y._attach(after, true)) {
783 if (Y.config.throwFail) {
789 Y.error('Attach error: ' + name, e, name);
796 for (j = 0; j < use.length; j++) {
798 if (!Y._attach(use)) {
816 Delays the `use` callback until another event has taken place such as
817 `window.onload`, `domready`, `contentready`, or `available`.
820 @method _delayCallback
821 @param {Function} cb The original `use` callback.
822 @param {String|Object} until Either an event name ('load', 'domready', etc.)
823 or an object containing event/args keys for contentready/available.
826 _delayCallback: function(cb, until) {
829 mod = ['event-base'];
831 until = (Y.Lang.isObject(until) ? until : { event: until });
833 if (until.event === 'load') {
834 mod.push('event-synthetic');
837 Y.log('Delaying use callback until: ' + until.event, 'info', 'yui');
839 Y.log('Use callback fired, waiting on delay', 'info', 'yui');
840 var args = arguments;
841 Y._use(mod, function() {
842 Y.log('Delayed use wrapper callback after dependencies', 'info', 'yui');
843 Y.on(until.event, function() {
844 args[1].delayUntil = until.event;
845 Y.log('Delayed use callback done after ' + until.event, 'info', 'yui');
853 Attaches one or more modules to this YUI instance. When this is executed,
854 the requirements of the desired modules are analyzed, and one of several
858 * All required modules have already been loaded, and just need to be
859 attached to this YUI instance. In this case, the `use()` callback will
860 be executed synchronously after the modules are attached.
862 * One or more modules have not yet been loaded, or the Get utility is not
863 available, or the `bootstrap` config option is `false`. In this case,
864 a warning is issued indicating that modules are missing, but all
865 available modules will still be attached and the `use()` callback will
866 be executed synchronously.
868 * One or more modules are missing and the Loader is not available but the
869 Get utility is, and `bootstrap` is not `false`. In this case, the Get
870 utility will be used to load the Loader, and we will then proceed to
873 * One or more modules are missing and the Loader is available. In this
874 case, the Loader will be used to resolve the dependency tree for the
875 missing modules and load them and their dependencies. When the Loader is
876 finished loading modules, the `use()` callback will be executed
881 // Loads and attaches dd and its dependencies.
882 YUI().use('dd', function (Y) {
886 // Loads and attaches dd and node as well as all of their dependencies.
887 YUI().use(['dd', 'node'], function (Y) {
891 // Attaches all modules that have already been loaded.
892 YUI().use('*', function (Y) {
896 // Attaches a gallery module.
897 YUI().use('gallery-yql', function (Y) {
901 // Attaches a YUI 2in3 module.
902 YUI().use('yui2-datatable', function (Y) {
907 @param {String|Array} modules* One or more module names to attach.
908 @param {Function} [callback] Callback function to be executed once all
909 specified modules and their dependencies have been attached.
910 @param {YUI} callback.Y The YUI instance created for this sandbox.
911 @param {Object} callback.status Object containing `success`, `msg` and
916 var args = SLICE.call(arguments, 0),
917 callback = args[args.length - 1],
924 // The last argument supplied to use can be a load complete callback
925 if (Y.Lang.isFunction(callback)) {
927 if (Y.config.delayUntil) {
928 callback = Y._delayCallback(callback, Y.config.delayUntil);
933 if (Y.Lang.isArray(args[0])) {
937 if (Y.config.cacheUse) {
938 while ((name = args[i++])) {
939 if (!Env._attached[name]) {
947 Y.log('already provisioned: ' + args, 'info', 'yui');
949 Y._notify(callback, ALREADY_DONE, args);
955 Y._useQueue = Y._useQueue || new Y.Queue();
956 Y._useQueue.add([args, callback]);
958 Y._use(args, function(Y, response) {
959 Y._notify(callback, response, args);
967 Handles Loader notifications about attachment/load errors.
970 @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
971 @param {Object} response Response returned from Loader.
972 @param {Array} args Arguments passed from Loader.
975 _notify: function(callback, response, args) {
976 if (!response.success && this.config.loadErrorFn) {
977 this.config.loadErrorFn.call(this, this, callback, response, args);
978 } else if (callback) {
979 if (this.Env._missed && this.Env._missed.length) {
980 response.msg = 'Missing modules: ' + this.Env._missed.join();
981 response.success = false;
983 if (this.config.throwFail) {
984 callback(this, response);
987 callback(this, response);
989 this.error('use callback error', e, args);
996 Called from the `use` method queue to ensure that only one set of loading
997 logic is performed at a time.
1000 @param {String} args* One or more modules to attach.
1001 @param {Function} [callback] Function to call once all required modules have
1005 _use: function(args, callback) {
1008 this._attach(['yui-base']);
1011 var len, loader, handleBoot,
1017 aliases = G_ENV.aliases,
1018 queue = G_ENV._loaderQueue,
1022 boot = config.bootstrap,
1027 fetchCSS = config.fetchCSS,
1028 process = function(names, skip) {
1030 var i = 0, a = [], name, len, m, req, use;
1032 if (!names.length) {
1038 for (i = 0; i < len; i++) {
1039 if (aliases[names[i]] && !mods[names[i]]) {
1040 a = [].concat(a, aliases[names[i]]);
1050 for (i = 0; i < len; i++) {
1056 // only attach a module once
1067 req = m.details.requires;
1068 use = m.details.use;
1070 // CSS files don't register themselves, see if it has
1072 if (!G_ENV._loaded[VERSION][name]) {
1075 used[name] = true; // probably css
1079 // make sure requirements are attached
1080 if (req && req.length) {
1084 // make sure we grab the submodule dependencies too
1085 if (use && use.length) {
1092 handleLoader = function(fromLoader) {
1093 var response = fromLoader || {
1099 data = response.data;
1104 origMissing = missing;
1108 redo = missing.length;
1110 if ([].concat(missing).sort().join() ==
1111 origMissing.sort().join()) {
1119 Y._use(missing, function() {
1120 Y.log('Nested use callback: ' + data, 'info', 'yui');
1121 if (Y._attach(data)) {
1122 Y._notify(callback, response, data);
1127 // Y.log('attaching from loader: ' + data, 'info', 'yui');
1128 ret = Y._attach(data);
1131 Y._notify(callback, response, args);
1135 if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
1136 Y._use.apply(Y, Y._useQueue.next());
1141 // Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');
1143 // YUI().use('*'); // bind everything available
1144 if (firstArg === '*') {
1147 if (mods.hasOwnProperty(i)) {
1151 ret = Y._attach(args);
1158 if ((mods.loader || mods['loader-base']) && !Y.Loader) {
1159 Y.log('Loader was found in meta, but it is not attached. Attaching..', 'info', 'yui');
1160 Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
1163 // Y.log('before loader requirements: ' + args, 'info', 'yui');
1165 // use loader to expand dependencies and sort the
1166 // requirements if it is available.
1167 if (boot && Y.Loader && args.length) {
1168 Y.log('Using loader to expand dependencies', 'info', 'yui');
1169 loader = getLoader(Y);
1170 loader.require(args);
1171 loader.ignoreRegistered = true;
1172 loader._boot = true;
1173 loader.calculate(null, (fetchCSS) ? null : 'js');
1174 args = loader.sorted;
1175 loader._boot = false;
1180 len = missing.length;
1184 missing = YArray.dedupe(missing);
1185 len = missing.length;
1186 Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
1191 if (boot && len && Y.Loader) {
1192 // Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
1193 Y.log('Using Loader', 'info', 'yui');
1195 loader = getLoader(Y);
1196 loader.onEnd = handleLoader;
1199 loader.ignoreRegistered = false;
1200 loader.require(missing);
1201 loader.insert(null, (fetchCSS) ? null : 'js');
1203 } else if (boot && len && Y.Get && !Env.bootstrapped) {
1207 handleBoot = function() {
1209 queue.running = false;
1210 Env.bootstrapped = true;
1211 G_ENV._bootstrapping = false;
1212 if (Y._attach(['loader'])) {
1213 Y._use(args, callback);
1217 if (G_ENV._bootstrapping) {
1218 Y.log('Waiting for loader', 'info', 'yui');
1219 queue.add(handleBoot);
1221 G_ENV._bootstrapping = true;
1222 Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
1223 Y.Get.script(config.base + config.loaderPath, {
1229 Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
1230 ret = Y._attach(args);
1241 Utility method for safely creating namespaces if they don't already exist.
1242 May be called statically on the YUI global object or as a method on a YUI
1245 When called statically, a namespace will be created on the YUI global
1248 // Create `YUI.your.namespace.here` as nested objects, preserving any
1249 // objects that already exist instead of overwriting them.
1250 YUI.namespace('your.namespace.here');
1252 When called as a method on a YUI instance, a namespace will be created on
1255 // Creates `Y.property.package`.
1256 Y.namespace('property.package');
1258 Dots in the input string cause `namespace` to create nested objects for each
1259 token. If any part of the requested namespace already exists, the current
1260 object will be left in place and will not be overwritten. This allows
1261 multiple calls to `namespace` to preserve existing namespaced properties.
1263 If the first token in the namespace string is "YAHOO", that token is
1264 discarded. This is legacy behavior for backwards compatibility with YUI 2.
1266 Be careful with namespace tokens. Reserved words may work in some browsers
1267 and not others. For instance, the following will fail in some browsers
1268 because the supported version of JavaScript reserves the word "long":
1270 Y.namespace('really.long.nested.namespace');
1272 Note: If you pass multiple arguments to create multiple namespaces, only the
1273 last one created is returned from this function.
1276 @param {String} namespace* One or more namespaces to create.
1277 @return {Object} Reference to the last namespace object created.
1279 namespace: function() {
1280 var a = arguments, o, i = 0, j, d, arg;
1282 for (; i < a.length; i++) {
1283 o = this; //Reset base object per argument or it will get reused from the last
1285 if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1286 d = arg.split(PERIOD);
1287 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1288 o[d[j]] = o[d[j]] || {};
1292 o[arg] = o[arg] || {};
1293 o = o[arg]; //Reset base object to the new object so it's returned
1299 // this is replaced if the log module is included
1302 // this is replaced if the dump module is included
1303 dump: function (o) { return ''+o; },
1308 The reporting mechanism is controlled by the `throwFail` configuration
1309 attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
1310 truthy, a JS exception is thrown.
1312 If an `errorFn` is specified in the config it must return `true` to indicate
1313 that the exception was handled and keep it from being thrown.
1316 @param {String} msg Error message.
1317 @param {Error|String} [e] JavaScript error object or an error string.
1318 @param {String} [src] Source of the error (such as the name of the module in
1319 which the error occurred).
1322 error: function(msg, e, src) {
1323 //TODO Add check for window.onerror here
1327 if (Y.config.errorFn) {
1328 ret = Y.config.errorFn.apply(Y, arguments);
1332 throw (e || new Error(msg));
1334 Y.message(msg, 'error', ''+src); // don't scrub this one
1341 Generates an id string that is unique among all YUI instances in this
1345 @param {String} [pre] Prefix.
1346 @return {String} Unique id.
1348 guid: function(pre) {
1349 var id = this.Env._guidp + '_' + (++this.Env._uidx);
1350 return (pre) ? (pre + id) : id;
1354 Returns a unique id associated with the given object and (if *readOnly* is
1355 falsy) stamps the object with that id so it can be identified in the future.
1357 Stamping an object involves adding a `_yuid` property to it that contains
1358 the object's id. One exception to this is that in Internet Explorer, DOM
1359 nodes have a `uniqueID` property that contains a browser-generated unique
1360 id, which will be used instead of a YUI-generated id when available.
1363 @param {Object} o Object to stamp.
1364 @param {Boolean} readOnly If truthy and the given object has not already
1365 been stamped, the object will not be modified and `null` will be
1367 @return {String} Object's unique id, or `null` if *readOnly* was truthy and
1368 the given object was not already stamped.
1370 stamp: function(o, readOnly) {
1376 // IE generates its own unique ID for dom nodes
1377 // The uniqueID property of a document node returns a new ID
1378 if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1381 uid = (typeof o === 'string') ? o : o._yuid;
1398 Destroys this YUI instance.
1403 destroy: function() {
1408 delete instances[Y.id];
1414 Safe `instanceof` wrapper that works around a memory leak in IE when the
1415 object being tested is `window` or `document`.
1417 Unless you are testing objects that may be `window` or `document`, you
1418 should use the native `instanceof` operator instead of this method.
1421 @param {Object} o Object to check.
1422 @param {Object} type Class to check against.
1427 YUI.prototype = proto;
1429 // inheritance utilities are not available yet
1430 for (prop in proto) {
1431 if (proto.hasOwnProperty(prop)) {
1432 YUI[prop] = proto[prop];
1437 Applies a configuration to all YUI instances in this execution context.
1439 The main use case for this method is in "mashups" where several third-party
1440 scripts need to write to a global YUI config, but cannot share a single
1441 centrally-managed config object. This way they can all call
1442 `YUI.applyConfig({})` instead of overwriting the single global config.
1449 fullpath: './davglass.js'
1457 fullpath: './foo.js'
1462 YUI().use('davglass', function (Y) {
1463 // Module davglass will be available here.
1467 @param {Object} o Configuration object to apply.
1471 YUI.applyConfig = function(o) {
1475 //If there is a GlobalConfig, apply it first to set the defaults
1476 if (YUI.GlobalConfig) {
1477 this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1479 //Apply this config to it
1480 this.prototype.applyConfig.call(this, o);
1481 //Reset GlobalConfig to the combined config
1482 YUI.GlobalConfig = this.config;
1485 // set up the environment
1489 // add a window load event at load time so we can capture
1490 // the case where it fires before dynamic loading is
1492 add(window, 'load', handleLoad);
1498 YUI.Env.remove = remove;
1501 // Support the CommonJS method for exporting our single global
1502 if (typeof exports == 'object') {
1505 * Set a method to be called when `Get.script` is called in Node.js
1506 * `Get` will open the file, then pass it's content and it's path
1507 * to this method before attaching it. Commonly used for code coverage
1508 * instrumentation. <strong>Calling this multiple times will only
1509 * attach the last hook method</strong>. This method is only
1510 * available in Node.js.
1511 * @method setLoadHook
1513 * @param {Function} fn The function to set
1514 * @param {String} fn.data The content of the file
1515 * @param {String} fn.path The file path of the file
1517 YUI.setLoadHook = function(fn) {
1518 YUI._getLoadHook = fn;
1521 * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
1522 * @method _getLoadHook
1524 * @param {String} data The content of the file
1525 * @param {String} path The file path of the file
1527 YUI._getLoadHook = null;
1530 YUI.Env[VERSION] = {};
1535 Config object that contains all of the configuration options for
1536 this `YUI` instance.
1538 This object is supplied by the implementer when instantiating YUI. Some
1539 properties have default values if they are not supplied by the implementer.
1541 This object should not be updated directly because some values are cached. Use
1542 `applyConfig()` to update the config object on a YUI instance that has already
1550 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
1551 if they're needed to load additional dependencies and aren't already available.
1553 Setting this to `false` will prevent YUI from automatically loading the Loader
1554 and module metadata, so you will need to manually ensure that they're available
1555 or handle dependency resolution yourself.
1557 @property {Boolean} bootstrap
1562 If `true`, `Y.log()` messages will be written to the browser's debug console
1563 when available and when `useBrowserConsole` is also `true`.
1565 @property {Boolean} debug
1570 Log messages to the browser console if `debug` is `true` and the browser has a
1573 @property {Boolean} useBrowserConsole
1578 A hash of log sources that should be logged. If specified, only messages from
1579 these sources will be logged. Others will be discarded.
1581 @property {Object} logInclude
1586 A hash of log sources that should be not be logged. If specified, all sources
1587 will be logged *except* those on this list.
1589 @property {Object} logExclude
1593 When the YUI seed file is dynamically loaded after the `window.onload` event has
1594 fired, set this to `true` to tell YUI that it shouldn't wait for `window.onload`
1597 This ensures that components that rely on `window.onload` and the `domready`
1598 custom event will work as expected even when YUI is dynamically injected.
1600 @property {Boolean} injected
1605 If `true`, `Y.error()` will generate or re-throw a JavaScript error. Otherwise,
1606 errors are merely logged silently.
1608 @property {Boolean} throwFail
1613 Reference to the global object for this execution context.
1615 In a browser, this is the current `window` object. In Node.js, this is the
1616 Node.js `global` object.
1618 @property {Object} global
1622 The browser window or frame that this YUI instance should operate in.
1624 When running in Node.js, this property is `undefined`, since there is no
1625 `window` object. Use `global` to get a reference to the global object that will
1626 work in both browsers and Node.js.
1628 @property {Window} win
1632 The browser `document` object associated with this YUI instance's `win` object.
1634 When running in Node.js, this property is `undefined`, since there is no
1637 @property {Document} doc
1641 A list of modules that defines the YUI core (overrides the default list).
1643 @property {Array} core
1645 @default ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3']
1649 A list of languages to use in order of preference.
1651 This list is matched against the list of available languages in modules that the
1652 YUI instance uses to determine the best possible localization of language
1655 Languages are represented using BCP 47 language tags, such as "en-GB" for
1656 English as used in the United Kingdom, or "zh-Hans-CN" for simplified Chinese as
1657 used in China. The list may be provided as a comma-separated string or as an
1660 @property {String|String[]} lang
1664 Default date format.
1666 @property {String} dateFormat
1667 @deprecated Use configuration in `DataType.Date.format()` instead.
1673 @property {String} locale
1674 @deprecated Use `config.lang` instead.
1678 Default generic polling interval in milliseconds.
1680 @property {Number} pollInterval
1685 The number of dynamic `<script>` nodes to insert by default before automatically
1686 removing them when loading scripts.
1688 This applies only to script nodes because removing the node will not make the
1689 evaluated script unavailable. Dynamic CSS nodes are not auto purged, because
1690 removing a linked style sheet will also remove the style definitions.
1692 @property {Number} purgethreshold
1697 Delay in milliseconds to wait after a window `resize` event before firing the
1698 event. If another `resize` event occurs before this delay has elapsed, the
1699 delay will start over to ensure that `resize` events are throttled.
1701 @property {Number} windowResizeDelay
1706 Base directory for dynamic loading.
1708 @property {String} base
1712 Base URL for a dynamic combo handler. This will be used to make combo-handled
1713 module requests if `combine` is set to `true.
1715 @property {String} comboBase
1716 @default "http://yui.yahooapis.com/combo?"
1720 Root path to prepend to each module path when creating a combo-handled request.
1722 This is updated for each YUI release to point to a specific version of the
1723 library; for example: "3.8.0/build/".
1725 @property {String} root
1729 Filter to apply to module urls. This filter will modify the default path for all
1732 The default path for the YUI library is the minified version of the files (e.g.,
1733 event-min.js). The filter property can be a predefined filter or a custom
1734 filter. The valid predefined filters are:
1736 - **debug**: Loads debug versions of modules (e.g., event-debug.js).
1737 - **raw**: Loads raw, non-minified versions of modules without debug logging
1740 You can also define a custom filter, which must be an object literal containing
1741 a search regular expression and a replacement string:
1744 searchExp : "-min\\.js",
1745 replaceStr: "-debug.js"
1748 @property {Object|String} filter
1752 Skin configuration and customizations.
1754 @property {Object} skin
1755 @param {String} [skin.defaultSkin='sam'] Default skin name. This skin will be
1756 applied automatically to skinnable components if not overridden by a
1757 component-specific skin name.
1758 @param {String} [skin.base='assets/skins/'] Default base path for a skin,
1759 relative to Loader's `base` path.
1760 @param {Object} [skin.overrides] Component-specific skin name overrides. Specify
1761 a component name as the key and, as the value, a string or array of strings
1762 for a skin or skins that should be loaded for that component instead of the
1767 Hash of per-component filter specifications. If specified for a given component,
1768 this overrides the global `filter` config.
1770 @property {Object} filters
1774 If `true`, YUI will use a combo handler to load multiple modules in as few
1775 requests as possible.
1777 The YUI CDN (which YUI uses by default) supports combo handling, but other
1778 servers may not. If the server from which you're loading YUI does not support
1779 combo handling, set this to `false`.
1781 Providing a value for the `base` config property will cause `combine` to default
1782 to `false` instead of `true`.
1784 @property {Boolean} combine
1789 Array of module names that should never be dynamically loaded.
1791 @property {String[]} ignore
1795 Array of module names that should always be loaded when required, even if
1796 already present on the page.
1798 @property {String[]} force
1802 DOM element or id that should be used as the insertion point for dynamically
1803 added `<script>` and `<link>` nodes.
1805 @property {HTMLElement|String} insertBefore
1809 Object hash containing attributes to add to dynamically added `<script>` nodes.
1811 @property {Object} jsAttributes
1815 Object hash containing attributes to add to dynamically added `<link>` nodes.
1817 @property {Object} cssAttributes
1821 Timeout in milliseconds before a dynamic JS or CSS request will be considered a
1822 failure. If not set, no timeout will be enforced.
1824 @property {Number} timeout
1828 Callback for the 'CSSComplete' event. When dynamically loading YUI components
1829 with CSS, this property fires when the CSS is finished loading.
1831 This provides an opportunity to enhance the presentation of a loading page a
1832 little bit before the entire loading process is done.
1834 @property {Function} onCSS
1838 A hash of module definitions to add to the list of available YUI modules. These
1839 modules can then be dynamically loaded via the `use()` method.
1841 This is a hash in which keys are module names and values are objects containing
1844 See `Loader.addModule()` for the supported module metadata fields. Also see
1845 `groups`, which provides a way to configure the base and combo spec for a set of
1853 fullpath: '/mymod1/mymod1.js'
1857 requires: ['mymod1'],
1858 fullpath: '/mymod2/mymod2.js'
1861 mymod3: '/js/mymod3.js',
1862 mycssmod: '/css/mycssmod.css'
1865 @property {Object} modules
1869 Aliases are dynamic groups of modules that can be used as shortcuts.
1875 davglass: [ 'node', 'yql', 'dd' ],
1876 mine: [ 'davglass', 'autocomplete']
1878 }).use('mine', function (Y) {
1879 // Node, YQL, DD & AutoComplete available here.
1882 @property {Object} aliases
1886 A hash of module group definitions.
1888 For each group you can specify a list of modules and the base path and
1889 combo spec to use when dynamically loading the modules.
1895 // specify whether or not this group has a combo service
1898 // The comboSeperator to use with this group's combo handler
1901 // The maxURLLength for this server
1904 // the base path for non-combo paths
1905 base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1907 // the path to the combo service
1908 comboBase: 'http://yui.yahooapis.com/combo?',
1910 // a fragment to prepend to the path attribute when
1911 // when building combo urls
1912 root: '2.8.0r4/build/',
1914 // the module definitions
1917 path: "yahoo-dom-event/yahoo-dom-event.js"
1920 path: "animation/animation.js",
1921 requires: ['yui2_yde']
1927 @property {Object} groups
1931 Path to the Loader JS file, relative to the `base` path.
1933 This is used to dynamically bootstrap the Loader when it's needed and isn't yet
1936 @property {String} loaderPath
1937 @default "loader/loader-min.js"
1941 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
1942 `false` to prevent YUI from loading any CSS, or set it to the string `"force"`
1943 to force CSS dependencies to be loaded even if their associated JS modules are
1946 @property {Boolean|String} fetchCSS
1951 Default gallery version used to build gallery module urls.
1953 @property {String} gallery
1958 Default YUI 2 version used to build YUI 2 module urls.
1960 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
1961 `2in3` config for pulling different revisions of the wrapped YUI 2 modules.
1963 @property {String} yui2
1969 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
1971 @property {String} 2in3
1977 Alternate console log function that should be used in environments without a
1978 supported native console. This function is executed with the YUI instance as its
1981 @property {Function} logFn
1986 The minimum log level to log messages for. Log levels are defined
1987 incrementally. Messages greater than or equal to the level specified will
1988 be shown. All others will be discarded. The order of log levels in
1989 increasing priority is:
1996 @property {String} logLevel
2002 Callback to execute when `Y.error()` is called. It receives the error message
2003 and a JavaScript error object if one was provided.
2005 This function is executed with the YUI instance as its `this` object.
2007 Returning `true` from this function will prevent an exception from being thrown.
2009 @property {Function} errorFn
2010 @param {String} errorFn.msg Error message
2011 @param {Object} [errorFn.err] Error object (if one was provided).
2016 A callback to execute when Loader fails to load one or more resources.
2018 This could be because of a script load failure. It could also be because a
2019 module fails to register itself when the `requireRegistration` config is `true`.
2021 If this function is defined, the `use()` callback will only be called when the
2022 loader succeeds. Otherwise, `use()` will always executes unless there was a
2023 JavaScript error when attaching a module.
2025 @property {Function} loadErrorFn
2030 If `true`, Loader will expect all loaded scripts to be first-class YUI modules
2031 that register themselves with the YUI global, and will trigger a failure if a
2032 loaded script does not register a YUI module.
2034 @property {Boolean} requireRegistration
2040 Cache serviced use() requests.
2042 @property {Boolean} cacheUse
2045 @deprecated No longer used.
2049 Whether or not YUI should use native ES5 functionality when available for
2050 features like `Y.Array.each()`, `Y.Object()`, etc.
2052 When `false`, YUI will always use its own fallback implementations instead of
2053 relying on ES5 functionality, even when ES5 functionality is available.
2055 @property {Boolean} useNativeES5
2061 * Leverage native JSON stringify if the browser has a native
2062 * implementation. In general, this is a good idea. See the Known Issues
2063 * section in the JSON user guide for caveats. The default value is true
2064 * for browsers with native JSON support.
2066 * @property useNativeJSONStringify
2073 * Leverage native JSON parse if the browser has a native implementation.
2074 * In general, this is a good idea. See the Known Issues section in the
2075 * JSON user guide for caveats. The default value is true for browsers with
2076 * native JSON support.
2078 * @property useNativeJSONParse
2085 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
2087 @property {Object|String} delayUntil
2091 You can use `load` or `domready` strings by default:
2094 delayUntil: 'domready'
2096 // This will not execute until 'domeready' occurs.
2099 Or you can delay until a node is available (with `available` or `contentready`):
2107 // This will not execute until a node matching the selector "#foo" is
2108 // available in the DOM.
2112 YUI.add('yui-base', function (Y, NAME) {
2117 * @submodule yui-base
2120 * The YUI module contains the components required for building the YUI
2121 * seed file. This includes the script loading mechanism, a simple queue,
2122 * and the core utilities for the library.
2124 * @submodule yui-base
2128 * Provides core language utilites and extensions used throughout YUI.
2134 var L = Y.Lang || (Y.Lang = {}),
2136 STRING_PROTO = String.prototype,
2137 TOSTRING = Object.prototype.toString,
2140 'undefined' : 'undefined',
2141 'number' : 'number',
2142 'boolean' : 'boolean',
2143 'string' : 'string',
2144 '[object Function]': 'function',
2145 '[object RegExp]' : 'regexp',
2146 '[object Array]' : 'array',
2147 '[object Date]' : 'date',
2148 '[object Error]' : 'error'
2151 SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
2153 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",
2154 WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+",
2155 TRIM_LEFT_REGEX = new RegExp("^" + WHITESPACE_CLASS),
2156 TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"),
2157 TRIMREGEX = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"),
2159 NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i;
2161 // -- Protected Methods --------------------------------------------------------
2164 Returns `true` if the given function appears to be implemented in native code,
2165 `false` otherwise. Will always return `false` -- even in ES5-capable browsers --
2166 if the `useNativeES5` YUI config option is set to `false`.
2168 This isn't guaranteed to be 100% accurate and won't work for anything other than
2169 functions, but it can be useful for determining whether a function like
2170 `Array.prototype.forEach` is native or a JS shim provided by another library.
2172 There's a great article by @kangax discussing certain flaws with this technique:
2173 <http://perfectionkills.com/detecting-built-in-host-methods/>
2175 While his points are valid, it's still possible to benefit from this function
2176 as long as it's used carefully and sparingly, and in such a way that false
2177 negatives have minimal consequences. It's used internally to avoid using
2178 potentially broken non-native ES5 shims that have been added to the page by
2182 @param {Function} fn Function to test.
2183 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
2188 L._isNative = function (fn) {
2189 return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
2192 // -- Public Methods -----------------------------------------------------------
2195 * Determines whether or not the provided item is an array.
2197 * Returns `false` for array-like collections such as the function `arguments`
2198 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
2199 * test for an array-like collection.
2202 * @param o The object to test.
2203 * @return {boolean} true if o is an array.
2206 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
2207 return L.type(o) === 'array';
2211 * Determines whether or not the provided item is a boolean.
2214 * @param o The object to test.
2215 * @return {boolean} true if o is a boolean.
2217 L.isBoolean = function(o) {
2218 return typeof o === 'boolean';
2222 * Determines whether or not the supplied item is a date instance.
2225 * @param o The object to test.
2226 * @return {boolean} true if o is a date.
2228 L.isDate = function(o) {
2229 return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
2234 * Determines whether or not the provided item is a function.
2235 * Note: Internet Explorer thinks certain functions are objects:
2239 * var obj = document.createElement("object");
2240 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
2242 * var input = document.createElement("input"); // append to body
2243 * Y.Lang.isFunction(input.focus) // reports false in IE
2247 * You will have to implement additional tests if these functions
2251 * @method isFunction
2253 * @param o The object to test.
2254 * @return {boolean} true if o is a function.
2256 L.isFunction = function(o) {
2257 return L.type(o) === 'function';
2261 * Determines whether or not the provided item is null.
2264 * @param o The object to test.
2265 * @return {boolean} true if o is null.
2267 L.isNull = function(o) {
2272 * Determines whether or not the provided item is a legal number.
2275 * @param o The object to test.
2276 * @return {boolean} true if o is a number.
2278 L.isNumber = function(o) {
2279 return typeof o === 'number' && isFinite(o);
2283 * Determines whether or not the provided item is of type object
2284 * or function. Note that arrays are also objects, so
2285 * <code>Y.Lang.isObject([]) === true</code>.
2288 * @param o The object to test.
2289 * @param failfn {boolean} fail if the input is a function.
2290 * @return {boolean} true if o is an object.
2291 * @see isPlainObject
2293 L.isObject = function(o, failfn) {
2295 return (o && (t === 'object' ||
2296 (!failfn && (t === 'function' || L.isFunction(o))))) || false;
2300 * Determines whether or not the provided value is a regexp.
2303 * @param value The value or object to test.
2304 * @return {boolean} true if value is a regexp.
2306 L.isRegExp = function(value) {
2307 return L.type(value) === 'regexp';
2311 * Determines whether or not the provided item is a string.
2314 * @param o The object to test.
2315 * @return {boolean} true if o is a string.
2317 L.isString = function(o) {
2318 return typeof o === 'string';
2322 * Determines whether or not the provided item is undefined.
2323 * @method isUndefined
2325 * @param o The object to test.
2326 * @return {boolean} true if o is undefined.
2328 L.isUndefined = function(o) {
2329 return typeof o === 'undefined';
2333 * A convenience method for detecting a legitimate non-null value.
2334 * Returns false for null/undefined/NaN, true for other values,
2335 * including 0/false/''
2338 * @param o The item to test.
2339 * @return {boolean} true if it is not null/undefined/NaN || false.
2341 L.isValue = function(o) {
2348 case 'null': // fallthru
2358 * Returns the current time in milliseconds.
2361 * @return {Number} Current time in milliseconds.
2365 L.now = Date.now || function () {
2366 return new Date().getTime();
2370 * Lightweight version of <code>Y.substitute</code>. Uses the same template
2371 * structure as <code>Y.substitute</code>, but doesn't support recursion,
2372 * auto-object coersion, or formats.
2374 * @param {string} s String to be modified.
2375 * @param {object} o Object containing replacement values.
2376 * @return {string} the substitute result.
2380 L.sub = function(s, o) {
2381 return s.replace ? s.replace(SUBREGEX, function (match, key) {
2382 return L.isUndefined(o[key]) ? match : o[key];
2387 * Returns a string without any leading or trailing whitespace. If
2388 * the input is not a string, the input will be returned untouched.
2391 * @param s {string} the string to trim.
2392 * @return {string} the trimmed string.
2394 L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) {
2395 return s && s.trim ? s.trim() : s;
2398 return s.replace(TRIMREGEX, '');
2405 * Returns a string without any leading whitespace.
2408 * @param s {string} the string to trim.
2409 * @return {string} the trimmed string.
2411 L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) {
2412 return s.trimLeft();
2414 return s.replace(TRIM_LEFT_REGEX, '');
2418 * Returns a string without any trailing whitespace.
2421 * @param s {string} the string to trim.
2422 * @return {string} the trimmed string.
2424 L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) {
2425 return s.trimRight();
2427 return s.replace(TRIM_RIGHT_REGEX, '');
2431 Returns one of the following strings, representing the type of the item passed
2448 * `typeof HTMLElementCollection` returns function in Safari, but
2449 `Y.Lang.type()` reports "object", which could be a good thing --
2450 but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2453 @param o the item to test.
2454 @return {string} the detected type.
2457 L.type = function(o) {
2458 return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2466 Native = Array.prototype,
2468 hasOwn = Object.prototype.hasOwnProperty;
2471 Provides utility methods for working with arrays. Additional array helpers can
2472 be found in the `collection` and `array-extras` modules.
2474 `Y.Array(thing)` returns a native array created from _thing_. Depending on
2475 _thing_'s type, one of the following will happen:
2477 * Arrays are returned unmodified unless a non-zero _startIndex_ is
2479 * Array-like collections (see `Array.test()`) are converted to arrays.
2480 * For everything else, a new array is created with _thing_ as the sole
2483 Note: elements that are also collections, such as `<form>` and `<select>`
2484 elements, are not automatically converted to arrays. To force a conversion,
2485 pass `true` as the value of the _force_ parameter.
2489 @param {Any} thing The thing to arrayify.
2490 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2491 collection, a subset of items starting at the specified index will be
2493 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2494 array-like collection no matter what.
2495 @return {Array} A native array created from _thing_, according to the rules
2498 function YArray(thing, startIndex, force) {
2501 /*jshint expr: true*/
2502 startIndex || (startIndex = 0);
2504 if (force || YArray.test(thing)) {
2505 // IE throws when trying to slice HTMLElement collections.
2507 return Native.slice.call(thing, startIndex);
2511 for (len = thing.length; startIndex < len; ++startIndex) {
2512 result.push(thing[startIndex]);
2525 Dedupes an array of strings, returning an array that's guaranteed to contain
2526 only one copy of a given string.
2528 This method differs from `Array.unique()` in that it's optimized for use only
2529 with arrays consisting entirely of strings or entirely of numbers, whereas
2530 `unique` may be used with other value types (but is slower).
2532 Using `dedupe()` with values other than strings or numbers, or with arrays
2533 containing a mix of strings and numbers, may result in unexpected behavior.
2536 @param {String[]|Number[]} array Array of strings or numbers to dedupe.
2537 @return {Array} Copy of _array_ containing no duplicate values.
2541 YArray.dedupe = Lang._isNative(Object.create) ? function (array) {
2542 var hash = Object.create(null),
2546 for (i = 0, len = array.length; i < len; ++i) {
2556 } : function (array) {
2561 for (i = 0, len = array.length; i < len; ++i) {
2564 if (!hasOwn.call(hash, item)) {
2574 Executes the supplied function on each item in the array. This method wraps
2575 the native ES5 `Array.forEach()` method if available.
2578 @param {Array} array Array to iterate.
2579 @param {Function} fn Function to execute on each item in the array. The function
2580 will receive the following arguments:
2581 @param {Any} fn.item Current array item.
2582 @param {Number} fn.index Current array index.
2583 @param {Array} fn.array Array being iterated.
2584 @param {Object} [thisObj] `this` object to use when calling _fn_.
2585 @return {YUI} The YUI instance.
2588 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2589 Native.forEach.call(array || [], fn, thisObj || Y);
2591 } : function (array, fn, thisObj) {
2592 for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2594 fn.call(thisObj || Y, array[i], i, array);
2609 Returns an object using the first array as keys and the second as values. If
2610 the second array is not provided, or if it doesn't contain the same number of
2611 values as the first array, then `true` will be used in place of the missing
2616 Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2617 // => {a: 'foo', b: 'bar', c: true}
2620 @param {String[]} keys Array of strings to use as keys.
2621 @param {Array} [values] Array to use as values.
2622 @return {Object} Hash using the first array as keys and the second as values.
2625 YArray.hash = function (keys, values) {
2627 vlen = (values && values.length) || 0,
2630 for (i = 0, len = keys.length; i < len; ++i) {
2632 hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2640 Returns the index of the first item in the array that's equal (using a strict
2641 equality check) to the specified _value_, or `-1` if the value isn't found.
2643 This method wraps the native ES5 `Array.indexOf()` method if available.
2646 @param {Array} array Array to search.
2647 @param {Any} value Value to search for.
2648 @param {Number} [from=0] The index at which to begin the search.
2649 @return {Number} Index of the item strictly equal to _value_, or `-1` if not
2653 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2654 return Native.indexOf.call(array, value, from);
2655 } : function (array, value, from) {
2656 // http://es5.github.com/#x15.4.4.14
2657 var len = array.length;
2660 from = (from > 0 || -1) * Math.floor(Math.abs(from));
2670 for (; from < len; ++from) {
2671 if (from in array && array[from] === value) {
2680 Numeric sort convenience function.
2682 The native `Array.prototype.sort()` function converts values to strings and
2683 sorts them in lexicographic order, which is unsuitable for sorting numeric
2684 values. Provide `Array.numericSort` as a custom sort function when you want
2685 to sort values in numeric order.
2689 [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2690 // => [4, 8, 15, 16, 23, 42]
2693 @param {Number} a First value to compare.
2694 @param {Number} b Second value to compare.
2695 @return {Number} Difference between _a_ and _b_.
2698 YArray.numericSort = function (a, b) {
2703 Executes the supplied function on each item in the array. Returning a truthy
2704 value from the function will stop the processing of remaining items.
2707 @param {Array} array Array to iterate over.
2708 @param {Function} fn Function to execute on each item. The function will receive
2709 the following arguments:
2710 @param {Any} fn.value Current array item.
2711 @param {Number} fn.index Current array index.
2712 @param {Array} fn.array Array being iterated over.
2713 @param {Object} [thisObj] `this` object to use when calling _fn_.
2714 @return {Boolean} `true` if the function returns a truthy value on any of the
2715 items in the array; `false` otherwise.
2718 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2719 return Native.some.call(array, fn, thisObj);
2720 } : function (array, fn, thisObj) {
2721 for (var i = 0, len = array.length; i < len; ++i) {
2722 if (i in array && fn.call(thisObj, array[i], i, array)) {
2731 Evaluates _obj_ to determine if it's an array, an array-like collection, or
2732 something else. This is useful when working with the function `arguments`
2733 collection and `HTMLElement` collections.
2735 Note: This implementation doesn't consider elements that are also
2736 collections, such as `<form>` and `<select>`, to be array-like.
2739 @param {Object} obj Object to test.
2740 @return {Number} A number indicating the results of the test:
2742 * 0: Neither an array nor an array-like collection.
2744 * 2: Array-like collection.
2748 YArray.test = function (obj) {
2751 if (Lang.isArray(obj)) {
2753 } else if (Lang.isObject(obj)) {
2755 // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
2756 // or functions without apply/call (Safari
2757 // HTMLElementCollection bug).
2758 if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
2767 * The YUI module contains the components required for building the YUI
2768 * seed file. This includes the script loading mechanism, a simple queue,
2769 * and the core utilities for the library.
2771 * @submodule yui-base
2775 * A simple FIFO queue. Items are added to the Queue with add(1..n items) and
2776 * removed using next().
2780 * @param {MIXED} item* 0..n items to seed the queue.
2784 this.add.apply(this, arguments);
2789 * Initialize the queue
2796 * The collection of enqueued items
2806 * Get the next item in the queue. FIFO support
2809 * @return {MIXED} the next item in the queue.
2812 return this._q.shift();
2816 * Get the last in the queue. LIFO support.
2819 * @return {MIXED} the last item in the queue.
2822 return this._q.pop();
2826 * Add 0..n items to the end of the queue.
2829 * @param {MIXED} item* 0..n items.
2830 * @return {object} this queue.
2833 this._q.push.apply(this._q, arguments);
2839 * Returns the current number of queued items.
2842 * @return {Number} The size.
2845 return this._q.length;
2851 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2854 The YUI module contains the components required for building the YUI seed file.
2855 This includes the script loading mechanism, a simple queue, and the core
2856 utilities for the library.
2862 var CACHED_DELIMITER = '__',
2864 hasOwn = Object.prototype.hasOwnProperty,
2865 isObject = Y.Lang.isObject;
2868 Returns a wrapper for a function which caches the return value of that function,
2869 keyed off of the combined string representation of the argument values provided
2870 when the wrapper is called.
2872 Calling this function again with the same arguments will return the cached value
2873 rather than executing the wrapped function.
2875 Note that since the cache is keyed off of the string representation of arguments
2876 passed to the wrapper function, arguments that aren't strings and don't provide
2877 a meaningful `toString()` method may result in unexpected caching behavior. For
2878 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2879 string `[object Object]` when used as a cache key.
2882 @param {Function} source The function to memoize.
2883 @param {Object} [cache={}] Object in which to store cached values. You may seed
2884 this object with pre-existing cached values if desired.
2885 @param {any} [refetch] If supplied, this value is compared with the cached value
2886 using a `==` comparison. If the values are equal, the wrapped function is
2887 executed again even though a cached value exists.
2888 @return {Function} Wrapped function.
2891 Y.cached = function (source, cache, refetch) {
2892 /*jshint expr: true*/
2893 cache || (cache = {});
2895 return function (arg) {
2896 var key = arguments.length > 1 ?
2897 Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2900 /*jshint eqeqeq: false*/
2901 if (!(key in cache) || (refetch && cache[key] == refetch)) {
2902 cache[key] = source.apply(source, arguments);
2910 Returns the `location` object from the window/frame in which this YUI instance
2911 operates, or `undefined` when executing in a non-browser environment
2914 It is _not_ recommended to hold references to the `window.location` object
2915 outside of the scope of a function in which its properties are being accessed or
2916 its methods are being called. This is because of a nasty bug/issue that exists
2917 in both Safari and MobileSafari browsers:
2918 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
2921 @return {location} The `location` object from the window/frame in which this YUI
2925 Y.getLocation = function () {
2926 // It is safer to look this up every time because yui-base is attached to a
2927 // YUI instance before a user's config is applied; i.e. `Y.config.win` does
2928 // not point the correct window object when this file is loaded.
2929 var win = Y.config.win;
2931 // It is not safe to hold a reference to the `location` object outside the
2932 // scope in which it is being used. The WebKit engine used in Safari and
2933 // MobileSafari will "disconnect" the `location` object from the `window`
2934 // when a page is restored from back/forward history cache.
2935 return win && win.location;
2939 Returns a new object containing all of the properties of all the supplied
2940 objects. The properties from later objects will overwrite those in earlier
2943 Passing in a single object will create a shallow copy of it. For a deep copy,
2947 @param {Object} objects* One or more objects to merge.
2948 @return {Object} A new merged object.
2950 Y.merge = function () {
2952 len = arguments.length,
2957 for (; i < len; ++i) {
2961 if (hasOwn.call(obj, key)) {
2962 result[key] = obj[key];
2971 Mixes _supplier_'s properties into _receiver_.
2973 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
2974 shadowed unless the _overwrite_ parameter is `true`, and will not be merged
2975 unless the _merge_ parameter is `true`.
2977 In the default mode (0), only properties the supplier owns are copied (prototype
2978 properties are not copied). The following copying modes are available:
2980 * `0`: _Default_. Object to object.
2981 * `1`: Prototype to prototype.
2982 * `2`: Prototype to prototype and object to object.
2983 * `3`: Prototype to object.
2984 * `4`: Object to prototype.
2987 @param {Function|Object} receiver The object or function to receive the mixed
2989 @param {Function|Object} supplier The object or function supplying the
2990 properties to be mixed.
2991 @param {Boolean} [overwrite=false] If `true`, properties that already exist
2992 on the receiver will be overwritten with properties from the supplier.
2993 @param {String[]} [whitelist] An array of property names to copy. If
2994 specified, only the whitelisted properties will be copied, and all others
2996 @param {Number} [mode=0] Mix mode to use. See above for available modes.
2997 @param {Boolean} [merge=false] If `true`, objects and arrays that already
2998 exist on the receiver will have the corresponding object/array from the
2999 supplier merged into them, rather than being skipped or overwritten. When
3000 both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
3001 @return {Function|Object|YUI} The receiver, or the YUI instance if the
3002 specified receiver is falsy.
3004 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
3005 var alwaysOverwrite, exists, from, i, key, len, to;
3007 // If no supplier is given, we return the receiver. If no receiver is given,
3008 // we return Y. Returning Y doesn't make much sense to me, but it's
3009 // grandfathered in for backcompat reasons.
3010 if (!receiver || !supplier) {
3011 return receiver || Y;
3015 // In mode 2 (prototype to prototype and object to object), we recurse
3016 // once to do the proto to proto mix. The object to object mix will be
3017 // handled later on.
3019 Y.mix(receiver.prototype, supplier.prototype, overwrite,
3020 whitelist, 0, merge);
3023 // Depending on which mode is specified, we may be copying from or to
3024 // the prototypes of the supplier and receiver.
3025 from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
3026 to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
3028 // If either the supplier or receiver doesn't actually have a
3029 // prototype property, then we could end up with an undefined `from`
3030 // or `to`. If that happens, we abort and return the receiver.
3039 // If `overwrite` is truthy and `merge` is falsy, then we can skip a
3040 // property existence check on each iteration and save some time.
3041 alwaysOverwrite = overwrite && !merge;
3044 for (i = 0, len = whitelist.length; i < len; ++i) {
3047 // We call `Object.prototype.hasOwnProperty` instead of calling
3048 // `hasOwnProperty` on the object itself, since the object's
3049 // `hasOwnProperty` method may have been overridden or removed.
3050 // Also, some native objects don't implement a `hasOwnProperty`
3052 if (!hasOwn.call(from, key)) {
3056 // The `key in to` check here is (sadly) intentional for backwards
3057 // compatibility reasons. It prevents undesired shadowing of
3058 // prototype members on `to`.
3059 exists = alwaysOverwrite ? false : key in to;
3061 if (merge && exists && isObject(to[key], true)
3062 && isObject(from[key], true)) {
3063 // If we're in merge mode, and the key is present on both
3064 // objects, and the value on both objects is either an object or
3065 // an array (but not a function), then we recurse to merge the
3066 // `from` value into the `to` value instead of overwriting it.
3068 // Note: It's intentional that the whitelist isn't passed to the
3069 // recursive call here. This is legacy behavior that lots of
3070 // code still depends on.
3071 Y.mix(to[key], from[key], overwrite, null, 0, merge);
3072 } else if (overwrite || !exists) {
3073 // We're not in merge mode, so we'll only copy the `from` value
3074 // to the `to` value if we're in overwrite mode or if the
3075 // current key doesn't exist on the `to` object.
3076 to[key] = from[key];
3081 // The code duplication here is for runtime performance reasons.
3082 // Combining whitelist and non-whitelist operations into a single
3083 // loop or breaking the shared logic out into a function both result
3084 // in worse performance, and Y.mix is critical enough that the byte
3085 // tradeoff is worth it.
3086 if (!hasOwn.call(from, key)) {
3090 // The `key in to` check here is (sadly) intentional for backwards
3091 // compatibility reasons. It prevents undesired shadowing of
3092 // prototype members on `to`.
3093 exists = alwaysOverwrite ? false : key in to;
3095 if (merge && exists && isObject(to[key], true)
3096 && isObject(from[key], true)) {
3097 Y.mix(to[key], from[key], overwrite, null, 0, merge);
3098 } else if (overwrite || !exists) {
3099 to[key] = from[key];
3103 // If this is an IE browser with the JScript enumeration bug, force
3104 // enumeration of the buggy properties by making a recursive call with
3105 // the buggy properties as the whitelist.
3106 if (Y.Object._hasEnumBug) {
3107 Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
3114 * The YUI module contains the components required for building the YUI
3115 * seed file. This includes the script loading mechanism, a simple queue,
3116 * and the core utilities for the library.
3118 * @submodule yui-base
3122 * Adds utilities to the YUI instance for working with objects.
3128 hasOwn = Object.prototype.hasOwnProperty,
3130 UNDEFINED, // <-- Note the comma. We're still declaring vars.
3133 * Returns a new object that uses _obj_ as its prototype. This method wraps the
3134 * native ES5 `Object.create()` method if available, but doesn't currently
3135 * pass through `Object.create()`'s second argument (properties) in order to
3136 * ensure compatibility with older browsers.
3139 * @param {Object} obj Prototype object.
3140 * @return {Object} New object using _obj_ as its prototype.
3143 O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
3144 // We currently wrap the native Object.create instead of simply aliasing it
3145 // to ensure consistency with our fallback shim, which currently doesn't
3146 // support Object.create()'s second argument (properties). Once we have a
3147 // safe fallback for the properties arg, we can stop wrapping
3149 return Object.create(obj);
3151 // Reusable constructor function for the Object.create() shim.
3155 return function (obj) {
3162 * Property names that IE doesn't enumerate in for..in loops, even when they
3163 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
3164 * manually enumerate these properties.
3166 * @property _forceEnum
3171 forceEnum = O._forceEnum = [
3174 'propertyIsEnumerable',
3181 * `true` if this browser has the JScript enumeration bug that prevents
3182 * enumeration of the properties named in the `_forceEnum` array, `false`
3186 * - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
3187 * - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
3189 * @property _hasEnumBug
3194 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
3197 * `true` if this browser incorrectly considers the `prototype` property of
3198 * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x.
3200 * @property _hasProtoEnumBug
3205 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
3208 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
3209 * exists only on _obj_'s prototype. This is essentially a safer version of
3210 * `obj.hasOwnProperty()`.
3213 * @param {Object} obj Object to test.
3214 * @param {String} key Property name to look for.
3215 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3218 owns = O.owns = function (obj, key) {
3219 return !!obj && hasOwn.call(obj, key);
3220 }; // <-- End of var declarations.
3223 * Alias for `owns()`.
3226 * @param {Object} obj Object to test.
3227 * @param {String} key Property name to look for.
3228 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3234 * Returns an array containing the object's enumerable keys. Does not include
3235 * prototype keys or non-enumerable keys.
3237 * Note that keys are returned in enumeration order (that is, in the same order
3238 * that they would be enumerated by a `for-in` loop), which may not be the same
3239 * as the order in which they were defined.
3241 * This method is an alias for the native ES5 `Object.keys()` method if
3242 * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of
3243 * `Object.keys()` have an inconsistency as they consider `prototype` to be
3244 * enumerable, so a non-native shim is used to rectify the difference.
3248 * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
3249 * // => ['a', 'b', 'c']
3252 * @param {Object} obj An object.
3253 * @return {String[]} Array of keys.
3256 O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) {
3257 if (!Lang.isObject(obj)) {
3258 throw new TypeError('Object.keys called on a non-object');
3264 if (hasProtoEnumBug && typeof obj === 'function') {
3266 if (owns(obj, key) && key !== 'prototype') {
3272 if (owns(obj, key)) {
3279 for (i = 0, len = forceEnum.length; i < len; ++i) {
3282 if (owns(obj, key)) {
3292 * Returns an array containing the values of the object's enumerable keys.
3294 * Note that values are returned in enumeration order (that is, in the same
3295 * order that they would be enumerated by a `for-in` loop), which may not be the
3296 * same as the order in which they were defined.
3300 * Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
3301 * // => ['foo', 'bar', 'baz']
3304 * @param {Object} obj An object.
3305 * @return {Array} Array of values.
3308 O.values = function (obj) {
3309 var keys = O.keys(obj),
3314 for (; i < len; ++i) {
3315 values.push(obj[keys[i]]);
3322 * Returns the number of enumerable keys owned by an object.
3325 * @param {Object} obj An object.
3326 * @return {Number} The object's size.
3329 O.size = function (obj) {
3331 return O.keys(obj).length;
3333 return 0; // Legacy behavior for non-objects.
3338 * Returns `true` if the object owns an enumerable property with the specified
3342 * @param {Object} obj An object.
3343 * @param {any} value The value to search for.
3344 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3347 O.hasValue = function (obj, value) {
3348 return Y.Array.indexOf(O.values(obj), value) > -1;
3352 * Executes a function on each enumerable property in _obj_. The function
3353 * receives the value, the key, and the object itself as parameters (in that
3356 * By default, only properties owned by _obj_ are enumerated. To include
3357 * prototype properties, set the _proto_ parameter to `true`.
3360 * @param {Object} obj Object to enumerate.
3361 * @param {Function} fn Function to execute on each enumerable property.
3362 * @param {mixed} fn.value Value of the current property.
3363 * @param {String} fn.key Key of the current property.
3364 * @param {Object} fn.obj Object being enumerated.
3365 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3366 * @param {Boolean} [proto=false] Include prototype properties.
3367 * @return {YUI} the YUI instance.
3371 O.each = function (obj, fn, thisObj, proto) {
3375 if (proto || owns(obj, key)) {
3376 fn.call(thisObj || Y, obj[key], key, obj);
3384 * Executes a function on each enumerable property in _obj_, but halts if the
3385 * function returns a truthy value. The function receives the value, the key,
3386 * and the object itself as paramters (in that order).
3388 * By default, only properties owned by _obj_ are enumerated. To include
3389 * prototype properties, set the _proto_ parameter to `true`.
3392 * @param {Object} obj Object to enumerate.
3393 * @param {Function} fn Function to execute on each enumerable property.
3394 * @param {mixed} fn.value Value of the current property.
3395 * @param {String} fn.key Key of the current property.
3396 * @param {Object} fn.obj Object being enumerated.
3397 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3398 * @param {Boolean} [proto=false] Include prototype properties.
3399 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3400 * `false` otherwise.
3403 O.some = function (obj, fn, thisObj, proto) {
3407 if (proto || owns(obj, key)) {
3408 if (fn.call(thisObj || Y, obj[key], key, obj)) {
3418 * Retrieves the sub value at the provided path,
3419 * from the value object provided.
3423 * @param o The object from which to extract the property value.
3424 * @param path {Array} A path array, specifying the object traversal path
3425 * from which to obtain the sub value.
3426 * @return {Any} The value stored in the path, undefined if not found,
3427 * undefined if the source is not an object. Returns the source object
3428 * if an empty path is provided.
3430 O.getValue = function(o, path) {
3431 if (!Lang.isObject(o)) {
3439 for (i = 0; o !== UNDEFINED && i < l; i++) {
3447 * Sets the sub-attribute value at the provided path on the
3448 * value object. Returns the modified value object, or
3449 * undefined if the path is invalid.
3453 * @param o The object on which to set the sub value.
3454 * @param path {Array} A path array, specifying the object traversal path
3455 * at which to set the sub value.
3456 * @param val {Any} The new value for the sub-attribute.
3457 * @return {Object} The modified object, with the new sub value set, or
3458 * undefined, if the path was invalid.
3460 O.setValue = function(o, path, val) {
3463 leafIdx = p.length - 1,
3467 for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3471 if (ref !== UNDEFINED) {
3482 * Returns `true` if the object has no enumerable properties of its own.
3485 * @param {Object} obj An object.
3486 * @return {Boolean} `true` if the object is empty.
3490 O.isEmpty = function (obj) {
3491 return !O.keys(Object(obj)).length;
3494 * The YUI module contains the components required for building the YUI seed
3495 * file. This includes the script loading mechanism, a simple queue, and the
3496 * core utilities for the library.
3498 * @submodule yui-base
3502 * YUI user agent detection.
3503 * Do not fork for a browser if it can be avoided. Use feature detection when
3504 * you can. Use the user agent as a last resort. For all fields listed
3505 * as @type float, UA stores a version number for the browser engine,
3506 * 0 otherwise. This value may or may not map to the version number of
3507 * the browser using the engine. The value is presented as a float so
3508 * that it can easily be used for boolean evaluation as well as for
3509 * looking for a particular range of versions. Because of this,
3510 * some of the granularity of the version info may be lost. The fields that
3511 * are @type string default to null. The API docs list the values that
3512 * these fields can have.
3518 * Static method on `YUI.Env` for parsing a UA string. Called at instantiation
3519 * to populate `Y.UA`.
3523 * @param {String} [subUA=navigator.userAgent] UA string to parse
3524 * @return {Object} The Y.UA object
3526 YUI.Env.parseUA = function(subUA) {
3528 var numberify = function(s) {
3530 return parseFloat(s.replace(/\./g, function() {
3531 return (c++ === 1) ? '' : '.';
3537 nav = win && win.navigator,
3542 * Internet Explorer version number or 0. Example: 6
3550 * Opera version number or 0. Example: 9.2
3558 * Gecko engine revision number. Will evaluate to 1 if Gecko
3559 * is detected but the revision could not be found. Other browsers
3560 * will be 0. Example: 1.8
3562 * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
3563 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3564 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3565 * Firefox 3.0 <-- 1.9
3566 * Firefox 3.5 <-- 1.91
3575 * AppleWebKit version. KHTML browsers that are not WebKit browsers
3576 * will evaluate to 1, other browsers 0. Example: 418.9
3578 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3579 * latest available for Mac OSX 10.3.
3580 * Safari 2.0.2: 416 <-- hasOwnProperty introduced
3581 * Safari 2.0.4: 418 <-- preventDefault fixed
3582 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3583 * different versions of webkit
3584 * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
3585 * updated, but not updated
3586 * to the latest patch.
3587 * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native
3588 * SVG and many major issues fixed).
3589 * Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic
3590 * update from 2.x via the 10.4.11 OS patch.
3591 * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
3592 * yahoo.com user agent hack removed.
3594 * http://en.wikipedia.org/wiki/Safari_version_history
3602 * Safari will be detected as webkit, but this property will also
3603 * be populated with the Safari version number
3611 * Chrome will be detected as webkit, but this property will also
3612 * be populated with the Chrome version number
3620 * The mobile property will be set to a string containing any relevant
3621 * user agent information when a modern mobile browser is detected.
3622 * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3623 * devices with the WebKit-based browser, and Opera Mini.
3632 * Adobe AIR version number or 0. Only populated if webkit is detected.
3639 * PhantomJS version number or 0. Only populated if webkit is detected.
3641 * @property phantomjs
3646 * Detects Apple iPad's OS version
3653 * Detects Apple iPhone's OS version
3660 * Detects Apples iPod's OS version
3667 * General truthy check for iPad, iPhone or iPod
3675 * Detects Googles Android OS version
3682 * Detects Kindle Silk
3689 * Detects Kindle Silk Acceleration
3696 * Detects Palms WebOS version
3704 * Google Caja version number or 0.
3708 caja: nav && nav.cajaVersion,
3711 * Set to true if the page appears to be in SSL
3719 * The operating system. Currently only detecting windows or macintosh
3728 * The Nodejs Version
3736 * Window8/IE10 Application host environment
3741 winjs: !!((typeof Windows !== "undefined") && Windows.System),
3743 * Are touch/msPointer events available on this device
3744 * @property touchEnabled
3751 ua = subUA || nav && nav.userAgent,
3753 loc = win && win.location,
3755 href = loc && loc.href,
3760 * The User Agent string that was parsed
3761 * @property userAgent
3768 o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3772 if ((/windows|win32/i).test(ua)) {
3774 } else if ((/macintosh|mac_powerpc/i).test(ua)) {
3776 } else if ((/android/i).test(ua)) {
3778 } else if ((/symbos/i).test(ua)) {
3780 } else if ((/linux/i).test(ua)) {
3782 } else if ((/rhino/i).test(ua)) {
3786 // Modern KHTML browsers should qualify as Safari X-Grade
3787 if ((/KHTML/).test(ua)) {
3790 if ((/IEMobile|XBLWP7/).test(ua)) {
3791 o.mobile = 'windows';
3793 if ((/Fennec/).test(ua)) {
3796 // Modern WebKit browsers are at least X-Grade
3797 m = ua.match(/AppleWebKit\/([^\s]*)/);
3799 o.webkit = numberify(m[1]);
3800 o.safari = o.webkit;
3802 if (/PhantomJS/.test(ua)) {
3803 m = ua.match(/PhantomJS\/([^\s]*)/);
3805 o.phantomjs = numberify(m[1]);
3809 // Mobile browser check
3810 if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
3811 o.mobile = 'Apple'; // iPhone or iPod Touch
3813 m = ua.match(/OS ([^\s]*)/);
3815 m = numberify(m[1].replace('_', '.'));
3819 o.ipad = o.ipod = o.iphone = 0;
3821 m = ua.match(/iPad|iPod|iPhone/);
3823 o[m[0].toLowerCase()] = o.ios;
3826 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3828 // Nokia N-series, webOS, ex: NokiaN95
3831 if (/webOS/.test(ua)) {
3833 m = ua.match(/webOS\/([^\s]*);/);
3835 o.webos = numberify(m[1]);
3838 if (/ Android/.test(ua)) {
3839 if (/Mobile/.test(ua)) {
3840 o.mobile = 'Android';
3842 m = ua.match(/Android ([^\s]*);/);
3844 o.android = numberify(m[1]);
3848 if (/Silk/.test(ua)) {
3849 m = ua.match(/Silk\/([^\s]*)\)/);
3851 o.silk = numberify(m[1]);
3854 o.android = 2.34; //Hack for desktop mode in Kindle
3857 if (/Accelerated=true/.test(ua)) {
3863 m = ua.match(/OPR\/(\d+\.\d+)/);
3866 // Opera 15+ with Blink (pretends to be both Chrome and Safari)
3867 o.opera = numberify(m[1]);
3869 m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
3871 if (m && m[1] && m[2]) {
3872 o.chrome = numberify(m[2]); // Chrome
3873 o.safari = 0; //Reset safari back to 0
3874 if (m[1] === 'CrMo') {
3875 o.mobile = 'chrome';
3878 m = ua.match(/AdobeAIR\/([^\s]*)/);
3880 o.air = m[0]; // Adobe AIR 1.0 or better
3886 if (!o.webkit) { // not webkit
3887 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3888 if (/Opera/.test(ua)) {
3889 m = ua.match(/Opera[\s\/]([^\s]*)/);
3891 o.opera = numberify(m[1]);
3893 m = ua.match(/Version\/([^\s]*)/);
3895 o.opera = numberify(m[1]); // opera 10+
3898 if (/Opera Mobi/.test(ua)) {
3900 m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
3902 o.opera = numberify(m[1]);
3905 m = ua.match(/Opera Mini[^;]*/);
3908 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3910 } else { // not opera or webkit
3911 m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/);
3913 if (m && (m[1] || m[2])) {
3914 o.ie = numberify(m[1] || m[2]);
3915 } else { // not opera, webkit, or ie
3916 m = ua.match(/Gecko\/([^\s]*)/);
3919 o.gecko = 1; // Gecko detected, look for revision
3920 m = ua.match(/rv:([^\s\)]*)/);
3922 o.gecko = numberify(m[1]);
3923 if (/Mobile|Tablet/.test(ua)) {
3933 //Check for known properties to tell if touch events are enabled on this device or if
3934 //the number of MSPointer touchpoints on this device is greater than 0.
3935 if (win && nav && !(o.chrome && o.chrome < 6)) {
3936 o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
3939 //It was a parsed UA, do not assign the global value.
3942 if (typeof process === 'object') {
3944 if (process.versions && process.versions.node) {
3946 o.os = process.platform;
3947 o.nodejs = numberify(process.versions.node);
3959 Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3962 Performs a simple comparison between two version numbers, accounting for
3963 standard versioning logic such as the fact that "535.8" is a lower version than
3964 "535.24", even though a simple numerical comparison would indicate that it's
3965 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
3966 considered equivalent.
3968 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
3969 1 if _a_ is higher than _b_.
3971 Versions may be numbers or strings containing numbers and dots. For example,
3972 both `535` and `"535.8.10"` are acceptable. A version string containing
3973 non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
3975 @method compareVersions
3976 @param {Number|String} a First version number to compare.
3977 @param {Number|String} b Second version number to compare.
3978 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
3981 Y.UA.compareVersions = function (a, b) {
3982 var aPart, aParts, bPart, bParts, i, len;
3988 aParts = (a + '').split('.');
3989 bParts = (b + '').split('.');
3991 for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
3992 aPart = parseInt(aParts[i], 10);
3993 bPart = parseInt(bParts[i], 10);
3995 /*jshint expr: true*/
3996 isNaN(aPart) && (aPart = 0);
3997 isNaN(bPart) && (bPart = 0);
3999 if (aPart < bPart) {
4003 if (aPart > bPart) {
4011 "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
4012 "anim-shape-transform": ["anim-shape"],
4013 "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"],
4014 "attribute": ["attribute-base","attribute-complex"],
4015 "attribute-events": ["attribute-observable"],
4016 "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
4017 "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
4018 "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
4019 "base": ["base-base","base-pluginhost","base-build"],
4020 "cache": ["cache-base","cache-offline","cache-plugin"],
4021 "charts": ["charts-base"],
4022 "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
4023 "color": ["color-base","color-hsl","color-harmony"],
4024 "controller": ["router"],
4025 "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
4026 "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
4027 "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
4028 "datatype": ["datatype-date","datatype-number","datatype-xml"],
4029 "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
4030 "datatype-number": ["datatype-number-parse","datatype-number-format"],
4031 "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
4032 "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
4033 "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
4034 "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
4035 "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"],
4036 "event-custom": ["event-custom-base","event-custom-complex"],
4037 "event-gestures": ["event-flick","event-move"],
4038 "handlebars": ["handlebars-compiler"],
4039 "highlight": ["highlight-base","highlight-accentfold"],
4040 "history": ["history-base","history-hash","history-hash-ie","history-html5"],
4041 "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
4042 "json": ["json-parse","json-stringify"],
4043 "loader": ["loader-base","loader-rollup","loader-yui3"],
4044 "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
4045 "pluginhost": ["pluginhost-base","pluginhost-config"],
4046 "querystring": ["querystring-parse","querystring-stringify"],
4047 "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
4048 "resize": ["resize-base","resize-proxy","resize-constrain"],
4049 "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
4050 "template": ["template-base","template-micro"],
4051 "text": ["text-accentfold","text-wordbreak"],
4052 "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]