[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 /** 9 The YUI module contains the components required for building the YUI seed file. 10 This includes the script loading mechanism, a simple queue, and the core 11 utilities for the library. 12 13 @module yui 14 @main yui 15 @submodule yui-base 16 **/ 17 18 /*jshint eqeqeq: false*/ 19 if (typeof YUI != 'undefined') { 20 YUI._YUI = YUI; 21 } 22 23 /** 24 The YUI global namespace object. This is the constructor for all YUI instances. 25 26 This is a self-instantiable factory function, meaning you don't need to precede 27 it with the `new` operator. You can invoke it directly like this: 28 29 YUI().use('*', function (Y) { 30 // Y is a new YUI instance. 31 }); 32 33 But it also works like this: 34 35 var Y = YUI(); 36 37 The `YUI` constructor accepts an optional config object, like this: 38 39 YUI({ 40 debug: true, 41 combine: false 42 }).use('node', function (Y) { 43 // Y.Node is ready to use. 44 }); 45 46 See the API docs for the <a href="config.html">Config</a> class for the complete 47 list of supported configuration properties accepted by the YUI constuctor. 48 49 If a global `YUI` object is already defined, the existing YUI object will not be 50 overwritten, to ensure that defined namespaces are preserved. 51 52 Each YUI instance has full custom event support, but only if the event system is 53 available. 54 55 @class YUI 56 @uses EventTarget 57 @constructor 58 @global 59 @param {Object} [config]* Zero or more optional configuration objects. Config 60 values are stored in the `Y.config` property. See the 61 <a href="config.html">Config</a> docs for the list of supported properties. 62 **/ 63 64 /*global YUI*/ 65 /*global YUI_config*/ 66 var YUI = function() { 67 var i = 0, 68 Y = this, 69 args = arguments, 70 l = args.length, 71 instanceOf = function(o, type) { 72 return (o && o.hasOwnProperty && (o instanceof type)); 73 }, 74 gconf = (typeof YUI_config !== 'undefined') && YUI_config; 75 76 if (!(instanceOf(Y, YUI))) { 77 Y = new YUI(); 78 } else { 79 // set up the core environment 80 Y._init(); 81 82 /** 83 Master configuration that might span multiple contexts in a non- 84 browser environment. It is applied first to all instances in all 85 contexts. 86 87 @example 88 89 YUI.GlobalConfig = { 90 filter: 'debug' 91 }; 92 93 YUI().use('node', function (Y) { 94 // debug files used here 95 }); 96 97 YUI({ 98 filter: 'min' 99 }).use('node', function (Y) { 100 // min files used here 101 }); 102 103 @property {Object} GlobalConfig 104 @global 105 @static 106 **/ 107 if (YUI.GlobalConfig) { 108 Y.applyConfig(YUI.GlobalConfig); 109 } 110 111 /** 112 Page-level config applied to all YUI instances created on the 113 current page. This is applied after `YUI.GlobalConfig` and before 114 any instance-level configuration. 115 116 @example 117 118 // Single global var to include before YUI seed file 119 YUI_config = { 120 filter: 'debug' 121 }; 122 123 YUI().use('node', function (Y) { 124 // debug files used here 125 }); 126 127 YUI({ 128 filter: 'min' 129 }).use('node', function (Y) { 130 // min files used here 131 }); 132 133 @property {Object} YUI_config 134 @global 135 **/ 136 if (gconf) { 137 Y.applyConfig(gconf); 138 } 139 140 // bind the specified additional modules for this instance 141 if (!l) { 142 Y._setup(); 143 } 144 } 145 146 if (l) { 147 // Each instance can accept one or more configuration objects. 148 // These are applied after YUI.GlobalConfig and YUI_Config, 149 // overriding values set in those config files if there is a 150 // matching property. 151 for (; i < l; i++) { 152 Y.applyConfig(args[i]); 153 } 154 155 Y._setup(); 156 } 157 158 Y.instanceOf = instanceOf; 159 160 return Y; 161 }; 162 163 (function() { 164 165 var proto, prop, 166 VERSION = '3.17.2', 167 PERIOD = '.', 168 BASE = 'http://yui.yahooapis.com/', 169 /* 170 These CSS class names can't be generated by 171 getClassName since it is not available at the 172 time they are being used. 173 */ 174 DOC_LABEL = 'yui3-js-enabled', 175 CSS_STAMP_EL = 'yui3-css-stamp', 176 NOOP = function() {}, 177 SLICE = Array.prototype.slice, 178 APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo 179 'io.xdrResponse': 1, // can call. this should 180 'SWF.eventHandler': 1 }, // be done at build time 181 hasWin = (typeof window != 'undefined'), 182 win = (hasWin) ? window : null, 183 doc = (hasWin) ? win.document : null, 184 docEl = doc && doc.documentElement, 185 docClass = docEl && docEl.className, 186 instances = {}, 187 time = new Date().getTime(), 188 add = function(el, type, fn, capture) { 189 if (el && el.addEventListener) { 190 el.addEventListener(type, fn, capture); 191 } else if (el && el.attachEvent) { 192 el.attachEvent('on' + type, fn); 193 } 194 }, 195 remove = function(el, type, fn, capture) { 196 if (el && el.removeEventListener) { 197 // this can throw an uncaught exception in FF 198 try { 199 el.removeEventListener(type, fn, capture); 200 } catch (ex) {} 201 } else if (el && el.detachEvent) { 202 el.detachEvent('on' + type, fn); 203 } 204 }, 205 handleReady = function() { 206 YUI.Env.DOMReady = true; 207 if (hasWin) { 208 remove(doc, 'DOMContentLoaded', handleReady); 209 } 210 }, 211 handleLoad = function() { 212 YUI.Env.windowLoaded = true; 213 YUI.Env.DOMReady = true; 214 if (hasWin) { 215 remove(window, 'load', handleLoad); 216 } 217 }, 218 getLoader = function(Y, o) { 219 var loader = Y.Env._loader, 220 lCore = [ 'loader-base' ], 221 G_ENV = YUI.Env, 222 mods = G_ENV.mods; 223 224 if (loader) { 225 //loader._config(Y.config); 226 loader.ignoreRegistered = false; 227 loader.onEnd = null; 228 loader.data = null; 229 loader.required = []; 230 loader.loadType = null; 231 } else { 232 loader = new Y.Loader(Y.config); 233 Y.Env._loader = loader; 234 } 235 if (mods && mods.loader) { 236 lCore = [].concat(lCore, YUI.Env.loaderExtras); 237 } 238 YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore)); 239 240 return loader; 241 }, 242 243 clobber = function(r, s) { 244 for (var i in s) { 245 if (s.hasOwnProperty(i)) { 246 r[i] = s[i]; 247 } 248 } 249 }, 250 251 ALREADY_DONE = { success: true }; 252 253 // Stamp the documentElement (HTML) with a class of "yui-loaded" to 254 // enable styles that need to key off of JS being enabled. 255 if (docEl && docClass.indexOf(DOC_LABEL) == -1) { 256 if (docClass) { 257 docClass += ' '; 258 } 259 docClass += DOC_LABEL; 260 docEl.className = docClass; 261 } 262 263 if (VERSION.indexOf('@') > -1) { 264 VERSION = '3.5.0'; // dev time hack for cdn test 265 } 266 267 proto = { 268 /** 269 Applies a new configuration object to the config of this YUI instance. This 270 will merge new group/module definitions, and will also update the loader 271 cache if necessary. Updating `Y.config` directly will not update the cache. 272 273 @method applyConfig 274 @param {Object} o the configuration object. 275 @since 3.2.0 276 **/ 277 applyConfig: function(o) { 278 279 o = o || NOOP; 280 281 var attr, 282 name, 283 // detail, 284 config = this.config, 285 mods = config.modules, 286 groups = config.groups, 287 aliases = config.aliases, 288 loader = this.Env._loader; 289 290 for (name in o) { 291 if (o.hasOwnProperty(name)) { 292 attr = o[name]; 293 if (mods && name == 'modules') { 294 clobber(mods, attr); 295 } else if (aliases && name == 'aliases') { 296 clobber(aliases, attr); 297 } else if (groups && name == 'groups') { 298 clobber(groups, attr); 299 } else if (name == 'win') { 300 config[name] = (attr && attr.contentWindow) || attr; 301 config.doc = config[name] ? config[name].document : null; 302 } else if (name == '_yuid') { 303 // preserve the guid 304 } else { 305 config[name] = attr; 306 } 307 } 308 } 309 310 if (loader) { 311 loader._config(o); 312 } 313 314 }, 315 316 /** 317 Old way to apply a config to this instance (calls `applyConfig` under the 318 hood). 319 320 @private 321 @method _config 322 @param {Object} o The config to apply 323 **/ 324 _config: function(o) { 325 this.applyConfig(o); 326 }, 327 328 /** 329 Initializes this YUI instance. 330 331 @private 332 @method _init 333 **/ 334 _init: function() { 335 var filter, el, 336 Y = this, 337 G_ENV = YUI.Env, 338 Env = Y.Env, 339 prop; 340 341 /** 342 The version number of this YUI instance. 343 344 This value is typically updated by a script when a YUI release is built, 345 so it may not reflect the correct version number when YUI is run from 346 the development source tree. 347 348 @property {String} version 349 **/ 350 Y.version = VERSION; 351 352 if (!Env) { 353 Y.Env = { 354 core: ['intl-base'], 355 loaderExtras: ['loader-rollup', 'loader-yui3'], 356 mods: {}, // flat module map 357 versions: {}, // version module map 358 base: BASE, 359 cdn: BASE + VERSION + '/build/', 360 // bootstrapped: false, 361 _idx: 0, 362 _used: {}, 363 _attached: {}, 364 _exported: {}, 365 _missed: [], 366 _yidx: 0, 367 _uidx: 0, 368 _guidp: 'y', 369 _loaded: {}, 370 // serviced: {}, 371 // Regex in English: 372 // I'll start at the \b(yui). 373 // 1. Look in the test string for "yui" or 374 // "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it 375 // can't match "foyui" or "i_heart_yui". This can be anywhere in the string. 376 // 2. After #1 must come a forward slash followed by the string matched in #1, so 377 // "yui-base/yui-base" or "yui-pants/yui-pants". 378 // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min", 379 // so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt". 380 // 4. This is followed by ".js", so "yui/yui.js". 381 // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string, 382 // then capture the junk between the LAST "&" and the string in 1-4. So 383 // "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js" 384 // will capture "3.3.0/build/" 385 // 386 // Regex Exploded: 387 // (?:\? Find a ? 388 // (?:[^&]*&) followed by 0..n characters followed by an & 389 // * in fact, find as many sets of characters followed by a & as you can 390 // ([^&]*) capture the stuff after the last & in \1 391 // )? but it's ok if all this ?junk&more_junk stuff isn't even there 392 // \b( after a word break find either the string 393 // yui(?:-\w+)? "yui" optionally followed by a -, then more characters 394 // ) and store the yui-* string in \2 395 // \/\2 then comes a / followed by the yui-* string in \2 396 // (?:-(min|debug))? optionally followed by "-min" or "-debug" 397 // .js and ending in ".js" 398 _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/, 399 parseBasePath: function(src, pattern) { 400 var match = src.match(pattern), 401 path, filter; 402 403 if (match) { 404 path = RegExp.leftContext || src.slice(0, src.indexOf(match[0])); 405 406 // this is to set up the path to the loader. The file 407 // filter for loader should match the yui include. 408 filter = match[3]; 409 410 // extract correct path for mixed combo urls 411 // http://yuilibrary.com/projects/yui3/ticket/2528423 412 if (match[1]) { 413 path += '?' + match[1]; 414 } 415 path = { 416 filter: filter, 417 path: path 418 }; 419 } 420 return path; 421 }, 422 getBase: G_ENV && G_ENV.getBase || 423 function(pattern) { 424 var nodes = (doc && doc.getElementsByTagName('script')) || [], 425 path = Env.cdn, parsed, 426 i, len, src; 427 428 for (i = 0, len = nodes.length; i < len; ++i) { 429 src = nodes[i].src; 430 if (src) { 431 parsed = Y.Env.parseBasePath(src, pattern); 432 if (parsed) { 433 filter = parsed.filter; 434 path = parsed.path; 435 break; 436 } 437 } 438 } 439 440 // use CDN default 441 return path; 442 } 443 444 }; 445 446 Env = Y.Env; 447 448 Env._loaded[VERSION] = {}; 449 450 if (G_ENV && Y !== YUI) { 451 Env._yidx = ++G_ENV._yidx; 452 Env._guidp = ('yui_' + VERSION + '_' + 453 Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_'); 454 } else if (YUI._YUI) { 455 456 G_ENV = YUI._YUI.Env; 457 Env._yidx += G_ENV._yidx; 458 Env._uidx += G_ENV._uidx; 459 460 for (prop in G_ENV) { 461 if (!(prop in Env)) { 462 Env[prop] = G_ENV[prop]; 463 } 464 } 465 466 delete YUI._YUI; 467 } 468 469 Y.id = Y.stamp(Y); 470 instances[Y.id] = Y; 471 472 } 473 474 Y.constructor = YUI; 475 476 // configuration defaults 477 Y.config = Y.config || { 478 bootstrap: true, 479 cacheUse: true, 480 debug: true, 481 doc: doc, 482 fetchCSS: true, 483 throwFail: true, 484 useBrowserConsole: true, 485 useNativeES5: true, 486 win: win, 487 global: Function('return this')() 488 }; 489 490 //Register the CSS stamp element 491 if (doc && !doc.getElementById(CSS_STAMP_EL)) { 492 el = doc.createElement('div'); 493 el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>'; 494 YUI.Env.cssStampEl = el.firstChild; 495 if (doc.body) { 496 doc.body.appendChild(YUI.Env.cssStampEl); 497 } else { 498 docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild); 499 } 500 } else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) { 501 YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL); 502 } 503 504 Y.config.lang = Y.config.lang || 'en-US'; 505 506 Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE); 507 508 if (!filter || (!('mindebug').indexOf(filter))) { 509 filter = 'min'; 510 } 511 filter = (filter) ? '-' + filter : filter; 512 Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js'; 513 514 }, 515 516 /** 517 Finishes the instance setup. Attaches whatever YUI modules were defined 518 at the time that this instance was created. 519 520 @method _setup 521 @private 522 **/ 523 _setup: function() { 524 var i, Y = this, 525 core = [], 526 mods = YUI.Env.mods, 527 extras = Y.config.core || [].concat(YUI.Env.core); //Clone it.. 528 529 for (i = 0; i < extras.length; i++) { 530 if (mods[extras[i]]) { 531 core.push(extras[i]); 532 } 533 } 534 535 Y._attach(['yui-base']); 536 Y._attach(core); 537 538 if (Y.Loader) { 539 getLoader(Y); 540 } 541 542 // Y.log(Y.id + ' initialized', 'info', 'yui'); 543 }, 544 545 /** 546 Executes the named method on the specified YUI instance if that method is 547 whitelisted. 548 549 @method applyTo 550 @param {String} id YUI instance id. 551 @param {String} method Name of the method to execute. For example: 552 'Object.keys'. 553 @param {Array} args Arguments to apply to the method. 554 @return {Mixed} Return value from the applied method, or `null` if the 555 specified instance was not found or the method was not whitelisted. 556 **/ 557 applyTo: function(id, method, args) { 558 if (!(method in APPLY_TO_AUTH)) { 559 this.log(method + ': applyTo not allowed', 'warn', 'yui'); 560 return null; 561 } 562 563 var instance = instances[id], nest, m, i; 564 if (instance) { 565 nest = method.split('.'); 566 m = instance; 567 for (i = 0; i < nest.length; i = i + 1) { 568 m = m[nest[i]]; 569 if (!m) { 570 this.log('applyTo not found: ' + method, 'warn', 'yui'); 571 } 572 } 573 return m && m.apply(instance, args); 574 } 575 576 return null; 577 }, 578 579 /** 580 Registers a YUI module and makes it available for use in a `YUI().use()` call or 581 as a dependency for other modules. 582 583 The easiest way to create a first-class YUI module is to use 584 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build 585 tool. 586 587 Shifter will automatically wrap your module code in a `YUI.add()` call along 588 with any configuration info required for the module. 589 590 @example 591 592 YUI.add('davglass', function (Y) { 593 Y.davglass = function () { 594 Y.log('Dav was here!'); 595 }; 596 }, '3.4.0', { 597 requires: ['harley-davidson', 'mt-dew'] 598 }); 599 600 @method add 601 @param {String} name Module name. 602 @param {Function} fn Function containing module code. This function will be 603 executed whenever the module is attached to a specific YUI instance. 604 605 @param {YUI} fn.Y The YUI instance to which this module is attached. 606 @param {String} fn.name Name of the module 607 608 @param {String} version Module version number. This is currently used only for 609 informational purposes, and is not used internally by YUI. 610 611 @param {Object} [details] Module config. 612 @param {Array} [details.requires] Array of other module names that must be 613 attached before this module can be attached. 614 @param {Array} [details.optional] Array of optional module names that should 615 be attached before this module is attached if they've already been 616 loaded. If the `loadOptional` YUI option is `true`, optional modules 617 that have not yet been loaded will be loaded just as if they were hard 618 requirements. 619 @param {Array} [details.use] Array of module names that are included within 620 or otherwise provided by this module, and which should be attached 621 automatically when this module is attached. This makes it possible to 622 create "virtual rollup" modules that simply attach a collection of other 623 modules or submodules. 624 625 @return {YUI} This YUI instance. 626 **/ 627 add: function(name, fn, version, details) { 628 details = details || {}; 629 var env = YUI.Env, 630 mod = { 631 name: name, 632 fn: fn, 633 version: version, 634 details: details 635 }, 636 //Instance hash so we don't apply it to the same instance twice 637 applied = {}, 638 loader, inst, modInfo, 639 i, versions = env.versions; 640 641 env.mods[name] = mod; 642 versions[version] = versions[version] || {}; 643 versions[version][name] = mod; 644 645 for (i in instances) { 646 if (instances.hasOwnProperty(i)) { 647 inst = instances[i]; 648 if (!applied[inst.id]) { 649 applied[inst.id] = true; 650 loader = inst.Env._loader; 651 if (loader) { 652 modInfo = loader.getModuleInfo(name); 653 if (!modInfo || modInfo.temp) { 654 loader.addModule(details, name); 655 } 656 } 657 } 658 } 659 } 660 661 return this; 662 }, 663 664 /** 665 Executes the callback function associated with each required module, 666 attaching the module to this YUI instance. 667 668 @method _attach 669 @param {Array} r The array of modules to attach 670 @param {Boolean} [moot=false] If `true`, don't throw a warning if the module 671 is not attached. 672 @private 673 **/ 674 _attach: function(r, moot) { 675 var i, name, mod, details, req, use, after, 676 mods = YUI.Env.mods, 677 aliases = YUI.Env.aliases, 678 Y = this, j, 679 cache = YUI.Env._renderedMods, 680 loader = Y.Env._loader, 681 done = Y.Env._attached, 682 exported = Y.Env._exported, 683 len = r.length, loader, def, go, 684 c = [], 685 modArgs, esCompat, reqlen, modInfo, 686 condition, 687 __exports__, __imports__; 688 689 //Check for conditional modules (in a second+ instance) and add their requirements 690 //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass 691 for (i = 0; i < len; i++) { 692 name = r[i]; 693 mod = mods[name]; 694 c.push(name); 695 if (loader && loader.conditions[name]) { 696 for (j in loader.conditions[name]) { 697 if (loader.conditions[name].hasOwnProperty(j)) { 698 def = loader.conditions[name][j]; 699 go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y))); 700 if (go) { 701 c.push(def.name); 702 } 703 } 704 } 705 } 706 } 707 r = c; 708 len = r.length; 709 710 for (i = 0; i < len; i++) { 711 if (!done[r[i]]) { 712 name = r[i]; 713 mod = mods[name]; 714 715 if (aliases && aliases[name] && !mod) { 716 Y._attach(aliases[name]); 717 continue; 718 } 719 if (!mod) { 720 modInfo = loader && loader.getModuleInfo(name); 721 if (modInfo) { 722 mod = modInfo; 723 moot = true; 724 } 725 726 // Y.log('no js def for: ' + name, 'info', 'yui'); 727 728 //if (!loader || !loader.moduleInfo[name]) { 729 //if ((!loader || !loader.moduleInfo[name]) && !moot) { 730 if (!moot && name) { 731 if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) { 732 Y.Env._missed.push(name); 733 Y.Env._missed = Y.Array.dedupe(Y.Env._missed); 734 Y.message('NOT loaded: ' + name, 'warn', 'yui'); 735 } 736 } 737 } else { 738 done[name] = true; 739 //Don't like this, but in case a mod was asked for once, then we fetch it 740 //We need to remove it from the missed list ^davglass 741 for (j = 0; j < Y.Env._missed.length; j++) { 742 if (Y.Env._missed[j] === name) { 743 Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui'); 744 Y.Env._missed.splice(j, 1); 745 } 746 } 747 748 // Optional dependencies normally work by modifying the 749 // dependency list of a module. If the dependency's test 750 // passes it is added to the list. If not, it's not loaded. 751 // This following check ensures that optional dependencies 752 // are not attached when they were already loaded into the 753 // page (when bundling for example) 754 if (loader && !loader._canBeAttached(name)) { 755 Y.log('Failed to attach module ' + name, 'warn', 'yui'); 756 return true; 757 } 758 759 /* 760 If it's a temp module, we need to redo it's requirements if it's already loaded 761 since it may have been loaded by another instance and it's dependencies might 762 have been redefined inside the fetched file. 763 */ 764 if (loader && cache && cache[name] && cache[name].temp) { 765 loader.getRequires(cache[name]); 766 req = []; 767 modInfo = loader.getModuleInfo(name); 768 for (j in modInfo.expanded_map) { 769 if (modInfo.expanded_map.hasOwnProperty(j)) { 770 req.push(j); 771 } 772 } 773 Y._attach(req); 774 } 775 776 details = mod.details; 777 req = details.requires; 778 esCompat = details.es; 779 use = details.use; 780 after = details.after; 781 //Force Intl load if there is a language (Loader logic) @todo fix this shit 782 if (details.lang) { 783 req = req || []; 784 req.unshift('intl'); 785 } 786 787 if (req) { 788 reqlen = req.length; 789 for (j = 0; j < reqlen; j++) { 790 if (!done[req[j]]) { 791 if (!Y._attach(req)) { 792 return false; 793 } 794 break; 795 } 796 } 797 } 798 799 if (after) { 800 for (j = 0; j < after.length; j++) { 801 if (!done[after[j]]) { 802 if (!Y._attach(after, true)) { 803 return false; 804 } 805 break; 806 } 807 } 808 } 809 810 if (mod.fn) { 811 modArgs = [Y, name]; 812 if (esCompat) { 813 __imports__ = {}; 814 __exports__ = {}; 815 // passing `exports` and `imports` onto the module function 816 modArgs.push(__imports__, __exports__); 817 if (req) { 818 reqlen = req.length; 819 for (j = 0; j < reqlen; j++) { 820 __imports__[req[j]] = exported.hasOwnProperty(req[j]) ? exported[req[j]] : Y; 821 } 822 } 823 } 824 if (Y.config.throwFail) { 825 __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); 826 } else { 827 try { 828 __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); 829 } catch (e) { 830 Y.error('Attach error: ' + name, e, name); 831 return false; 832 } 833 } 834 if (esCompat) { 835 // store the `exports` in case others `es` modules requires it 836 exported[name] = __exports__; 837 838 // If an ES module is conditionally loaded and set 839 // to be used "instead" another module, replace the 840 // trigger module's content with the conditionally 841 // loaded one so the values returned by require() 842 // still makes sense 843 condition = mod.details.condition; 844 if (condition && condition.when === 'instead') { 845 exported[condition.trigger] = __exports__; 846 } 847 } 848 } 849 850 if (use) { 851 for (j = 0; j < use.length; j++) { 852 if (!done[use[j]]) { 853 if (!Y._attach(use)) { 854 return false; 855 } 856 break; 857 } 858 } 859 } 860 861 862 863 } 864 } 865 } 866 867 return true; 868 }, 869 870 /** 871 Delays the `use` callback until another event has taken place such as 872 `window.onload`, `domready`, `contentready`, or `available`. 873 874 @private 875 @method _delayCallback 876 @param {Function} cb The original `use` callback. 877 @param {String|Object} until Either an event name ('load', 'domready', etc.) 878 or an object containing event/args keys for contentready/available. 879 @return {Function} 880 **/ 881 _delayCallback: function(cb, until) { 882 883 var Y = this, 884 mod = ['event-base']; 885 886 until = (Y.Lang.isObject(until) ? until : { event: until }); 887 888 if (until.event === 'load') { 889 mod.push('event-synthetic'); 890 } 891 892 Y.log('Delaying use callback until: ' + until.event, 'info', 'yui'); 893 return function() { 894 Y.log('Use callback fired, waiting on delay', 'info', 'yui'); 895 var args = arguments; 896 Y._use(mod, function() { 897 Y.log('Delayed use wrapper callback after dependencies', 'info', 'yui'); 898 Y.on(until.event, function() { 899 args[1].delayUntil = until.event; 900 Y.log('Delayed use callback done after ' + until.event, 'info', 'yui'); 901 cb.apply(Y, args); 902 }, until.args); 903 }); 904 }; 905 }, 906 907 /** 908 Attaches one or more modules to this YUI instance. When this is executed, 909 the requirements of the desired modules are analyzed, and one of several 910 things can happen: 911 912 913 * All required modules have already been loaded, and just need to be 914 attached to this YUI instance. In this case, the `use()` callback will 915 be executed synchronously after the modules are attached. 916 917 * One or more modules have not yet been loaded, or the Get utility is not 918 available, or the `bootstrap` config option is `false`. In this case, 919 a warning is issued indicating that modules are missing, but all 920 available modules will still be attached and the `use()` callback will 921 be executed synchronously. 922 923 * One or more modules are missing and the Loader is not available but the 924 Get utility is, and `bootstrap` is not `false`. In this case, the Get 925 utility will be used to load the Loader, and we will then proceed to 926 the following state: 927 928 * One or more modules are missing and the Loader is available. In this 929 case, the Loader will be used to resolve the dependency tree for the 930 missing modules and load them and their dependencies. When the Loader is 931 finished loading modules, the `use()` callback will be executed 932 asynchronously. 933 934 @example 935 936 // Loads and attaches dd and its dependencies. 937 YUI().use('dd', function (Y) { 938 // ... 939 }); 940 941 // Loads and attaches dd and node as well as all of their dependencies. 942 YUI().use(['dd', 'node'], function (Y) { 943 // ... 944 }); 945 946 // Attaches all modules that have already been loaded. 947 YUI().use('*', function (Y) { 948 // ... 949 }); 950 951 // Attaches a gallery module. 952 YUI().use('gallery-yql', function (Y) { 953 // ... 954 }); 955 956 // Attaches a YUI 2in3 module. 957 YUI().use('yui2-datatable', function (Y) { 958 // ... 959 }); 960 961 @method use 962 @param {String|Array} modules* One or more module names to attach. 963 @param {Function} [callback] Callback function to be executed once all 964 specified modules and their dependencies have been attached. 965 @param {YUI} callback.Y The YUI instance created for this sandbox. 966 @param {Object} callback.status Object containing `success`, `msg` and 967 `data` properties. 968 @chainable 969 **/ 970 use: function() { 971 var args = SLICE.call(arguments, 0), 972 callback = args[args.length - 1], 973 Y = this, 974 i = 0, 975 name, 976 Env = Y.Env, 977 provisioned = true; 978 979 // The last argument supplied to use can be a load complete callback 980 if (Y.Lang.isFunction(callback)) { 981 args.pop(); 982 if (Y.config.delayUntil) { 983 callback = Y._delayCallback(callback, Y.config.delayUntil); 984 } 985 } else { 986 callback = null; 987 } 988 if (Y.Lang.isArray(args[0])) { 989 args = args[0]; 990 } 991 992 if (Y.config.cacheUse) { 993 while ((name = args[i++])) { 994 if (!Env._attached[name]) { 995 provisioned = false; 996 break; 997 } 998 } 999 1000 if (provisioned) { 1001 if (args.length) { 1002 Y.log('already provisioned: ' + args, 'info', 'yui'); 1003 } 1004 Y._notify(callback, ALREADY_DONE, args); 1005 return Y; 1006 } 1007 } 1008 1009 if (Y._loading) { 1010 Y._useQueue = Y._useQueue || new Y.Queue(); 1011 Y._useQueue.add([args, callback]); 1012 } else { 1013 Y._use(args, function(Y, response) { 1014 Y._notify(callback, response, args); 1015 }); 1016 } 1017 1018 return Y; 1019 }, 1020 1021 /** 1022 Sugar for loading both legacy and ES6-based YUI modules. 1023 1024 @method require 1025 @param {String} [modules*] List of module names to import or a single 1026 module name. 1027 @param {Function} callback Callback that gets called once all the modules 1028 were loaded. Each parameter of the callback is the export value of the 1029 corresponding module in the list. If the module is a legacy YUI module, 1030 the YUI instance is used instead of the module exports. 1031 @example 1032 ``` 1033 YUI().require(['es6-set'], function (Y, imports) { 1034 var Set = imports.Set, 1035 set = new Set(); 1036 }); 1037 ``` 1038 **/ 1039 require: function () { 1040 var args = SLICE.call(arguments), 1041 callback; 1042 1043 if (typeof args[args.length - 1] === 'function') { 1044 callback = args.pop(); 1045 1046 // only add the callback if one was provided 1047 // YUI().require('foo'); is valid 1048 args.push(function (Y) { 1049 var i, length = args.length, 1050 exported = Y.Env._exported, 1051 __imports__ = {}; 1052 1053 // Get only the imports requested as arguments 1054 for (i = 0; i < length; i++) { 1055 if (exported.hasOwnProperty(args[i])) { 1056 __imports__[args[i]] = exported[args[i]]; 1057 } 1058 } 1059 1060 // Using `undefined` because: 1061 // - Using `Y.config.global` would force the value of `this` to be 1062 // the global object even in strict mode 1063 // - Using `Y` goes against the goal of moving away from a shared 1064 // object and start thinking in terms of imported and exported 1065 // objects 1066 callback.call(undefined, Y, __imports__); 1067 }); 1068 } 1069 // Do not return the Y object. This makes it hard to follow this 1070 // traditional pattern: 1071 // var Y = YUI().use(...); 1072 // This is a good idea in the light of ES6 modules, to avoid working 1073 // in the global scope. 1074 // This also leaves the door open for returning a promise, once the 1075 // YUI loader is based on the ES6 loader which uses 1076 // loader.import(...).then(...) 1077 this.use.apply(this, args); 1078 }, 1079 1080 /** 1081 Handles Loader notifications about attachment/load errors. 1082 1083 @method _notify 1084 @param {Function} callback Callback to pass to `Y.config.loadErrorFn`. 1085 @param {Object} response Response returned from Loader. 1086 @param {Array} args Arguments passed from Loader. 1087 @private 1088 **/ 1089 _notify: function(callback, response, args) { 1090 if (!response.success && this.config.loadErrorFn) { 1091 this.config.loadErrorFn.call(this, this, callback, response, args); 1092 } else if (callback) { 1093 if (this.Env._missed && this.Env._missed.length) { 1094 response.msg = 'Missing modules: ' + this.Env._missed.join(); 1095 response.success = false; 1096 } 1097 if (this.config.throwFail) { 1098 callback(this, response); 1099 } else { 1100 try { 1101 callback(this, response); 1102 } catch (e) { 1103 this.error('use callback error', e, args); 1104 } 1105 } 1106 } 1107 }, 1108 1109 /** 1110 Called from the `use` method queue to ensure that only one set of loading 1111 logic is performed at a time. 1112 1113 @method _use 1114 @param {String} args* One or more modules to attach. 1115 @param {Function} [callback] Function to call once all required modules have 1116 been attached. 1117 @private 1118 **/ 1119 _use: function(args, callback) { 1120 1121 if (!this.Array) { 1122 this._attach(['yui-base']); 1123 } 1124 1125 var len, loader, handleBoot, 1126 Y = this, 1127 G_ENV = YUI.Env, 1128 mods = G_ENV.mods, 1129 Env = Y.Env, 1130 used = Env._used, 1131 aliases = G_ENV.aliases, 1132 queue = G_ENV._loaderQueue, 1133 firstArg = args[0], 1134 YArray = Y.Array, 1135 config = Y.config, 1136 boot = config.bootstrap, 1137 missing = [], 1138 i, 1139 r = [], 1140 ret = true, 1141 fetchCSS = config.fetchCSS, 1142 process = function(names, skip) { 1143 1144 var i = 0, a = [], name, len, m, req, use; 1145 1146 if (!names.length) { 1147 return; 1148 } 1149 1150 if (aliases) { 1151 len = names.length; 1152 for (i = 0; i < len; i++) { 1153 if (aliases[names[i]] && !mods[names[i]]) { 1154 a = [].concat(a, aliases[names[i]]); 1155 } else { 1156 a.push(names[i]); 1157 } 1158 } 1159 names = a; 1160 } 1161 1162 len = names.length; 1163 1164 for (i = 0; i < len; i++) { 1165 name = names[i]; 1166 if (!skip) { 1167 r.push(name); 1168 } 1169 1170 // only attach a module once 1171 if (used[name]) { 1172 continue; 1173 } 1174 1175 m = mods[name]; 1176 req = null; 1177 use = null; 1178 1179 if (m) { 1180 used[name] = true; 1181 req = m.details.requires; 1182 use = m.details.use; 1183 } else { 1184 // CSS files don't register themselves, see if it has 1185 // been loaded 1186 if (!G_ENV._loaded[VERSION][name]) { 1187 missing.push(name); 1188 } else { 1189 used[name] = true; // probably css 1190 } 1191 } 1192 1193 // make sure requirements are attached 1194 if (req && req.length) { 1195 process(req); 1196 } 1197 1198 // make sure we grab the submodule dependencies too 1199 if (use && use.length) { 1200 process(use, 1); 1201 } 1202 } 1203 1204 }, 1205 1206 handleLoader = function(fromLoader) { 1207 var response = fromLoader || { 1208 success: true, 1209 msg: 'not dynamic' 1210 }, 1211 redo, origMissing, 1212 ret = true, 1213 data = response.data; 1214 1215 Y._loading = false; 1216 1217 if (data) { 1218 origMissing = missing; 1219 missing = []; 1220 r = []; 1221 process(data); 1222 redo = missing.length; 1223 if (redo) { 1224 if ([].concat(missing).sort().join() == 1225 origMissing.sort().join()) { 1226 redo = false; 1227 } 1228 } 1229 } 1230 1231 if (redo && data) { 1232 Y._loading = true; 1233 Y._use(missing, function() { 1234 Y.log('Nested use callback: ' + data, 'info', 'yui'); 1235 if (Y._attach(data)) { 1236 Y._notify(callback, response, data); 1237 } 1238 }); 1239 } else { 1240 if (data) { 1241 // Y.log('attaching from loader: ' + data, 'info', 'yui'); 1242 ret = Y._attach(data); 1243 } 1244 if (ret) { 1245 Y._notify(callback, response, args); 1246 } 1247 } 1248 1249 if (Y._useQueue && Y._useQueue.size() && !Y._loading) { 1250 Y._use.apply(Y, Y._useQueue.next()); 1251 } 1252 1253 }; 1254 1255 // Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui'); 1256 1257 // YUI().use('*'); // bind everything available 1258 if (firstArg === '*') { 1259 args = []; 1260 for (i in mods) { 1261 if (mods.hasOwnProperty(i)) { 1262 args.push(i); 1263 } 1264 } 1265 ret = Y._attach(args); 1266 if (ret) { 1267 handleLoader(); 1268 } 1269 return Y; 1270 } 1271 1272 if ((mods.loader || mods['loader-base']) && !Y.Loader) { 1273 Y.log('Loader was found in meta, but it is not attached. Attaching..', 'info', 'yui'); 1274 Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]); 1275 } 1276 1277 // Y.log('before loader requirements: ' + args, 'info', 'yui'); 1278 1279 // use loader to expand dependencies and sort the 1280 // requirements if it is available. 1281 if (boot && Y.Loader && args.length) { 1282 Y.log('Using loader to expand dependencies', 'info', 'yui'); 1283 loader = getLoader(Y); 1284 loader.require(args); 1285 loader.ignoreRegistered = true; 1286 loader._boot = true; 1287 loader.calculate(null, (fetchCSS) ? null : 'js'); 1288 args = loader.sorted; 1289 loader._boot = false; 1290 } 1291 1292 process(args); 1293 1294 len = missing.length; 1295 1296 1297 if (len) { 1298 missing = YArray.dedupe(missing); 1299 len = missing.length; 1300 Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui'); 1301 } 1302 1303 1304 // dynamic load 1305 if (boot && len && Y.Loader) { 1306 // Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui'); 1307 Y.log('Using Loader', 'info', 'yui'); 1308 Y._loading = true; 1309 loader = getLoader(Y); 1310 loader.onEnd = handleLoader; 1311 loader.context = Y; 1312 loader.data = args; 1313 loader.ignoreRegistered = false; 1314 loader.require(missing); 1315 loader.insert(null, (fetchCSS) ? null : 'js'); 1316 1317 } else if (boot && len && Y.Get && !Env.bootstrapped) { 1318 1319 Y._loading = true; 1320 1321 handleBoot = function() { 1322 Y._loading = false; 1323 queue.running = false; 1324 Env.bootstrapped = true; 1325 G_ENV._bootstrapping = false; 1326 if (Y._attach(['loader'])) { 1327 Y._use(args, callback); 1328 } 1329 }; 1330 1331 if (G_ENV._bootstrapping) { 1332 Y.log('Waiting for loader', 'info', 'yui'); 1333 queue.add(handleBoot); 1334 } else { 1335 G_ENV._bootstrapping = true; 1336 Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui'); 1337 Y.Get.script(config.base + config.loaderPath, { 1338 onEnd: handleBoot 1339 }); 1340 } 1341 1342 } else { 1343 Y.log('Attaching available dependencies: ' + args, 'info', 'yui'); 1344 ret = Y._attach(args); 1345 if (ret) { 1346 handleLoader(); 1347 } 1348 } 1349 1350 return Y; 1351 }, 1352 1353 1354 /** 1355 Utility method for safely creating namespaces if they don't already exist. 1356 May be called statically on the YUI global object or as a method on a YUI 1357 instance. 1358 1359 When called statically, a namespace will be created on the YUI global 1360 object: 1361 1362 // Create `YUI.your.namespace.here` as nested objects, preserving any 1363 // objects that already exist instead of overwriting them. 1364 YUI.namespace('your.namespace.here'); 1365 1366 When called as a method on a YUI instance, a namespace will be created on 1367 that instance: 1368 1369 // Creates `Y.property.package`. 1370 Y.namespace('property.package'); 1371 1372 Dots in the input string cause `namespace` to create nested objects for each 1373 token. If any part of the requested namespace already exists, the current 1374 object will be left in place and will not be overwritten. This allows 1375 multiple calls to `namespace` to preserve existing namespaced properties. 1376 1377 If the first token in the namespace string is "YAHOO", that token is 1378 discarded. This is legacy behavior for backwards compatibility with YUI 2. 1379 1380 Be careful with namespace tokens. Reserved words may work in some browsers 1381 and not others. For instance, the following will fail in some browsers 1382 because the supported version of JavaScript reserves the word "long": 1383 1384 Y.namespace('really.long.nested.namespace'); 1385 1386 Note: If you pass multiple arguments to create multiple namespaces, only the 1387 last one created is returned from this function. 1388 1389 @method namespace 1390 @param {String} namespace* One or more namespaces to create. 1391 @return {Object} Reference to the last namespace object created. 1392 **/ 1393 namespace: function() { 1394 var a = arguments, o, i = 0, j, d, arg; 1395 1396 for (; i < a.length; i++) { 1397 o = this; //Reset base object per argument or it will get reused from the last 1398 arg = a[i]; 1399 if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present 1400 d = arg.split(PERIOD); 1401 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) { 1402 o[d[j]] = o[d[j]] || {}; 1403 o = o[d[j]]; 1404 } 1405 } else { 1406 o[arg] = o[arg] || {}; 1407 o = o[arg]; //Reset base object to the new object so it's returned 1408 } 1409 } 1410 return o; 1411 }, 1412 1413 // this is replaced if the log module is included 1414 log: NOOP, 1415 message: NOOP, 1416 // this is replaced if the dump module is included 1417 dump: function (o) { return ''+o; }, 1418 1419 /** 1420 Reports an error. 1421 1422 The reporting mechanism is controlled by the `throwFail` configuration 1423 attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is 1424 truthy, a JS exception is thrown. 1425 1426 If an `errorFn` is specified in the config it must return `true` to indicate 1427 that the exception was handled and keep it from being thrown. 1428 1429 @method error 1430 @param {String} msg Error message. 1431 @param {Error|String} [e] JavaScript error object or an error string. 1432 @param {String} [src] Source of the error (such as the name of the module in 1433 which the error occurred). 1434 @chainable 1435 **/ 1436 error: function(msg, e, src) { 1437 //TODO Add check for window.onerror here 1438 1439 var Y = this, ret; 1440 1441 if (Y.config.errorFn) { 1442 ret = Y.config.errorFn.apply(Y, arguments); 1443 } 1444 1445 if (!ret) { 1446 throw (e || new Error(msg)); 1447 } else { 1448 Y.message(msg, 'error', ''+src); // don't scrub this one 1449 } 1450 1451 return Y; 1452 }, 1453 1454 /** 1455 Generates an id string that is unique among all YUI instances in this 1456 execution context. 1457 1458 @method guid 1459 @param {String} [pre] Prefix. 1460 @return {String} Unique id. 1461 **/ 1462 guid: function(pre) { 1463 var id = this.Env._guidp + '_' + (++this.Env._uidx); 1464 return (pre) ? (pre + id) : id; 1465 }, 1466 1467 /** 1468 Returns a unique id associated with the given object and (if *readOnly* is 1469 falsy) stamps the object with that id so it can be identified in the future. 1470 1471 Stamping an object involves adding a `_yuid` property to it that contains 1472 the object's id. One exception to this is that in Internet Explorer, DOM 1473 nodes have a `uniqueID` property that contains a browser-generated unique 1474 id, which will be used instead of a YUI-generated id when available. 1475 1476 @method stamp 1477 @param {Object} o Object to stamp. 1478 @param {Boolean} readOnly If truthy and the given object has not already 1479 been stamped, the object will not be modified and `null` will be 1480 returned. 1481 @return {String} Object's unique id, or `null` if *readOnly* was truthy and 1482 the given object was not already stamped. 1483 **/ 1484 stamp: function(o, readOnly) { 1485 var uid; 1486 if (!o) { 1487 return o; 1488 } 1489 1490 // IE generates its own unique ID for dom nodes 1491 // The uniqueID property of a document node returns a new ID 1492 if (o.uniqueID && o.nodeType && o.nodeType !== 9) { 1493 uid = o.uniqueID; 1494 } else { 1495 uid = (typeof o === 'string') ? o : o._yuid; 1496 } 1497 1498 if (!uid) { 1499 uid = this.guid(); 1500 if (!readOnly) { 1501 try { 1502 o._yuid = uid; 1503 } catch (e) { 1504 uid = null; 1505 } 1506 } 1507 } 1508 return uid; 1509 }, 1510 1511 /** 1512 Destroys this YUI instance. 1513 1514 @method destroy 1515 @since 3.3.0 1516 **/ 1517 destroy: function() { 1518 var Y = this; 1519 if (Y.Event) { 1520 Y.Event._unload(); 1521 } 1522 delete instances[Y.id]; 1523 delete Y.Env; 1524 delete Y.config; 1525 } 1526 1527 /** 1528 Safe `instanceof` wrapper that works around a memory leak in IE when the 1529 object being tested is `window` or `document`. 1530 1531 Unless you are testing objects that may be `window` or `document`, you 1532 should use the native `instanceof` operator instead of this method. 1533 1534 @method instanceOf 1535 @param {Object} o Object to check. 1536 @param {Object} type Class to check against. 1537 @since 3.3.0 1538 **/ 1539 }; 1540 1541 YUI.prototype = proto; 1542 1543 // inheritance utilities are not available yet 1544 for (prop in proto) { 1545 if (proto.hasOwnProperty(prop)) { 1546 YUI[prop] = proto[prop]; 1547 } 1548 } 1549 1550 /** 1551 Applies a configuration to all YUI instances in this execution context. 1552 1553 The main use case for this method is in "mashups" where several third-party 1554 scripts need to write to a global YUI config, but cannot share a single 1555 centrally-managed config object. This way they can all call 1556 `YUI.applyConfig({})` instead of overwriting the single global config. 1557 1558 @example 1559 1560 YUI.applyConfig({ 1561 modules: { 1562 davglass: { 1563 fullpath: './davglass.js' 1564 } 1565 } 1566 }); 1567 1568 YUI.applyConfig({ 1569 modules: { 1570 foo: { 1571 fullpath: './foo.js' 1572 } 1573 } 1574 }); 1575 1576 YUI().use('davglass', function (Y) { 1577 // Module davglass will be available here. 1578 }); 1579 1580 @method applyConfig 1581 @param {Object} o Configuration object to apply. 1582 @static 1583 @since 3.5.0 1584 **/ 1585 YUI.applyConfig = function(o) { 1586 if (!o) { 1587 return; 1588 } 1589 //If there is a GlobalConfig, apply it first to set the defaults 1590 if (YUI.GlobalConfig) { 1591 this.prototype.applyConfig.call(this, YUI.GlobalConfig); 1592 } 1593 //Apply this config to it 1594 this.prototype.applyConfig.call(this, o); 1595 //Reset GlobalConfig to the combined config 1596 YUI.GlobalConfig = this.config; 1597 }; 1598 1599 // set up the environment 1600 YUI._init(); 1601 1602 if (hasWin) { 1603 add(doc, 'DOMContentLoaded', handleReady); 1604 1605 // add a window load event at load time so we can capture 1606 // the case where it fires before dynamic loading is 1607 // complete. 1608 add(window, 'load', handleLoad); 1609 } else { 1610 handleReady(); 1611 handleLoad(); 1612 } 1613 1614 YUI.Env.add = add; 1615 YUI.Env.remove = remove; 1616 1617 /*global exports*/ 1618 // Support the CommonJS method for exporting our single global 1619 if (typeof exports == 'object') { 1620 exports.YUI = YUI; 1621 /** 1622 * Set a method to be called when `Get.script` is called in Node.js 1623 * `Get` will open the file, then pass it's content and it's path 1624 * to this method before attaching it. Commonly used for code coverage 1625 * instrumentation. <strong>Calling this multiple times will only 1626 * attach the last hook method</strong>. This method is only 1627 * available in Node.js. 1628 * @method setLoadHook 1629 * @static 1630 * @param {Function} fn The function to set 1631 * @param {String} fn.data The content of the file 1632 * @param {String} fn.path The file path of the file 1633 */ 1634 YUI.setLoadHook = function(fn) { 1635 YUI._getLoadHook = fn; 1636 }; 1637 /** 1638 * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook` 1639 * @method _getLoadHook 1640 * @private 1641 * @param {String} data The content of the file 1642 * @param {String} path The file path of the file 1643 */ 1644 YUI._getLoadHook = null; 1645 } 1646 1647 YUI.Env[VERSION] = {}; 1648 }()); 1649 1650 1651 /** 1652 Config object that contains all of the configuration options for 1653 this `YUI` instance. 1654 1655 This object is supplied by the implementer when instantiating YUI. Some 1656 properties have default values if they are not supplied by the implementer. 1657 1658 This object should not be updated directly because some values are cached. Use 1659 `applyConfig()` to update the config object on a YUI instance that has already 1660 been configured. 1661 1662 @class config 1663 @static 1664 **/ 1665 1666 /** 1667 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata 1668 if they're needed to load additional dependencies and aren't already available. 1669 1670 Setting this to `false` will prevent YUI from automatically loading the Loader 1671 and module metadata, so you will need to manually ensure that they're available 1672 or handle dependency resolution yourself. 1673 1674 @property {Boolean} bootstrap 1675 @default true 1676 **/ 1677 1678 /** 1679 If `true`, `Y.log()` messages will be written to the browser's debug console 1680 when available and when `useBrowserConsole` is also `true`. 1681 1682 @property {Boolean} debug 1683 @default true 1684 **/ 1685 1686 /** 1687 Log messages to the browser console if `debug` is `true` and the browser has a 1688 supported console. 1689 1690 @property {Boolean} useBrowserConsole 1691 @default true 1692 **/ 1693 1694 /** 1695 A hash of log sources that should be logged. If specified, only messages from 1696 these sources will be logged. Others will be discarded. 1697 1698 @property {Object} logInclude 1699 @type object 1700 **/ 1701 1702 /** 1703 A hash of log sources that should be not be logged. If specified, all sources 1704 will be logged *except* those on this list. 1705 1706 @property {Object} logExclude 1707 **/ 1708 1709 /** 1710 When the YUI seed file is dynamically loaded after the `window.onload` event has 1711 fired, set this to `true` to tell YUI that it shouldn't wait for `window.onload` 1712 to occur. 1713 1714 This ensures that components that rely on `window.onload` and the `domready` 1715 custom event will work as expected even when YUI is dynamically injected. 1716 1717 @property {Boolean} injected 1718 @default false 1719 **/ 1720 1721 /** 1722 If `true`, `Y.error()` will generate or re-throw a JavaScript error. Otherwise, 1723 errors are merely logged silently. 1724 1725 @property {Boolean} throwFail 1726 @default true 1727 **/ 1728 1729 /** 1730 Reference to the global object for this execution context. 1731 1732 In a browser, this is the current `window` object. In Node.js, this is the 1733 Node.js `global` object. 1734 1735 @property {Object} global 1736 **/ 1737 1738 /** 1739 The browser window or frame that this YUI instance should operate in. 1740 1741 When running in Node.js, this property is `undefined`, since there is no 1742 `window` object. Use `global` to get a reference to the global object that will 1743 work in both browsers and Node.js. 1744 1745 @property {Window} win 1746 **/ 1747 1748 /** 1749 The browser `document` object associated with this YUI instance's `win` object. 1750 1751 When running in Node.js, this property is `undefined`, since there is no 1752 `document` object. 1753 1754 @property {Document} doc 1755 **/ 1756 1757 /** 1758 A list of modules that defines the YUI core (overrides the default list). 1759 1760 @property {Array} core 1761 @type Array 1762 @default ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3'] 1763 **/ 1764 1765 /** 1766 A list of languages to use in order of preference. 1767 1768 This list is matched against the list of available languages in modules that the 1769 YUI instance uses to determine the best possible localization of language 1770 sensitive modules. 1771 1772 Languages are represented using BCP 47 language tags, such as "en-GB" for 1773 English as used in the United Kingdom, or "zh-Hans-CN" for simplified Chinese as 1774 used in China. The list may be provided as a comma-separated string or as an 1775 array. 1776 1777 @property {String|String[]} lang 1778 **/ 1779 1780 /** 1781 Default date format. 1782 1783 @property {String} dateFormat 1784 @deprecated Use configuration in `DataType.Date.format()` instead. 1785 **/ 1786 1787 /** 1788 Default locale. 1789 1790 @property {String} locale 1791 @deprecated Use `config.lang` instead. 1792 **/ 1793 1794 /** 1795 Default generic polling interval in milliseconds. 1796 1797 @property {Number} pollInterval 1798 @default 20 1799 **/ 1800 1801 /** 1802 The number of dynamic `<script>` nodes to insert by default before automatically 1803 removing them when loading scripts. 1804 1805 This applies only to script nodes because removing the node will not make the 1806 evaluated script unavailable. Dynamic CSS nodes are not auto purged, because 1807 removing a linked style sheet will also remove the style definitions. 1808 1809 @property {Number} purgethreshold 1810 @default 20 1811 **/ 1812 1813 /** 1814 Delay in milliseconds to wait after a window `resize` event before firing the 1815 event. If another `resize` event occurs before this delay has elapsed, the 1816 delay will start over to ensure that `resize` events are throttled. 1817 1818 @property {Number} windowResizeDelay 1819 @default 40 1820 **/ 1821 1822 /** 1823 Base directory for dynamic loading. 1824 1825 @property {String} base 1826 **/ 1827 1828 /** 1829 Base URL for a dynamic combo handler. This will be used to make combo-handled 1830 module requests if `combine` is set to `true. 1831 1832 @property {String} comboBase 1833 @default "http://yui.yahooapis.com/combo?" 1834 **/ 1835 1836 /** 1837 Root path to prepend to each module path when creating a combo-handled request. 1838 1839 This is updated for each YUI release to point to a specific version of the 1840 library; for example: "3.8.0/build/". 1841 1842 @property {String} root 1843 **/ 1844 1845 /** 1846 Filter to apply to module urls. This filter will modify the default path for all 1847 modules. 1848 1849 The default path for the YUI library is the minified version of the files (e.g., 1850 event-min.js). The filter property can be a predefined filter or a custom 1851 filter. The valid predefined filters are: 1852 1853 - **debug**: Loads debug versions of modules (e.g., event-debug.js). 1854 - **raw**: Loads raw, non-minified versions of modules without debug logging 1855 (e.g., event.js). 1856 1857 You can also define a custom filter, which must be an object literal containing 1858 a search regular expression and a replacement string: 1859 1860 myFilter: { 1861 searchExp : "-min\\.js", 1862 replaceStr: "-debug.js" 1863 } 1864 1865 @property {Object|String} filter 1866 **/ 1867 1868 /** 1869 Skin configuration and customizations. 1870 1871 @property {Object} skin 1872 @param {String} [skin.defaultSkin='sam'] Default skin name. This skin will be 1873 applied automatically to skinnable components if not overridden by a 1874 component-specific skin name. 1875 @param {String} [skin.base='assets/skins/'] Default base path for a skin, 1876 relative to Loader's `base` path. 1877 @param {Object} [skin.overrides] Component-specific skin name overrides. Specify 1878 a component name as the key and, as the value, a string or array of strings 1879 for a skin or skins that should be loaded for that component instead of the 1880 `defaultSkin`. 1881 **/ 1882 1883 /** 1884 Hash of per-component filter specifications. If specified for a given component, 1885 this overrides the global `filter` config. 1886 1887 @example 1888 YUI({ 1889 modules: { 1890 'foo': './foo.js', 1891 'bar': './bar.js', 1892 'baz': './baz.js' 1893 }, 1894 filters: { 1895 'foo': { 1896 searchExp: '.js', 1897 replaceStr: '-coverage.js' 1898 } 1899 } 1900 }).use('foo', 'bar', 'baz', function (Y) { 1901 // foo-coverage.js is loaded 1902 // bar.js is loaded 1903 // baz.js is loaded 1904 }); 1905 1906 @property {Object} filters 1907 **/ 1908 1909 /** 1910 If `true`, YUI will use a combo handler to load multiple modules in as few 1911 requests as possible. 1912 1913 The YUI CDN (which YUI uses by default) supports combo handling, but other 1914 servers may not. If the server from which you're loading YUI does not support 1915 combo handling, set this to `false`. 1916 1917 Providing a value for the `base` config property will cause `combine` to default 1918 to `false` instead of `true`. 1919 1920 @property {Boolean} combine 1921 @default true 1922 */ 1923 1924 /** 1925 Array of module names that should never be dynamically loaded. 1926 1927 @property {String[]} ignore 1928 **/ 1929 1930 /** 1931 Array of module names that should always be loaded when required, even if 1932 already present on the page. 1933 1934 @property {String[]} force 1935 **/ 1936 1937 /** 1938 DOM element or id that should be used as the insertion point for dynamically 1939 added `<script>` and `<link>` nodes. 1940 1941 @property {HTMLElement|String} insertBefore 1942 **/ 1943 1944 /** 1945 Object hash containing attributes to add to dynamically added `<script>` nodes. 1946 1947 @property {Object} jsAttributes 1948 **/ 1949 1950 /** 1951 Object hash containing attributes to add to dynamically added `<link>` nodes. 1952 1953 @property {Object} cssAttributes 1954 **/ 1955 1956 /** 1957 Timeout in milliseconds before a dynamic JS or CSS request will be considered a 1958 failure. If not set, no timeout will be enforced. 1959 1960 @property {Number} timeout 1961 **/ 1962 1963 /** 1964 A hash of module definitions to add to the list of available YUI modules. These 1965 modules can then be dynamically loaded via the `use()` method. 1966 1967 This is a hash in which keys are module names and values are objects containing 1968 module metadata. 1969 1970 See `Loader.addModule()` for the supported module metadata fields. Also see 1971 `groups`, which provides a way to configure the base and combo spec for a set of 1972 modules. 1973 1974 @example 1975 1976 modules: { 1977 mymod1: { 1978 requires: ['node'], 1979 fullpath: '/mymod1/mymod1.js' 1980 }, 1981 1982 mymod2: { 1983 requires: ['mymod1'], 1984 fullpath: '/mymod2/mymod2.js' 1985 }, 1986 1987 mymod3: '/js/mymod3.js', 1988 mycssmod: '/css/mycssmod.css' 1989 } 1990 1991 @property {Object} modules 1992 **/ 1993 1994 /** 1995 Aliases are dynamic groups of modules that can be used as shortcuts. 1996 1997 @example 1998 1999 YUI({ 2000 aliases: { 2001 davglass: [ 'node', 'yql', 'dd' ], 2002 mine: [ 'davglass', 'autocomplete'] 2003 } 2004 }).use('mine', function (Y) { 2005 // Node, YQL, DD & AutoComplete available here. 2006 }); 2007 2008 @property {Object} aliases 2009 **/ 2010 2011 /** 2012 A hash of module group definitions. 2013 2014 For each group you can specify a list of modules and the base path and 2015 combo spec to use when dynamically loading the modules. 2016 2017 @example 2018 2019 groups: { 2020 yui2: { 2021 // specify whether or not this group has a combo service 2022 combine: true, 2023 2024 // The comboSeperator to use with this group's combo handler 2025 comboSep: ';', 2026 2027 // The maxURLLength for this server 2028 maxURLLength: 500, 2029 2030 // the base path for non-combo paths 2031 base: 'http://yui.yahooapis.com/2.8.0r4/build/', 2032 2033 // the path to the combo service 2034 comboBase: 'http://yui.yahooapis.com/combo?', 2035 2036 // a fragment to prepend to the path attribute when 2037 // when building combo urls 2038 root: '2.8.0r4/build/', 2039 2040 // the module definitions 2041 modules: { 2042 yui2_yde: { 2043 path: "yahoo-dom-event/yahoo-dom-event.js" 2044 }, 2045 yui2_anim: { 2046 path: "animation/animation.js", 2047 requires: ['yui2_yde'] 2048 } 2049 } 2050 } 2051 } 2052 2053 @property {Object} groups 2054 **/ 2055 2056 /** 2057 Path to the Loader JS file, relative to the `base` path. 2058 2059 This is used to dynamically bootstrap the Loader when it's needed and isn't yet 2060 available. 2061 2062 @property {String} loaderPath 2063 @default "loader/loader-min.js" 2064 **/ 2065 2066 /** 2067 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to 2068 `false` to prevent YUI from loading any CSS, or set it to the string `"force"` 2069 to force CSS dependencies to be loaded even if their associated JS modules are 2070 already loaded. 2071 2072 @property {Boolean|String} fetchCSS 2073 @default true 2074 **/ 2075 2076 /** 2077 Default gallery version used to build gallery module urls. 2078 2079 @property {String} gallery 2080 @since 3.1.0 2081 **/ 2082 2083 /** 2084 Default YUI 2 version used to build YUI 2 module urls. 2085 2086 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the 2087 `2in3` config for pulling different revisions of the wrapped YUI 2 modules. 2088 2089 @property {String} yui2 2090 @default "2.9.0" 2091 @since 3.1.0 2092 **/ 2093 2094 /** 2095 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3. 2096 2097 @property {String} 2in3 2098 @default "4" 2099 @since 3.1.0 2100 **/ 2101 2102 /** 2103 Alternate console log function that should be used in environments without a 2104 supported native console. This function is executed with the YUI instance as its 2105 `this` object. 2106 2107 @property {Function} logFn 2108 @since 3.1.0 2109 **/ 2110 2111 /** 2112 The minimum log level to log messages for. Log levels are defined 2113 incrementally. Messages greater than or equal to the level specified will 2114 be shown. All others will be discarded. The order of log levels in 2115 increasing priority is: 2116 2117 debug 2118 info 2119 warn 2120 error 2121 2122 @property {String} logLevel 2123 @default 'debug' 2124 @since 3.10.0 2125 **/ 2126 2127 /** 2128 Callback to execute when `Y.error()` is called. It receives the error message 2129 and a JavaScript error object if one was provided. 2130 2131 This function is executed with the YUI instance as its `this` object. 2132 2133 Returning `true` from this function will prevent an exception from being thrown. 2134 2135 @property {Function} errorFn 2136 @param {String} errorFn.msg Error message 2137 @param {Object} [errorFn.err] Error object (if one was provided). 2138 @since 3.2.0 2139 **/ 2140 2141 /** 2142 A callback to execute when Loader fails to load one or more resources. 2143 2144 This could be because of a script load failure. It could also be because a 2145 module fails to register itself when the `requireRegistration` config is `true`. 2146 2147 If this function is defined, the `use()` callback will only be called when the 2148 loader succeeds. Otherwise, `use()` will always executes unless there was a 2149 JavaScript error when attaching a module. 2150 2151 @property {Function} loadErrorFn 2152 @since 3.3.0 2153 **/ 2154 2155 /** 2156 If `true`, Loader will expect all loaded scripts to be first-class YUI modules 2157 that register themselves with the YUI global, and will trigger a failure if a 2158 loaded script does not register a YUI module. 2159 2160 @property {Boolean} requireRegistration 2161 @default false 2162 @since 3.3.0 2163 **/ 2164 2165 /** 2166 Cache serviced use() requests. 2167 2168 @property {Boolean} cacheUse 2169 @default true 2170 @since 3.3.0 2171 @deprecated No longer used. 2172 **/ 2173 2174 /** 2175 Whether or not YUI should use native ES5 functionality when available for 2176 features like `Y.Array.each()`, `Y.Object()`, etc. 2177 2178 When `false`, YUI will always use its own fallback implementations instead of 2179 relying on ES5 functionality, even when ES5 functionality is available. 2180 2181 @property {Boolean} useNativeES5 2182 @default true 2183 @since 3.5.0 2184 **/ 2185 2186 /** 2187 * Leverage native JSON stringify if the browser has a native 2188 * implementation. In general, this is a good idea. See the Known Issues 2189 * section in the JSON user guide for caveats. The default value is true 2190 * for browsers with native JSON support. 2191 * 2192 * @property useNativeJSONStringify 2193 * @type Boolean 2194 * @default true 2195 * @since 3.8.0 2196 */ 2197 2198 /** 2199 * Leverage native JSON parse if the browser has a native implementation. 2200 * In general, this is a good idea. See the Known Issues section in the 2201 * JSON user guide for caveats. The default value is true for browsers with 2202 * native JSON support. 2203 * 2204 * @property useNativeJSONParse 2205 * @type Boolean 2206 * @default true 2207 * @since 3.8.0 2208 */ 2209 2210 /** 2211 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`) 2212 2213 @property {Object|String} delayUntil 2214 @since 3.6.0 2215 @example 2216 2217 You can use `load` or `domready` strings by default: 2218 2219 YUI({ 2220 delayUntil: 'domready' 2221 }, function (Y) { 2222 // This will not execute until 'domeready' occurs. 2223 }); 2224 2225 Or you can delay until a node is available (with `available` or `contentready`): 2226 2227 YUI({ 2228 delayUntil: { 2229 event: 'available', 2230 args : '#foo' 2231 } 2232 }, function (Y) { 2233 // This will not execute until a node matching the selector "#foo" is 2234 // available in the DOM. 2235 }); 2236 2237 **/ 2238 YUI.add('yui-base', function (Y, NAME) { 2239 2240 /* 2241 * YUI stub 2242 * @module yui 2243 * @submodule yui-base 2244 */ 2245 /** 2246 * The YUI module contains the components required for building the YUI 2247 * seed file. This includes the script loading mechanism, a simple queue, 2248 * and the core utilities for the library. 2249 * @module yui 2250 * @submodule yui-base 2251 */ 2252 2253 /** 2254 * Provides core language utilites and extensions used throughout YUI. 2255 * 2256 * @class Lang 2257 * @static 2258 */ 2259 2260 var L = Y.Lang || (Y.Lang = {}), 2261 2262 STRING_PROTO = String.prototype, 2263 TOSTRING = Object.prototype.toString, 2264 2265 TYPES = { 2266 'undefined' : 'undefined', 2267 'number' : 'number', 2268 'boolean' : 'boolean', 2269 'string' : 'string', 2270 '[object Function]': 'function', 2271 '[object RegExp]' : 'regexp', 2272 '[object Array]' : 'array', 2273 '[object Date]' : 'date', 2274 '[object Error]' : 'error' 2275 }, 2276 2277 SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g, 2278 2279 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", 2280 WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+", 2281 TRIM_LEFT_REGEX = new RegExp("^" + WHITESPACE_CLASS), 2282 TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"), 2283 TRIMREGEX = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"), 2284 2285 NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i; 2286 2287 // -- Protected Methods -------------------------------------------------------- 2288 2289 /** 2290 Returns `true` if the given function appears to be implemented in native code, 2291 `false` otherwise. Will always return `false` -- even in ES5-capable browsers -- 2292 if the `useNativeES5` YUI config option is set to `false`. 2293 2294 This isn't guaranteed to be 100% accurate and won't work for anything other than 2295 functions, but it can be useful for determining whether a function like 2296 `Array.prototype.forEach` is native or a JS shim provided by another library. 2297 2298 There's a great article by @kangax discussing certain flaws with this technique: 2299 <http://perfectionkills.com/detecting-built-in-host-methods/> 2300 2301 While his points are valid, it's still possible to benefit from this function 2302 as long as it's used carefully and sparingly, and in such a way that false 2303 negatives have minimal consequences. It's used internally to avoid using 2304 potentially broken non-native ES5 shims that have been added to the page by 2305 other libraries. 2306 2307 @method _isNative 2308 @param {Function} fn Function to test. 2309 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise. 2310 @static 2311 @protected 2312 @since 3.5.0 2313 **/ 2314 L._isNative = function (fn) { 2315 return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn)); 2316 }; 2317 2318 // -- Public Methods ----------------------------------------------------------- 2319 2320 /** 2321 * Determines whether or not the provided item is an array. 2322 * 2323 * Returns `false` for array-like collections such as the function `arguments` 2324 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to 2325 * test for an array-like collection. 2326 * 2327 * @method isArray 2328 * @param o The object to test. 2329 * @return {boolean} true if o is an array. 2330 * @static 2331 */ 2332 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) { 2333 return L.type(o) === 'array'; 2334 }; 2335 2336 /** 2337 * Determines whether or not the provided item is a boolean. 2338 * @method isBoolean 2339 * @static 2340 * @param o The object to test. 2341 * @return {boolean} true if o is a boolean. 2342 */ 2343 L.isBoolean = function(o) { 2344 return typeof o === 'boolean'; 2345 }; 2346 2347 /** 2348 * Determines whether or not the supplied item is a date instance. 2349 * @method isDate 2350 * @static 2351 * @param o The object to test. 2352 * @return {boolean} true if o is a date. 2353 */ 2354 L.isDate = function(o) { 2355 return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o); 2356 }; 2357 2358 /** 2359 * <p> 2360 * Determines whether or not the provided item is a function. 2361 * Note: Internet Explorer thinks certain functions are objects: 2362 * </p> 2363 * 2364 * <pre> 2365 * var obj = document.createElement("object"); 2366 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE 2367 * 2368 * var input = document.createElement("input"); // append to body 2369 * Y.Lang.isFunction(input.focus) // reports false in IE 2370 * </pre> 2371 * 2372 * <p> 2373 * You will have to implement additional tests if these functions 2374 * matter to you. 2375 * </p> 2376 * 2377 * @method isFunction 2378 * @static 2379 * @param o The object to test. 2380 * @return {boolean} true if o is a function. 2381 */ 2382 L.isFunction = function(o) { 2383 return L.type(o) === 'function'; 2384 }; 2385 2386 /** 2387 * Determines whether or not the provided item is null. 2388 * @method isNull 2389 * @static 2390 * @param o The object to test. 2391 * @return {boolean} true if o is null. 2392 */ 2393 L.isNull = function(o) { 2394 return o === null; 2395 }; 2396 2397 /** 2398 * Determines whether or not the provided item is a legal number. 2399 * @method isNumber 2400 * @static 2401 * @param o The object to test. 2402 * @return {boolean} true if o is a number. 2403 */ 2404 L.isNumber = function(o) { 2405 return typeof o === 'number' && isFinite(o); 2406 }; 2407 2408 /** 2409 * Determines whether or not the provided item is of type object 2410 * or function. Note that arrays are also objects, so 2411 * <code>Y.Lang.isObject([]) === true</code>. 2412 * @method isObject 2413 * @static 2414 * @param o The object to test. 2415 * @param failfn {boolean} fail if the input is a function. 2416 * @return {boolean} true if o is an object. 2417 * @see isPlainObject 2418 */ 2419 L.isObject = function(o, failfn) { 2420 var t = typeof o; 2421 return (o && (t === 'object' || 2422 (!failfn && (t === 'function' || L.isFunction(o))))) || false; 2423 }; 2424 2425 /** 2426 * Determines whether or not the provided value is a regexp. 2427 * @method isRegExp 2428 * @static 2429 * @param value The value or object to test. 2430 * @return {boolean} true if value is a regexp. 2431 */ 2432 L.isRegExp = function(value) { 2433 return L.type(value) === 'regexp'; 2434 }; 2435 2436 /** 2437 * Determines whether or not the provided item is a string. 2438 * @method isString 2439 * @static 2440 * @param o The object to test. 2441 * @return {boolean} true if o is a string. 2442 */ 2443 L.isString = function(o) { 2444 return typeof o === 'string'; 2445 }; 2446 2447 /** 2448 * Determines whether or not the provided item is undefined. 2449 * @method isUndefined 2450 * @static 2451 * @param o The object to test. 2452 * @return {boolean} true if o is undefined. 2453 */ 2454 L.isUndefined = function(o) { 2455 return typeof o === 'undefined'; 2456 }; 2457 2458 /** 2459 * A convenience method for detecting a legitimate non-null value. 2460 * Returns false for null/undefined/NaN, true for other values, 2461 * including 0/false/'' 2462 * @method isValue 2463 * @static 2464 * @param o The item to test. 2465 * @return {boolean} true if it is not null/undefined/NaN || false. 2466 */ 2467 L.isValue = function(o) { 2468 var t = L.type(o); 2469 2470 switch (t) { 2471 case 'number': 2472 return isFinite(o); 2473 2474 case 'null': // fallthru 2475 case 'undefined': 2476 return false; 2477 2478 default: 2479 return !!t; 2480 } 2481 }; 2482 2483 /** 2484 * Returns the current time in milliseconds. 2485 * 2486 * @method now 2487 * @return {Number} Current time in milliseconds. 2488 * @static 2489 * @since 3.3.0 2490 */ 2491 L.now = Date.now || function () { 2492 return new Date().getTime(); 2493 }; 2494 2495 /** 2496 * Performs `{placeholder}` substitution on a string. The object passed as the 2497 * second parameter provides values to replace the `{placeholder}`s. 2498 * `{placeholder}` token names must match property names of the object. For example, 2499 * 2500 *`var greeting = Y.Lang.sub("Hello, {who}!", { who: "World" });` 2501 * 2502 * `{placeholder}` tokens that are undefined on the object map will be left 2503 * in tact (leaving unsightly `{placeholder}`'s in the output string). 2504 * 2505 * @method sub 2506 * @param {string} s String to be modified. 2507 * @param {object} o Object containing replacement values. 2508 * @return {string} the substitute result. 2509 * @static 2510 * @since 3.2.0 2511 */ 2512 L.sub = function(s, o) { 2513 return s.replace ? s.replace(SUBREGEX, function (match, key) { 2514 return L.isUndefined(o[key]) ? match : o[key]; 2515 }) : s; 2516 }; 2517 2518 /** 2519 * Returns a string without any leading or trailing whitespace. If 2520 * the input is not a string, the input will be returned untouched. 2521 * @method trim 2522 * @static 2523 * @param s {string} the string to trim. 2524 * @return {string} the trimmed string. 2525 */ 2526 L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) { 2527 return s && s.trim ? s.trim() : s; 2528 } : function (s) { 2529 try { 2530 return s.replace(TRIMREGEX, ''); 2531 } catch (e) { 2532 return s; 2533 } 2534 }; 2535 2536 /** 2537 * Returns a string without any leading whitespace. 2538 * @method trimLeft 2539 * @static 2540 * @param s {string} the string to trim. 2541 * @return {string} the trimmed string. 2542 */ 2543 L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) { 2544 return s.trimLeft(); 2545 } : function (s) { 2546 return s.replace(TRIM_LEFT_REGEX, ''); 2547 }; 2548 2549 /** 2550 * Returns a string without any trailing whitespace. 2551 * @method trimRight 2552 * @static 2553 * @param s {string} the string to trim. 2554 * @return {string} the trimmed string. 2555 */ 2556 L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) { 2557 return s.trimRight(); 2558 } : function (s) { 2559 return s.replace(TRIM_RIGHT_REGEX, ''); 2560 }; 2561 2562 /** 2563 Returns one of the following strings, representing the type of the item passed 2564 in: 2565 2566 * "array" 2567 * "boolean" 2568 * "date" 2569 * "error" 2570 * "function" 2571 * "null" 2572 * "number" 2573 * "object" 2574 * "regexp" 2575 * "string" 2576 * "undefined" 2577 2578 Known issues: 2579 2580 * `typeof HTMLElementCollection` returns function in Safari, but 2581 `Y.Lang.type()` reports "object", which could be a good thing -- 2582 but it actually caused the logic in <code>Y.Lang.isObject</code> to fail. 2583 2584 @method type 2585 @param o the item to test. 2586 @return {string} the detected type. 2587 @static 2588 **/ 2589 L.type = function(o) { 2590 return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null'); 2591 }; 2592 /** 2593 @module yui 2594 @submodule yui-base 2595 */ 2596 2597 var Lang = Y.Lang, 2598 Native = Array.prototype, 2599 2600 hasOwn = Object.prototype.hasOwnProperty; 2601 2602 /** 2603 Provides utility methods for working with arrays. Additional array helpers can 2604 be found in the `collection` and `array-extras` modules. 2605 2606 `Y.Array(thing)` returns a native array created from _thing_. Depending on 2607 _thing_'s type, one of the following will happen: 2608 2609 * Arrays are returned unmodified unless a non-zero _startIndex_ is 2610 specified. 2611 * Array-like collections (see `Array.test()`) are converted to arrays. 2612 * For everything else, a new array is created with _thing_ as the sole 2613 item. 2614 2615 Note: elements that are also collections, such as `<form>` and `<select>` 2616 elements, are not automatically converted to arrays. To force a conversion, 2617 pass `true` as the value of the _force_ parameter. 2618 2619 @class Array 2620 @constructor 2621 @param {Any} thing The thing to arrayify. 2622 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like 2623 collection, a subset of items starting at the specified index will be 2624 returned. 2625 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an 2626 array-like collection no matter what. 2627 @return {Array} A native array created from _thing_, according to the rules 2628 described above. 2629 **/ 2630 function YArray(thing, startIndex, force) { 2631 var len, result; 2632 2633 /*jshint expr: true*/ 2634 startIndex || (startIndex = 0); 2635 2636 if (force || YArray.test(thing)) { 2637 // IE throws when trying to slice HTMLElement collections. 2638 try { 2639 return Native.slice.call(thing, startIndex); 2640 } catch (ex) { 2641 result = []; 2642 2643 for (len = thing.length; startIndex < len; ++startIndex) { 2644 result.push(thing[startIndex]); 2645 } 2646 2647 return result; 2648 } 2649 } 2650 2651 return [thing]; 2652 } 2653 2654 Y.Array = YArray; 2655 2656 /** 2657 Dedupes an array of strings, returning an array that's guaranteed to contain 2658 only one copy of a given string. 2659 2660 This method differs from `Array.unique()` in that it's optimized for use only 2661 with arrays consisting entirely of strings or entirely of numbers, whereas 2662 `unique` may be used with other value types (but is slower). 2663 2664 Using `dedupe()` with values other than strings or numbers, or with arrays 2665 containing a mix of strings and numbers, may result in unexpected behavior. 2666 2667 @method dedupe 2668 @param {String[]|Number[]} array Array of strings or numbers to dedupe. 2669 @return {Array} Copy of _array_ containing no duplicate values. 2670 @static 2671 @since 3.4.0 2672 **/ 2673 YArray.dedupe = Lang._isNative(Object.create) ? function (array) { 2674 var hash = Object.create(null), 2675 results = [], 2676 i, item, len; 2677 2678 for (i = 0, len = array.length; i < len; ++i) { 2679 item = array[i]; 2680 2681 if (!hash[item]) { 2682 hash[item] = 1; 2683 results.push(item); 2684 } 2685 } 2686 2687 return results; 2688 } : function (array) { 2689 var hash = {}, 2690 results = [], 2691 i, item, len; 2692 2693 for (i = 0, len = array.length; i < len; ++i) { 2694 item = array[i]; 2695 2696 if (!hasOwn.call(hash, item)) { 2697 hash[item] = 1; 2698 results.push(item); 2699 } 2700 } 2701 2702 return results; 2703 }; 2704 2705 /** 2706 Executes the supplied function on each item in the array. This method wraps 2707 the native ES5 `Array.forEach()` method if available. 2708 2709 @method each 2710 @param {Array} array Array to iterate. 2711 @param {Function} fn Function to execute on each item in the array. The function 2712 will receive the following arguments: 2713 @param {Any} fn.item Current array item. 2714 @param {Number} fn.index Current array index. 2715 @param {Array} fn.array Array being iterated. 2716 @param {Object} [thisObj] `this` object to use when calling _fn_. 2717 @return {YUI} The YUI instance. 2718 @static 2719 **/ 2720 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) { 2721 Native.forEach.call(array || [], fn, thisObj || Y); 2722 return Y; 2723 } : function (array, fn, thisObj) { 2724 for (var i = 0, len = (array && array.length) || 0; i < len; ++i) { 2725 if (i in array) { 2726 fn.call(thisObj || Y, array[i], i, array); 2727 } 2728 } 2729 2730 return Y; 2731 }; 2732 2733 /** 2734 Alias for `each()`. 2735 2736 @method forEach 2737 @static 2738 **/ 2739 2740 /** 2741 Returns an object using the first array as keys and the second as values. If 2742 the second array is not provided, or if it doesn't contain the same number of 2743 values as the first array, then `true` will be used in place of the missing 2744 values. 2745 2746 @example 2747 2748 Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']); 2749 // => {a: 'foo', b: 'bar', c: true} 2750 2751 @method hash 2752 @param {String[]} keys Array of strings to use as keys. 2753 @param {Array} [values] Array to use as values. 2754 @return {Object} Hash using the first array as keys and the second as values. 2755 @static 2756 **/ 2757 YArray.hash = function (keys, values) { 2758 var hash = {}, 2759 vlen = (values && values.length) || 0, 2760 i, len; 2761 2762 for (i = 0, len = keys.length; i < len; ++i) { 2763 if (i in keys) { 2764 hash[keys[i]] = vlen > i && i in values ? values[i] : true; 2765 } 2766 } 2767 2768 return hash; 2769 }; 2770 2771 /** 2772 Returns the index of the first item in the array that's equal (using a strict 2773 equality check) to the specified _value_, or `-1` if the value isn't found. 2774 2775 This method wraps the native ES5 `Array.indexOf()` method if available. 2776 2777 @method indexOf 2778 @param {Array} array Array to search. 2779 @param {Any} value Value to search for. 2780 @param {Number} [from=0] The index at which to begin the search. 2781 @return {Number} Index of the item strictly equal to _value_, or `-1` if not 2782 found. 2783 @static 2784 **/ 2785 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) { 2786 return Native.indexOf.call(array, value, from); 2787 } : function (array, value, from) { 2788 // http://es5.github.com/#x15.4.4.14 2789 var len = array.length; 2790 2791 from = +from || 0; 2792 from = (from > 0 || -1) * Math.floor(Math.abs(from)); 2793 2794 if (from < 0) { 2795 from += len; 2796 2797 if (from < 0) { 2798 from = 0; 2799 } 2800 } 2801 2802 for (; from < len; ++from) { 2803 if (from in array && array[from] === value) { 2804 return from; 2805 } 2806 } 2807 2808 return -1; 2809 }; 2810 2811 /** 2812 Numeric sort convenience function. 2813 2814 The native `Array.prototype.sort()` function converts values to strings and 2815 sorts them in lexicographic order, which is unsuitable for sorting numeric 2816 values. Provide `Array.numericSort` as a custom sort function when you want 2817 to sort values in numeric order. 2818 2819 @example 2820 2821 [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort); 2822 // => [4, 8, 15, 16, 23, 42] 2823 2824 @method numericSort 2825 @param {Number} a First value to compare. 2826 @param {Number} b Second value to compare. 2827 @return {Number} Difference between _a_ and _b_. 2828 @static 2829 **/ 2830 YArray.numericSort = function (a, b) { 2831 return a - b; 2832 }; 2833 2834 /** 2835 Executes the supplied function on each item in the array. Returning a truthy 2836 value from the function will stop the processing of remaining items. 2837 2838 @method some 2839 @param {Array} array Array to iterate over. 2840 @param {Function} fn Function to execute on each item. The function will receive 2841 the following arguments: 2842 @param {Any} fn.value Current array item. 2843 @param {Number} fn.index Current array index. 2844 @param {Array} fn.array Array being iterated over. 2845 @param {Object} [thisObj] `this` object to use when calling _fn_. 2846 @return {Boolean} `true` if the function returns a truthy value on any of the 2847 items in the array; `false` otherwise. 2848 @static 2849 **/ 2850 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) { 2851 return Native.some.call(array, fn, thisObj); 2852 } : function (array, fn, thisObj) { 2853 for (var i = 0, len = array.length; i < len; ++i) { 2854 if (i in array && fn.call(thisObj, array[i], i, array)) { 2855 return true; 2856 } 2857 } 2858 2859 return false; 2860 }; 2861 2862 /** 2863 Evaluates _obj_ to determine if it's an array, an array-like collection, or 2864 something else. This is useful when working with the function `arguments` 2865 collection and `HTMLElement` collections. 2866 2867 Note: This implementation doesn't consider elements that are also 2868 collections, such as `<form>` and `<select>`, to be array-like. 2869 2870 @method test 2871 @param {Object} obj Object to test. 2872 @return {Number} A number indicating the results of the test: 2873 2874 * 0: Neither an array nor an array-like collection. 2875 * 1: Real array. 2876 * 2: Array-like collection. 2877 2878 @static 2879 **/ 2880 YArray.test = function (obj) { 2881 var result = 0; 2882 2883 if (Lang.isArray(obj)) { 2884 result = 1; 2885 } else if (Lang.isObject(obj)) { 2886 try { 2887 // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here), 2888 // or functions without apply/call (Safari 2889 // HTMLElementCollection bug). 2890 if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) { 2891 result = 2; 2892 } 2893 } catch (ex) {} 2894 } 2895 2896 return result; 2897 }; 2898 /** 2899 * The YUI module contains the components required for building the YUI 2900 * seed file. This includes the script loading mechanism, a simple queue, 2901 * and the core utilities for the library. 2902 * @module yui 2903 * @submodule yui-base 2904 */ 2905 2906 /** 2907 * A simple FIFO queue. Items are added to the Queue with add(1..n items) and 2908 * removed using next(). 2909 * 2910 * @class Queue 2911 * @constructor 2912 * @param {MIXED} item* 0..n items to seed the queue. 2913 */ 2914 function Queue() { 2915 this._init(); 2916 this.add.apply(this, arguments); 2917 } 2918 2919 Queue.prototype = { 2920 /** 2921 * Initialize the queue 2922 * 2923 * @method _init 2924 * @protected 2925 */ 2926 _init: function() { 2927 /** 2928 * The collection of enqueued items 2929 * 2930 * @property _q 2931 * @type Array 2932 * @protected 2933 */ 2934 this._q = []; 2935 }, 2936 2937 /** 2938 * Get the next item in the queue. FIFO support 2939 * 2940 * @method next 2941 * @return {MIXED} the next item in the queue. 2942 */ 2943 next: function() { 2944 return this._q.shift(); 2945 }, 2946 2947 /** 2948 * Get the last in the queue. LIFO support. 2949 * 2950 * @method last 2951 * @return {MIXED} the last item in the queue. 2952 */ 2953 last: function() { 2954 return this._q.pop(); 2955 }, 2956 2957 /** 2958 * Add 0..n items to the end of the queue. 2959 * 2960 * @method add 2961 * @param {MIXED} item* 0..n items. 2962 * @return {object} this queue. 2963 */ 2964 add: function() { 2965 this._q.push.apply(this._q, arguments); 2966 2967 return this; 2968 }, 2969 2970 /** 2971 * Returns the current number of queued items. 2972 * 2973 * @method size 2974 * @return {Number} The size. 2975 */ 2976 size: function() { 2977 return this._q.length; 2978 } 2979 }; 2980 2981 Y.Queue = Queue; 2982 2983 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue(); 2984 2985 /** 2986 The YUI module contains the components required for building the YUI seed file. 2987 This includes the script loading mechanism, a simple queue, and the core 2988 utilities for the library. 2989 2990 @module yui 2991 @submodule yui-base 2992 **/ 2993 2994 var CACHED_DELIMITER = '__', 2995 2996 hasOwn = Object.prototype.hasOwnProperty, 2997 isObject = Y.Lang.isObject; 2998 2999 /** 3000 Returns a wrapper for a function which caches the return value of that function, 3001 keyed off of the combined string representation of the argument values provided 3002 when the wrapper is called. 3003 3004 Calling this function again with the same arguments will return the cached value 3005 rather than executing the wrapped function. 3006 3007 Note that since the cache is keyed off of the string representation of arguments 3008 passed to the wrapper function, arguments that aren't strings and don't provide 3009 a meaningful `toString()` method may result in unexpected caching behavior. For 3010 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the 3011 string `[object Object]` when used as a cache key. 3012 3013 @method cached 3014 @param {Function} source The function to memoize. 3015 @param {Object} [cache={}] Object in which to store cached values. You may seed 3016 this object with pre-existing cached values if desired. 3017 @param {any} [refetch] If supplied, this value is compared with the cached value 3018 using a `==` comparison. If the values are equal, the wrapped function is 3019 executed again even though a cached value exists. 3020 @return {Function} Wrapped function. 3021 @for YUI 3022 **/ 3023 Y.cached = function (source, cache, refetch) { 3024 /*jshint expr: true*/ 3025 cache || (cache = {}); 3026 3027 return function (arg) { 3028 var key = arguments.length > 1 ? 3029 Array.prototype.join.call(arguments, CACHED_DELIMITER) : 3030 String(arg); 3031 3032 /*jshint eqeqeq: false*/ 3033 if (!(key in cache) || (refetch && cache[key] == refetch)) { 3034 cache[key] = source.apply(source, arguments); 3035 } 3036 3037 return cache[key]; 3038 }; 3039 }; 3040 3041 /** 3042 Returns the `location` object from the window/frame in which this YUI instance 3043 operates, or `undefined` when executing in a non-browser environment 3044 (e.g. Node.js). 3045 3046 It is _not_ recommended to hold references to the `window.location` object 3047 outside of the scope of a function in which its properties are being accessed or 3048 its methods are being called. This is because of a nasty bug/issue that exists 3049 in both Safari and MobileSafari browsers: 3050 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679). 3051 3052 @method getLocation 3053 @return {location} The `location` object from the window/frame in which this YUI 3054 instance operates. 3055 @since 3.5.0 3056 **/ 3057 Y.getLocation = function () { 3058 // It is safer to look this up every time because yui-base is attached to a 3059 // YUI instance before a user's config is applied; i.e. `Y.config.win` does 3060 // not point the correct window object when this file is loaded. 3061 var win = Y.config.win; 3062 3063 // It is not safe to hold a reference to the `location` object outside the 3064 // scope in which it is being used. The WebKit engine used in Safari and 3065 // MobileSafari will "disconnect" the `location` object from the `window` 3066 // when a page is restored from back/forward history cache. 3067 return win && win.location; 3068 }; 3069 3070 /** 3071 Returns a new object containing all of the properties of all the supplied 3072 objects. The properties from later objects will overwrite those in earlier 3073 objects. 3074 3075 Passing in a single object will create a shallow copy of it. For a deep copy, 3076 use `clone()`. 3077 3078 @method merge 3079 @param {Object} objects* One or more objects to merge. 3080 @return {Object} A new merged object. 3081 **/ 3082 Y.merge = function () { 3083 var i = 0, 3084 len = arguments.length, 3085 result = {}, 3086 key, 3087 obj; 3088 3089 for (; i < len; ++i) { 3090 obj = arguments[i]; 3091 3092 for (key in obj) { 3093 if (hasOwn.call(obj, key)) { 3094 result[key] = obj[key]; 3095 } 3096 } 3097 } 3098 3099 return result; 3100 }; 3101 3102 /** 3103 Mixes _supplier_'s properties into _receiver_. 3104 3105 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or 3106 shadowed unless the _overwrite_ parameter is `true`, and will not be merged 3107 unless the _merge_ parameter is `true`. 3108 3109 In the default mode (0), only properties the supplier owns are copied (prototype 3110 properties are not copied). The following copying modes are available: 3111 3112 * `0`: _Default_. Object to object. 3113 * `1`: Prototype to prototype. 3114 * `2`: Prototype to prototype and object to object. 3115 * `3`: Prototype to object. 3116 * `4`: Object to prototype. 3117 3118 @method mix 3119 @param {Function|Object} receiver The object or function to receive the mixed 3120 properties. 3121 @param {Function|Object} supplier The object or function supplying the 3122 properties to be mixed. 3123 @param {Boolean} [overwrite=false] If `true`, properties that already exist 3124 on the receiver will be overwritten with properties from the supplier. 3125 @param {String[]} [whitelist] An array of property names to copy. If 3126 specified, only the whitelisted properties will be copied, and all others 3127 will be ignored. 3128 @param {Number} [mode=0] Mix mode to use. See above for available modes. 3129 @param {Boolean} [merge=false] If `true`, objects and arrays that already 3130 exist on the receiver will have the corresponding object/array from the 3131 supplier merged into them, rather than being skipped or overwritten. When 3132 both _overwrite_ and _merge_ are `true`, _merge_ takes precedence. 3133 @return {Function|Object|YUI} The receiver, or the YUI instance if the 3134 specified receiver is falsy. 3135 **/ 3136 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { 3137 var alwaysOverwrite, exists, from, i, key, len, to; 3138 3139 // If no supplier is given, we return the receiver. If no receiver is given, 3140 // we return Y. Returning Y doesn't make much sense to me, but it's 3141 // grandfathered in for backcompat reasons. 3142 if (!receiver || !supplier) { 3143 return receiver || Y; 3144 } 3145 3146 if (mode) { 3147 // In mode 2 (prototype to prototype and object to object), we recurse 3148 // once to do the proto to proto mix. The object to object mix will be 3149 // handled later on. 3150 if (mode === 2) { 3151 Y.mix(receiver.prototype, supplier.prototype, overwrite, 3152 whitelist, 0, merge); 3153 } 3154 3155 // Depending on which mode is specified, we may be copying from or to 3156 // the prototypes of the supplier and receiver. 3157 from = mode === 1 || mode === 3 ? supplier.prototype : supplier; 3158 to = mode === 1 || mode === 4 ? receiver.prototype : receiver; 3159 3160 // If either the supplier or receiver doesn't actually have a 3161 // prototype property, then we could end up with an undefined `from` 3162 // or `to`. If that happens, we abort and return the receiver. 3163 if (!from || !to) { 3164 return receiver; 3165 } 3166 } else { 3167 from = supplier; 3168 to = receiver; 3169 } 3170 3171 // If `overwrite` is truthy and `merge` is falsy, then we can skip a 3172 // property existence check on each iteration and save some time. 3173 alwaysOverwrite = overwrite && !merge; 3174 3175 if (whitelist) { 3176 for (i = 0, len = whitelist.length; i < len; ++i) { 3177 key = whitelist[i]; 3178 3179 // We call `Object.prototype.hasOwnProperty` instead of calling 3180 // `hasOwnProperty` on the object itself, since the object's 3181 // `hasOwnProperty` method may have been overridden or removed. 3182 // Also, some native objects don't implement a `hasOwnProperty` 3183 // method. 3184 if (!hasOwn.call(from, key)) { 3185 continue; 3186 } 3187 3188 // The `key in to` check here is (sadly) intentional for backwards 3189 // compatibility reasons. It prevents undesired shadowing of 3190 // prototype members on `to`. 3191 exists = alwaysOverwrite ? false : key in to; 3192 3193 if (merge && exists && isObject(to[key], true) 3194 && isObject(from[key], true)) { 3195 // If we're in merge mode, and the key is present on both 3196 // objects, and the value on both objects is either an object or 3197 // an array (but not a function), then we recurse to merge the 3198 // `from` value into the `to` value instead of overwriting it. 3199 // 3200 // Note: It's intentional that the whitelist isn't passed to the 3201 // recursive call here. This is legacy behavior that lots of 3202 // code still depends on. 3203 Y.mix(to[key], from[key], overwrite, null, 0, merge); 3204 } else if (overwrite || !exists) { 3205 // We're not in merge mode, so we'll only copy the `from` value 3206 // to the `to` value if we're in overwrite mode or if the 3207 // current key doesn't exist on the `to` object. 3208 to[key] = from[key]; 3209 } 3210 } 3211 } else { 3212 for (key in from) { 3213 // The code duplication here is for runtime performance reasons. 3214 // Combining whitelist and non-whitelist operations into a single 3215 // loop or breaking the shared logic out into a function both result 3216 // in worse performance, and Y.mix is critical enough that the byte 3217 // tradeoff is worth it. 3218 if (!hasOwn.call(from, key)) { 3219 continue; 3220 } 3221 3222 // The `key in to` check here is (sadly) intentional for backwards 3223 // compatibility reasons. It prevents undesired shadowing of 3224 // prototype members on `to`. 3225 exists = alwaysOverwrite ? false : key in to; 3226 3227 if (merge && exists && isObject(to[key], true) 3228 && isObject(from[key], true)) { 3229 Y.mix(to[key], from[key], overwrite, null, 0, merge); 3230 } else if (overwrite || !exists) { 3231 to[key] = from[key]; 3232 } 3233 } 3234 3235 // If this is an IE browser with the JScript enumeration bug, force 3236 // enumeration of the buggy properties by making a recursive call with 3237 // the buggy properties as the whitelist. 3238 if (Y.Object._hasEnumBug) { 3239 Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge); 3240 } 3241 } 3242 3243 return receiver; 3244 }; 3245 /** 3246 * The YUI module contains the components required for building the YUI 3247 * seed file. This includes the script loading mechanism, a simple queue, 3248 * and the core utilities for the library. 3249 * @module yui 3250 * @submodule yui-base 3251 */ 3252 3253 /** 3254 * Adds utilities to the YUI instance for working with objects. 3255 * 3256 * @class Object 3257 */ 3258 3259 var Lang = Y.Lang, 3260 hasOwn = Object.prototype.hasOwnProperty, 3261 3262 UNDEFINED, // <-- Note the comma. We're still declaring vars. 3263 3264 /** 3265 * Returns a new object that uses _obj_ as its prototype. This method wraps the 3266 * native ES5 `Object.create()` method if available, but doesn't currently 3267 * pass through `Object.create()`'s second argument (properties) in order to 3268 * ensure compatibility with older browsers. 3269 * 3270 * @method () 3271 * @param {Object} obj Prototype object. 3272 * @return {Object} New object using _obj_ as its prototype. 3273 * @static 3274 */ 3275 O = Y.Object = Lang._isNative(Object.create) ? function (obj) { 3276 // We currently wrap the native Object.create instead of simply aliasing it 3277 // to ensure consistency with our fallback shim, which currently doesn't 3278 // support Object.create()'s second argument (properties). Once we have a 3279 // safe fallback for the properties arg, we can stop wrapping 3280 // Object.create(). 3281 return Object.create(obj); 3282 } : (function () { 3283 // Reusable constructor function for the Object.create() shim. 3284 function F() {} 3285 3286 // The actual shim. 3287 return function (obj) { 3288 F.prototype = obj; 3289 return new F(); 3290 }; 3291 }()), 3292 3293 /** 3294 * Property names that IE doesn't enumerate in for..in loops, even when they 3295 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to 3296 * manually enumerate these properties. 3297 * 3298 * @property _forceEnum 3299 * @type String[] 3300 * @protected 3301 * @static 3302 */ 3303 forceEnum = O._forceEnum = [ 3304 'hasOwnProperty', 3305 'isPrototypeOf', 3306 'propertyIsEnumerable', 3307 'toString', 3308 'toLocaleString', 3309 'valueOf' 3310 ], 3311 3312 /** 3313 * `true` if this browser has the JScript enumeration bug that prevents 3314 * enumeration of the properties named in the `_forceEnum` array, `false` 3315 * otherwise. 3316 * 3317 * See: 3318 * - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug> 3319 * - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation> 3320 * 3321 * @property _hasEnumBug 3322 * @type Boolean 3323 * @protected 3324 * @static 3325 */ 3326 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'), 3327 3328 /** 3329 * `true` if this browser incorrectly considers the `prototype` property of 3330 * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x. 3331 * 3332 * @property _hasProtoEnumBug 3333 * @type Boolean 3334 * @protected 3335 * @static 3336 */ 3337 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'), 3338 3339 /** 3340 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or 3341 * exists only on _obj_'s prototype. This is essentially a safer version of 3342 * `obj.hasOwnProperty()`. 3343 * 3344 * @method owns 3345 * @param {Object} obj Object to test. 3346 * @param {String} key Property name to look for. 3347 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise. 3348 * @static 3349 */ 3350 owns = O.owns = function (obj, key) { 3351 return !!obj && hasOwn.call(obj, key); 3352 }; // <-- End of var declarations. 3353 3354 /** 3355 * Alias for `owns()`. 3356 * 3357 * @method hasKey 3358 * @param {Object} obj Object to test. 3359 * @param {String} key Property name to look for. 3360 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise. 3361 * @static 3362 */ 3363 O.hasKey = owns; 3364 3365 /** 3366 * Returns an array containing the object's enumerable keys. Does not include 3367 * prototype keys or non-enumerable keys. 3368 * 3369 * Note that keys are returned in enumeration order (that is, in the same order 3370 * that they would be enumerated by a `for-in` loop), which may not be the same 3371 * as the order in which they were defined. 3372 * 3373 * This method is an alias for the native ES5 `Object.keys()` method if 3374 * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of 3375 * `Object.keys()` have an inconsistency as they consider `prototype` to be 3376 * enumerable, so a non-native shim is used to rectify the difference. 3377 * 3378 * @example 3379 * 3380 * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'}); 3381 * // => ['a', 'b', 'c'] 3382 * 3383 * @method keys 3384 * @param {Object} obj An object. 3385 * @return {String[]} Array of keys. 3386 * @static 3387 */ 3388 O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) { 3389 if (!Lang.isObject(obj)) { 3390 throw new TypeError('Object.keys called on a non-object'); 3391 } 3392 3393 var keys = [], 3394 i, key, len; 3395 3396 if (hasProtoEnumBug && typeof obj === 'function') { 3397 for (key in obj) { 3398 if (owns(obj, key) && key !== 'prototype') { 3399 keys.push(key); 3400 } 3401 } 3402 } else { 3403 for (key in obj) { 3404 if (owns(obj, key)) { 3405 keys.push(key); 3406 } 3407 } 3408 } 3409 3410 if (hasEnumBug) { 3411 for (i = 0, len = forceEnum.length; i < len; ++i) { 3412 key = forceEnum[i]; 3413 3414 if (owns(obj, key)) { 3415 keys.push(key); 3416 } 3417 } 3418 } 3419 3420 return keys; 3421 }; 3422 3423 /** 3424 * Returns an array containing the values of the object's enumerable keys. 3425 * 3426 * Note that values are returned in enumeration order (that is, in the same 3427 * order that they would be enumerated by a `for-in` loop), which may not be the 3428 * same as the order in which they were defined. 3429 * 3430 * @example 3431 * 3432 * Y.Object.values({a: 'foo', b: 'bar', c: 'baz'}); 3433 * // => ['foo', 'bar', 'baz'] 3434 * 3435 * @method values 3436 * @param {Object} obj An object. 3437 * @return {Array} Array of values. 3438 * @static 3439 */ 3440 O.values = function (obj) { 3441 var keys = O.keys(obj), 3442 i = 0, 3443 len = keys.length, 3444 values = []; 3445 3446 for (; i < len; ++i) { 3447 values.push(obj[keys[i]]); 3448 } 3449 3450 return values; 3451 }; 3452 3453 /** 3454 * Returns the number of enumerable keys owned by an object. 3455 * 3456 * @method size 3457 * @param {Object} obj An object. 3458 * @return {Number} The object's size. 3459 * @static 3460 */ 3461 O.size = function (obj) { 3462 try { 3463 return O.keys(obj).length; 3464 } catch (ex) { 3465 return 0; // Legacy behavior for non-objects. 3466 } 3467 }; 3468 3469 /** 3470 * Returns `true` if the object owns an enumerable property with the specified 3471 * value. 3472 * 3473 * @method hasValue 3474 * @param {Object} obj An object. 3475 * @param {any} value The value to search for. 3476 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise. 3477 * @static 3478 */ 3479 O.hasValue = function (obj, value) { 3480 return Y.Array.indexOf(O.values(obj), value) > -1; 3481 }; 3482 3483 /** 3484 * Executes a function on each enumerable property in _obj_. The function 3485 * receives the value, the key, and the object itself as parameters (in that 3486 * order). 3487 * 3488 * By default, only properties owned by _obj_ are enumerated. To include 3489 * prototype properties, set the _proto_ parameter to `true`. 3490 * 3491 * @method each 3492 * @param {Object} obj Object to enumerate. 3493 * @param {Function} fn Function to execute on each enumerable property. 3494 * @param {mixed} fn.value Value of the current property. 3495 * @param {String} fn.key Key of the current property. 3496 * @param {Object} fn.obj Object being enumerated. 3497 * @param {Object} [thisObj] `this` object to use when calling _fn_. 3498 * @param {Boolean} [proto=false] Include prototype properties. 3499 * @return {YUI} the YUI instance. 3500 * @chainable 3501 * @static 3502 */ 3503 O.each = function (obj, fn, thisObj, proto) { 3504 var key; 3505 3506 for (key in obj) { 3507 if (proto || owns(obj, key)) { 3508 fn.call(thisObj || Y, obj[key], key, obj); 3509 } 3510 } 3511 3512 return Y; 3513 }; 3514 3515 /** 3516 * Executes a function on each enumerable property in _obj_, but halts if the 3517 * function returns a truthy value. The function receives the value, the key, 3518 * and the object itself as paramters (in that order). 3519 * 3520 * By default, only properties owned by _obj_ are enumerated. To include 3521 * prototype properties, set the _proto_ parameter to `true`. 3522 * 3523 * @method some 3524 * @param {Object} obj Object to enumerate. 3525 * @param {Function} fn Function to execute on each enumerable property. 3526 * @param {mixed} fn.value Value of the current property. 3527 * @param {String} fn.key Key of the current property. 3528 * @param {Object} fn.obj Object being enumerated. 3529 * @param {Object} [thisObj] `this` object to use when calling _fn_. 3530 * @param {Boolean} [proto=false] Include prototype properties. 3531 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value, 3532 * `false` otherwise. 3533 * @static 3534 */ 3535 O.some = function (obj, fn, thisObj, proto) { 3536 var key; 3537 3538 for (key in obj) { 3539 if (proto || owns(obj, key)) { 3540 if (fn.call(thisObj || Y, obj[key], key, obj)) { 3541 return true; 3542 } 3543 } 3544 } 3545 3546 return false; 3547 }; 3548 3549 /** 3550 * Retrieves the sub value at the provided path, 3551 * from the value object provided. 3552 * 3553 * @method getValue 3554 * @static 3555 * @param o The object from which to extract the property value. 3556 * @param path {Array} A path array, specifying the object traversal path 3557 * from which to obtain the sub value. 3558 * @return {Any} The value stored in the path, undefined if not found, 3559 * undefined if the source is not an object. Returns the source object 3560 * if an empty path is provided. 3561 */ 3562 O.getValue = function(o, path) { 3563 if (!Lang.isObject(o)) { 3564 return UNDEFINED; 3565 } 3566 3567 var i, 3568 p = Y.Array(path), 3569 l = p.length; 3570 3571 for (i = 0; o !== UNDEFINED && i < l; i++) { 3572 o = o[p[i]]; 3573 } 3574 3575 return o; 3576 }; 3577 3578 /** 3579 * Sets the sub-attribute value at the provided path on the 3580 * value object. Returns the modified value object, or 3581 * undefined if the path is invalid. 3582 * 3583 * @method setValue 3584 * @static 3585 * @param o The object on which to set the sub value. 3586 * @param path {Array} A path array, specifying the object traversal path 3587 * at which to set the sub value. 3588 * @param val {Any} The new value for the sub-attribute. 3589 * @return {Object} The modified object, with the new sub value set, or 3590 * undefined, if the path was invalid. 3591 */ 3592 O.setValue = function(o, path, val) { 3593 var i, 3594 p = Y.Array(path), 3595 leafIdx = p.length - 1, 3596 ref = o; 3597 3598 if (leafIdx >= 0) { 3599 for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) { 3600 ref = ref[p[i]]; 3601 } 3602 3603 if (ref !== UNDEFINED) { 3604 ref[p[i]] = val; 3605 } else { 3606 return UNDEFINED; 3607 } 3608 } 3609 3610 return o; 3611 }; 3612 3613 /** 3614 * Returns `true` if the object has no enumerable properties of its own. 3615 * 3616 * @method isEmpty 3617 * @param {Object} obj An object. 3618 * @return {Boolean} `true` if the object is empty. 3619 * @static 3620 * @since 3.2.0 3621 */ 3622 O.isEmpty = function (obj) { 3623 return !O.keys(Object(obj)).length; 3624 }; 3625 /** 3626 * The YUI module contains the components required for building the YUI seed 3627 * file. This includes the script loading mechanism, a simple queue, and the 3628 * core utilities for the library. 3629 * @module yui 3630 * @submodule yui-base 3631 */ 3632 3633 /** 3634 * YUI user agent detection. 3635 * Do not fork for a browser if it can be avoided. Use feature detection when 3636 * you can. Use the user agent as a last resort. For all fields listed 3637 * as @type float, UA stores a version number for the browser engine, 3638 * 0 otherwise. This value may or may not map to the version number of 3639 * the browser using the engine. The value is presented as a float so 3640 * that it can easily be used for boolean evaluation as well as for 3641 * looking for a particular range of versions. Because of this, 3642 * some of the granularity of the version info may be lost. The fields that 3643 * are @type string default to null. The API docs list the values that 3644 * these fields can have. 3645 * @class UA 3646 * @static 3647 */ 3648 3649 /** 3650 * Static method on `YUI.Env` for parsing a UA string. Called at instantiation 3651 * to populate `Y.UA`. 3652 * 3653 * @static 3654 * @method parseUA 3655 * @param {String} [subUA=navigator.userAgent] UA string to parse 3656 * @return {Object} The Y.UA object 3657 */ 3658 YUI.Env.parseUA = function(subUA) { 3659 3660 var numberify = function(s) { 3661 var c = 0; 3662 return parseFloat(s.replace(/\./g, function() { 3663 return (c++ === 1) ? '' : '.'; 3664 })); 3665 }, 3666 3667 win = Y.config.win, 3668 3669 nav = win && win.navigator, 3670 3671 o = { 3672 3673 /** 3674 * Internet Explorer version number or 0. Example: 6 3675 * @property ie 3676 * @type float 3677 * @static 3678 */ 3679 ie: 0, 3680 3681 /** 3682 * Opera version number or 0. Example: 9.2 3683 * @property opera 3684 * @type float 3685 * @static 3686 */ 3687 opera: 0, 3688 3689 /** 3690 * Gecko engine revision number. Will evaluate to 1 if Gecko 3691 * is detected but the revision could not be found. Other browsers 3692 * will be 0. Example: 1.8 3693 * <pre> 3694 * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7 3695 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8 3696 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81 3697 * Firefox 3.0 <-- 1.9 3698 * Firefox 3.5 <-- 1.91 3699 * </pre> 3700 * @property gecko 3701 * @type float 3702 * @static 3703 */ 3704 gecko: 0, 3705 3706 /** 3707 * AppleWebKit version. KHTML browsers that are not WebKit browsers 3708 * will evaluate to 1, other browsers 0. Example: 418.9 3709 * <pre> 3710 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the 3711 * latest available for Mac OSX 10.3. 3712 * Safari 2.0.2: 416 <-- hasOwnProperty introduced 3713 * Safari 2.0.4: 418 <-- preventDefault fixed 3714 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run 3715 * different versions of webkit 3716 * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been 3717 * updated, but not updated 3718 * to the latest patch. 3719 * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native 3720 * SVG and many major issues fixed). 3721 * Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic 3722 * update from 2.x via the 10.4.11 OS patch. 3723 * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event. 3724 * yahoo.com user agent hack removed. 3725 * </pre> 3726 * http://en.wikipedia.org/wiki/Safari_version_history 3727 * @property webkit 3728 * @type float 3729 * @static 3730 */ 3731 webkit: 0, 3732 3733 /** 3734 * Safari will be detected as webkit, but this property will also 3735 * be populated with the Safari version number 3736 * @property safari 3737 * @type float 3738 * @static 3739 */ 3740 safari: 0, 3741 3742 /** 3743 * Chrome will be detected as webkit, but this property will also 3744 * be populated with the Chrome version number 3745 * @property chrome 3746 * @type float 3747 * @static 3748 */ 3749 chrome: 0, 3750 3751 /** 3752 * The mobile property will be set to a string containing any relevant 3753 * user agent information when a modern mobile browser is detected. 3754 * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series 3755 * devices with the WebKit-based browser, and Opera Mini. 3756 * @property mobile 3757 * @type string 3758 * @default null 3759 * @static 3760 */ 3761 mobile: null, 3762 3763 /** 3764 * Adobe AIR version number or 0. Only populated if webkit is detected. 3765 * Example: 1.0 3766 * @property air 3767 * @type float 3768 */ 3769 air: 0, 3770 /** 3771 * PhantomJS version number or 0. Only populated if webkit is detected. 3772 * Example: 1.0 3773 * @property phantomjs 3774 * @type float 3775 */ 3776 phantomjs: 0, 3777 /** 3778 * Detects Apple iPad's OS version 3779 * @property ipad 3780 * @type float 3781 * @static 3782 */ 3783 ipad: 0, 3784 /** 3785 * Detects Apple iPhone's OS version 3786 * @property iphone 3787 * @type float 3788 * @static 3789 */ 3790 iphone: 0, 3791 /** 3792 * Detects Apples iPod's OS version 3793 * @property ipod 3794 * @type float 3795 * @static 3796 */ 3797 ipod: 0, 3798 /** 3799 * General truthy check for iPad, iPhone or iPod 3800 * @property ios 3801 * @type Boolean 3802 * @default null 3803 * @static 3804 */ 3805 ios: null, 3806 /** 3807 * Detects Googles Android OS version 3808 * @property android 3809 * @type float 3810 * @static 3811 */ 3812 android: 0, 3813 /** 3814 * Detects Kindle Silk 3815 * @property silk 3816 * @type float 3817 * @static 3818 */ 3819 silk: 0, 3820 /** 3821 * Detects Ubuntu version 3822 * @property ubuntu 3823 * @type float 3824 * @static 3825 */ 3826 ubuntu: 0, 3827 /** 3828 * Detects Kindle Silk Acceleration 3829 * @property accel 3830 * @type Boolean 3831 * @static 3832 */ 3833 accel: false, 3834 /** 3835 * Detects Palms WebOS version 3836 * @property webos 3837 * @type float 3838 * @static 3839 */ 3840 webos: 0, 3841 3842 /** 3843 * Google Caja version number or 0. 3844 * @property caja 3845 * @type float 3846 */ 3847 caja: nav && nav.cajaVersion, 3848 3849 /** 3850 * Set to true if the page appears to be in SSL 3851 * @property secure 3852 * @type boolean 3853 * @static 3854 */ 3855 secure: false, 3856 3857 /** 3858 * The operating system. Currently only detecting windows or macintosh 3859 * @property os 3860 * @type string 3861 * @default null 3862 * @static 3863 */ 3864 os: null, 3865 3866 /** 3867 * The Nodejs Version 3868 * @property nodejs 3869 * @type float 3870 * @default 0 3871 * @static 3872 */ 3873 nodejs: 0, 3874 /** 3875 * Window8/IE10 Application host environment 3876 * @property winjs 3877 * @type Boolean 3878 * @static 3879 */ 3880 winjs: !!((typeof Windows !== "undefined") && Windows.System), 3881 /** 3882 * Are touch/msPointer events available on this device 3883 * @property touchEnabled 3884 * @type Boolean 3885 * @static 3886 */ 3887 touchEnabled: false 3888 }, 3889 3890 ua = subUA || nav && nav.userAgent, 3891 3892 loc = win && win.location, 3893 3894 href = loc && loc.href, 3895 3896 m; 3897 3898 /** 3899 * The User Agent string that was parsed 3900 * @property userAgent 3901 * @type String 3902 * @static 3903 */ 3904 o.userAgent = ua; 3905 3906 3907 o.secure = href && (href.toLowerCase().indexOf('https') === 0); 3908 3909 if (ua) { 3910 3911 if ((/windows|win32/i).test(ua)) { 3912 o.os = 'windows'; 3913 } else if ((/macintosh|mac_powerpc/i).test(ua)) { 3914 o.os = 'macintosh'; 3915 } else if ((/android/i).test(ua)) { 3916 o.os = 'android'; 3917 } else if ((/symbos/i).test(ua)) { 3918 o.os = 'symbos'; 3919 } else if ((/linux/i).test(ua)) { 3920 o.os = 'linux'; 3921 } else if ((/rhino/i).test(ua)) { 3922 o.os = 'rhino'; 3923 } 3924 3925 // Modern KHTML browsers should qualify as Safari X-Grade 3926 if ((/KHTML/).test(ua)) { 3927 o.webkit = 1; 3928 } 3929 if ((/IEMobile|XBLWP7/).test(ua)) { 3930 o.mobile = 'windows'; 3931 } 3932 if ((/Fennec/).test(ua)) { 3933 o.mobile = 'gecko'; 3934 } 3935 // Modern WebKit browsers are at least X-Grade 3936 m = ua.match(/AppleWebKit\/([^\s]*)/); 3937 if (m && m[1]) { 3938 o.webkit = numberify(m[1]); 3939 o.safari = o.webkit; 3940 3941 if (/PhantomJS/.test(ua)) { 3942 m = ua.match(/PhantomJS\/([^\s]*)/); 3943 if (m && m[1]) { 3944 o.phantomjs = numberify(m[1]); 3945 } 3946 } 3947 3948 // Mobile browser check 3949 if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) { 3950 o.mobile = 'Apple'; // iPhone or iPod Touch 3951 3952 m = ua.match(/OS ([^\s]*)/); 3953 if (m && m[1]) { 3954 m = numberify(m[1].replace('_', '.')); 3955 } 3956 o.ios = m; 3957 o.os = 'ios'; 3958 o.ipad = o.ipod = o.iphone = 0; 3959 3960 m = ua.match(/iPad|iPod|iPhone/); 3961 if (m && m[0]) { 3962 o[m[0].toLowerCase()] = o.ios; 3963 } 3964 } else { 3965 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/); 3966 if (m) { 3967 // Nokia N-series, webOS, ex: NokiaN95 3968 o.mobile = m[0]; 3969 } 3970 if (/webOS/.test(ua)) { 3971 o.mobile = 'WebOS'; 3972 m = ua.match(/webOS\/([^\s]*);/); 3973 if (m && m[1]) { 3974 o.webos = numberify(m[1]); 3975 } 3976 } 3977 if (/ Android/.test(ua)) { 3978 if (/Mobile/.test(ua)) { 3979 o.mobile = 'Android'; 3980 } 3981 m = ua.match(/Android ([^\s]*);/); 3982 if (m && m[1]) { 3983 o.android = numberify(m[1]); 3984 } 3985 3986 } 3987 if (/Silk/.test(ua)) { 3988 m = ua.match(/Silk\/([^\s]*)/); 3989 if (m && m[1]) { 3990 o.silk = numberify(m[1]); 3991 } 3992 if (!o.android) { 3993 o.android = 2.34; //Hack for desktop mode in Kindle 3994 o.os = 'Android'; 3995 } 3996 if (/Accelerated=true/.test(ua)) { 3997 o.accel = true; 3998 } 3999 } 4000 } 4001 4002 m = ua.match(/OPR\/(\d+\.\d+)/); 4003 4004 if (m && m[1]) { 4005 // Opera 15+ with Blink (pretends to be both Chrome and Safari) 4006 o.opera = numberify(m[1]); 4007 } else { 4008 m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/); 4009 4010 if (m && m[1] && m[2]) { 4011 o.chrome = numberify(m[2]); // Chrome 4012 o.safari = 0; //Reset safari back to 0 4013 if (m[1] === 'CrMo') { 4014 o.mobile = 'chrome'; 4015 } 4016 } else { 4017 m = ua.match(/AdobeAIR\/([^\s]*)/); 4018 if (m) { 4019 o.air = m[0]; // Adobe AIR 1.0 or better 4020 } 4021 } 4022 } 4023 } 4024 4025 m = ua.match(/Ubuntu\ (\d+\.\d+)/); 4026 if (m && m[1]) { 4027 4028 o.os = 'linux'; 4029 o.ubuntu = numberify(m[1]); 4030 4031 m = ua.match(/\ WebKit\/([^\s]*)/); 4032 if (m && m[1]) { 4033 o.webkit = numberify(m[1]); 4034 } 4035 m = ua.match(/\ Chromium\/([^\s]*)/); 4036 if (m && m[1]) { 4037 o.chrome = numberify(m[1]); 4038 } 4039 if (/ Mobile$/.test(ua)) { 4040 o.mobile = 'Ubuntu'; 4041 } 4042 } 4043 4044 if (!o.webkit) { // not webkit 4045 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) 4046 if (/Opera/.test(ua)) { 4047 m = ua.match(/Opera[\s\/]([^\s]*)/); 4048 if (m && m[1]) { 4049 o.opera = numberify(m[1]); 4050 } 4051 m = ua.match(/Version\/([^\s]*)/); 4052 if (m && m[1]) { 4053 o.opera = numberify(m[1]); // opera 10+ 4054 } 4055 4056 if (/Opera Mobi/.test(ua)) { 4057 o.mobile = 'opera'; 4058 m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/); 4059 if (m && m[1]) { 4060 o.opera = numberify(m[1]); 4061 } 4062 } 4063 m = ua.match(/Opera Mini[^;]*/); 4064 4065 if (m) { 4066 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 4067 } 4068 } else { // not opera or webkit 4069 m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/); 4070 4071 if (m && (m[1] || m[2])) { 4072 o.ie = numberify(m[1] || m[2]); 4073 } else { // not opera, webkit, or ie 4074 m = ua.match(/Gecko\/([^\s]*)/); 4075 4076 if (m) { 4077 o.gecko = 1; // Gecko detected, look for revision 4078 m = ua.match(/rv:([^\s\)]*)/); 4079 if (m && m[1]) { 4080 o.gecko = numberify(m[1]); 4081 if (/Mobile|Tablet/.test(ua)) { 4082 o.mobile = "ffos"; 4083 } 4084 } 4085 } 4086 } 4087 } 4088 } 4089 } 4090 4091 //Check for known properties to tell if touch events are enabled on this device or if 4092 //the number of MSPointer touchpoints on this device is greater than 0. 4093 if (win && nav && !(o.chrome && o.chrome < 6)) { 4094 o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0))); 4095 } 4096 4097 //It was a parsed UA, do not assign the global value. 4098 if (!subUA) { 4099 4100 if (typeof process === 'object') { 4101 4102 if (process.versions && process.versions.node) { 4103 //NodeJS 4104 o.os = process.platform; 4105 o.nodejs = numberify(process.versions.node); 4106 } 4107 } 4108 4109 YUI.Env.UA = o; 4110 4111 } 4112 4113 return o; 4114 }; 4115 4116 4117 Y.UA = YUI.Env.UA || YUI.Env.parseUA(); 4118 4119 /** 4120 Performs a simple comparison between two version numbers, accounting for 4121 standard versioning logic such as the fact that "535.8" is a lower version than 4122 "535.24", even though a simple numerical comparison would indicate that it's 4123 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are 4124 considered equivalent. 4125 4126 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent, 4127 1 if _a_ is higher than _b_. 4128 4129 Versions may be numbers or strings containing numbers and dots. For example, 4130 both `535` and `"535.8.10"` are acceptable. A version string containing 4131 non-numeric characters, like `"535.8.beta"`, may produce unexpected results. 4132 4133 @method compareVersions 4134 @param {Number|String} a First version number to compare. 4135 @param {Number|String} b Second version number to compare. 4136 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is 4137 higher than _b_. 4138 **/ 4139 Y.UA.compareVersions = function (a, b) { 4140 var aPart, aParts, bPart, bParts, i, len; 4141 4142 if (a === b) { 4143 return 0; 4144 } 4145 4146 aParts = (a + '').split('.'); 4147 bParts = (b + '').split('.'); 4148 4149 for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) { 4150 aPart = parseInt(aParts[i], 10); 4151 bPart = parseInt(bParts[i], 10); 4152 4153 /*jshint expr: true*/ 4154 isNaN(aPart) && (aPart = 0); 4155 isNaN(bPart) && (bPart = 0); 4156 4157 if (aPart < bPart) { 4158 return -1; 4159 } 4160 4161 if (aPart > bPart) { 4162 return 1; 4163 } 4164 } 4165 4166 return 0; 4167 }; 4168 YUI.Env.aliases = { 4169 "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"], 4170 "anim-shape-transform": ["anim-shape"], 4171 "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"], 4172 "attribute": ["attribute-base","attribute-complex"], 4173 "attribute-events": ["attribute-observable"], 4174 "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"], 4175 "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"], 4176 "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"], 4177 "base": ["base-base","base-pluginhost","base-build"], 4178 "cache": ["cache-base","cache-offline","cache-plugin"], 4179 "charts": ["charts-base"], 4180 "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"], 4181 "color": ["color-base","color-hsl","color-harmony"], 4182 "controller": ["router"], 4183 "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"], 4184 "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"], 4185 "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"], 4186 "datatype": ["datatype-date","datatype-number","datatype-xml"], 4187 "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"], 4188 "datatype-number": ["datatype-number-parse","datatype-number-format"], 4189 "datatype-xml": ["datatype-xml-parse","datatype-xml-format"], 4190 "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"], 4191 "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"], 4192 "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"], 4193 "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"], 4194 "event-custom": ["event-custom-base","event-custom-complex"], 4195 "event-gestures": ["event-flick","event-move"], 4196 "handlebars": ["handlebars-compiler"], 4197 "highlight": ["highlight-base","highlight-accentfold"], 4198 "history": ["history-base","history-hash","history-html5"], 4199 "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"], 4200 "json": ["json-parse","json-stringify"], 4201 "loader": ["loader-base","loader-rollup","loader-yui3"], 4202 "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"], 4203 "pluginhost": ["pluginhost-base","pluginhost-config"], 4204 "querystring": ["querystring-parse","querystring-stringify"], 4205 "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"], 4206 "resize": ["resize-base","resize-proxy","resize-constrain"], 4207 "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"], 4208 "template": ["template-base","template-micro"], 4209 "text": ["text-accentfold","text-wordbreak"], 4210 "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"] 4211 }; 4212 4213 4214 }, '3.17.2');
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |