[ 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: ['get', 'features', 'intl-base', 'yui-log', 'yui-later'], 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', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]}); 4215 YUI.add('get', function (Y, NAME) { 4216 4217 /*jslint boss:true, expr:true, laxbreak: true */ 4218 4219 /** 4220 Provides dynamic loading of remote JavaScript and CSS resources. 4221 4222 @module get 4223 @class Get 4224 @static 4225 **/ 4226 4227 var Lang = Y.Lang, 4228 4229 CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode() 4230 4231 Get, Transaction; 4232 4233 Y.Get = Get = { 4234 // -- Public Properties ---------------------------------------------------- 4235 4236 /** 4237 Default options for CSS requests. Options specified here will override 4238 global defaults for CSS requests. 4239 4240 See the `options` property for all available options. 4241 4242 @property cssOptions 4243 @type Object 4244 @static 4245 @since 3.5.0 4246 **/ 4247 cssOptions: { 4248 attributes: { 4249 rel: 'stylesheet' 4250 }, 4251 4252 doc : Y.config.linkDoc || Y.config.doc, 4253 pollInterval: 50 4254 }, 4255 4256 /** 4257 Default options for JS requests. Options specified here will override global 4258 defaults for JS requests. 4259 4260 See the `options` property for all available options. 4261 4262 @property jsOptions 4263 @type Object 4264 @static 4265 @since 3.5.0 4266 **/ 4267 jsOptions: { 4268 autopurge: true, 4269 doc : Y.config.scriptDoc || Y.config.doc 4270 }, 4271 4272 /** 4273 Default options to use for all requests. 4274 4275 Note that while all available options are documented here for ease of 4276 discovery, some options (like callback functions) only make sense at the 4277 transaction level. 4278 4279 Callback functions specified via the options object or the `options` 4280 parameter of the `css()`, `js()`, or `load()` methods will receive the 4281 transaction object as a parameter. See `Y.Get.Transaction` for details on 4282 the properties and methods available on transactions. 4283 4284 @static 4285 @since 3.5.0 4286 @property {Object} options 4287 4288 @property {Boolean} [options.async=false] Whether or not to load scripts 4289 asynchronously, meaning they're requested in parallel and execution 4290 order is not guaranteed. Has no effect on CSS, since CSS is always 4291 loaded asynchronously. 4292 4293 @property {Object} [options.attributes] HTML attribute name/value pairs that 4294 should be added to inserted nodes. By default, the `charset` attribute 4295 will be set to "utf-8" and nodes will be given an auto-generated `id` 4296 attribute, but you can override these with your own values if desired. 4297 4298 @property {Boolean} [options.autopurge] Whether or not to automatically 4299 purge inserted nodes after the purge threshold is reached. This is 4300 `true` by default for JavaScript, but `false` for CSS since purging a 4301 CSS node will also remove any styling applied by the referenced file. 4302 4303 @property {Object} [options.context] `this` object to use when calling 4304 callback functions. Defaults to the transaction object. 4305 4306 @property {Mixed} [options.data] Arbitrary data object to pass to "on*" 4307 callbacks. 4308 4309 @property {Document} [options.doc] Document into which nodes should be 4310 inserted. By default, the current document is used. 4311 4312 @property {HTMLElement|String} [options.insertBefore] HTML element or id 4313 string of an element before which all generated nodes should be 4314 inserted. If not specified, Get will automatically determine the best 4315 place to insert nodes for maximum compatibility. 4316 4317 @property {Function} [options.onEnd] Callback to execute after a transaction 4318 is complete, regardless of whether it succeeded or failed. 4319 4320 @property {Function} [options.onFailure] Callback to execute after a 4321 transaction fails, times out, or is aborted. 4322 4323 @property {Function} [options.onProgress] Callback to execute after each 4324 individual request in a transaction either succeeds or fails. 4325 4326 @property {Function} [options.onSuccess] Callback to execute after a 4327 transaction completes successfully with no errors. Note that in browsers 4328 that don't support the `error` event on CSS `<link>` nodes, a failed CSS 4329 request may still be reported as a success because in these browsers 4330 it can be difficult or impossible to distinguish between success and 4331 failure for CSS resources. 4332 4333 @property {Function} [options.onTimeout] Callback to execute after a 4334 transaction times out. 4335 4336 @property {Number} [options.pollInterval=50] Polling interval (in 4337 milliseconds) for detecting CSS load completion in browsers that don't 4338 support the `load` event on `<link>` nodes. This isn't used for 4339 JavaScript. 4340 4341 @property {Number} [options.purgethreshold=20] Number of nodes to insert 4342 before triggering an automatic purge when `autopurge` is `true`. 4343 4344 @property {Number} [options.timeout] Number of milliseconds to wait before 4345 aborting a transaction. When a timeout occurs, the `onTimeout` callback 4346 is called, followed by `onFailure` and finally `onEnd`. By default, 4347 there is no timeout. 4348 4349 @property {String} [options.type] Resource type ("css" or "js"). This option 4350 is set automatically by the `css()` and `js()` functions and will be 4351 ignored there, but may be useful when using the `load()` function. If 4352 not specified, the type will be inferred from the URL, defaulting to 4353 "js" if the URL doesn't contain a recognizable file extension. 4354 **/ 4355 options: { 4356 attributes: { 4357 charset: 'utf-8' 4358 }, 4359 4360 purgethreshold: 20 4361 }, 4362 4363 // -- Protected Properties ------------------------------------------------- 4364 4365 /** 4366 Regex that matches a CSS URL. Used to guess the file type when it's not 4367 specified. 4368 4369 @property REGEX_CSS 4370 @type RegExp 4371 @final 4372 @protected 4373 @static 4374 @since 3.5.0 4375 **/ 4376 REGEX_CSS: /\.css(?:[?;].*)?$/i, 4377 4378 /** 4379 Regex that matches a JS URL. Used to guess the file type when it's not 4380 specified. 4381 4382 @property REGEX_JS 4383 @type RegExp 4384 @final 4385 @protected 4386 @static 4387 @since 3.5.0 4388 **/ 4389 REGEX_JS : /\.js(?:[?;].*)?$/i, 4390 4391 /** 4392 Contains information about the current environment, such as what script and 4393 link injection features it supports. 4394 4395 This object is created and populated the first time the `_getEnv()` method 4396 is called. 4397 4398 @property _env 4399 @type Object 4400 @protected 4401 @static 4402 @since 3.5.0 4403 **/ 4404 4405 /** 4406 Mapping of document _yuid strings to <head> or <base> node references so we 4407 don't have to look the node up each time we want to insert a request node. 4408 4409 @property _insertCache 4410 @type Object 4411 @protected 4412 @static 4413 @since 3.5.0 4414 **/ 4415 _insertCache: {}, 4416 4417 /** 4418 Information about the currently pending transaction, if any. 4419 4420 This is actually an object with two properties: `callback`, containing the 4421 optional callback passed to `css()`, `load()`, or `js()`; and `transaction`, 4422 containing the actual transaction instance. 4423 4424 @property _pending 4425 @type Object 4426 @protected 4427 @static 4428 @since 3.5.0 4429 **/ 4430 _pending: null, 4431 4432 /** 4433 HTML nodes eligible to be purged next time autopurge is triggered. 4434 4435 @property _purgeNodes 4436 @type HTMLElement[] 4437 @protected 4438 @static 4439 @since 3.5.0 4440 **/ 4441 _purgeNodes: [], 4442 4443 /** 4444 Queued transactions and associated callbacks. 4445 4446 @property _queue 4447 @type Object[] 4448 @protected 4449 @static 4450 @since 3.5.0 4451 **/ 4452 _queue: [], 4453 4454 // -- Public Methods ------------------------------------------------------- 4455 4456 /** 4457 Aborts the specified transaction. 4458 4459 This will cause the transaction's `onFailure` callback to be called and 4460 will prevent any new script and link nodes from being added to the document, 4461 but any resources that have already been requested will continue loading 4462 (there's no safe way to prevent this, unfortunately). 4463 4464 *Note:* This method is deprecated as of 3.5.0, and will be removed in a 4465 future version of YUI. Use the transaction-level `abort()` method instead. 4466 4467 @method abort 4468 @param {Get.Transaction} transaction Transaction to abort. 4469 @deprecated Use the `abort()` method on the transaction instead. 4470 @static 4471 **/ 4472 abort: function (transaction) { 4473 var i, id, item, len, pending; 4474 4475 Y.log('`Y.Get.abort()` is deprecated as of 3.5.0. Use the `abort()` method on the transaction instead.', 'warn', 'get'); 4476 4477 if (!transaction.abort) { 4478 id = transaction; 4479 pending = this._pending; 4480 transaction = null; 4481 4482 if (pending && pending.transaction.id === id) { 4483 transaction = pending.transaction; 4484 this._pending = null; 4485 } else { 4486 for (i = 0, len = this._queue.length; i < len; ++i) { 4487 item = this._queue[i].transaction; 4488 4489 if (item.id === id) { 4490 transaction = item; 4491 this._queue.splice(i, 1); 4492 break; 4493 } 4494 } 4495 } 4496 } 4497 4498 transaction && transaction.abort(); 4499 }, 4500 4501 /** 4502 Loads one or more CSS files. 4503 4504 The _urls_ parameter may be provided as a URL string, a request object, 4505 or an array of URL strings and/or request objects. 4506 4507 A request object is just an object that contains a `url` property and zero 4508 or more options that should apply specifically to that request. 4509 Request-specific options take priority over transaction-level options and 4510 default options. 4511 4512 URLs may be relative or absolute, and do not have to have the same origin 4513 as the current page. 4514 4515 The `options` parameter may be omitted completely and a callback passed in 4516 its place, if desired. 4517 4518 @example 4519 4520 // Load a single CSS file and log a message on completion. 4521 Y.Get.css('foo.css', function (err) { 4522 if (err) { 4523 Y.log('foo.css failed to load!'); 4524 } else { 4525 Y.log('foo.css was loaded successfully'); 4526 } 4527 }); 4528 4529 // Load multiple CSS files and log a message when all have finished 4530 // loading. 4531 var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css']; 4532 4533 Y.Get.css(urls, function (err) { 4534 if (err) { 4535 Y.log('one or more files failed to load!'); 4536 } else { 4537 Y.log('all files loaded successfully'); 4538 } 4539 }); 4540 4541 // Specify transaction-level options, which will apply to all requests 4542 // within the transaction. 4543 Y.Get.css(urls, { 4544 attributes: {'class': 'my-css'}, 4545 timeout : 5000 4546 }); 4547 4548 // Specify per-request options, which override transaction-level and 4549 // default options. 4550 Y.Get.css([ 4551 {url: 'foo.css', attributes: {id: 'foo'}}, 4552 {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}} 4553 ]); 4554 4555 @method css 4556 @param {String|Object|Array} urls URL string, request object, or array 4557 of URLs and/or request objects to load. 4558 @param {Object} [options] Options for this transaction. See the 4559 `Y.Get.options` property for a complete list of available options. 4560 @param {Function} [callback] Callback function to be called on completion. 4561 This is a general callback and will be called before any more granular 4562 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4563 object. 4564 4565 @param {Array|null} callback.err Array of errors that occurred during 4566 the transaction, or `null` on success. 4567 @param {Get.Transaction} callback.transaction Transaction object. 4568 4569 @return {Get.Transaction} Transaction object. 4570 @static 4571 **/ 4572 css: function (urls, options, callback) { 4573 return this._load('css', urls, options, callback); 4574 }, 4575 4576 /** 4577 Loads one or more JavaScript resources. 4578 4579 The _urls_ parameter may be provided as a URL string, a request object, 4580 or an array of URL strings and/or request objects. 4581 4582 A request object is just an object that contains a `url` property and zero 4583 or more options that should apply specifically to that request. 4584 Request-specific options take priority over transaction-level options and 4585 default options. 4586 4587 URLs may be relative or absolute, and do not have to have the same origin 4588 as the current page. 4589 4590 The `options` parameter may be omitted completely and a callback passed in 4591 its place, if desired. 4592 4593 Scripts will be executed in the order they're specified unless the `async` 4594 option is `true`, in which case they'll be loaded in parallel and executed 4595 in whatever order they finish loading. 4596 4597 @example 4598 4599 // Load a single JS file and log a message on completion. 4600 Y.Get.js('foo.js', function (err) { 4601 if (err) { 4602 Y.log('foo.js failed to load!'); 4603 } else { 4604 Y.log('foo.js was loaded successfully'); 4605 } 4606 }); 4607 4608 // Load multiple JS files, execute them in order, and log a message when 4609 // all have finished loading. 4610 var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js']; 4611 4612 Y.Get.js(urls, function (err) { 4613 if (err) { 4614 Y.log('one or more files failed to load!'); 4615 } else { 4616 Y.log('all files loaded successfully'); 4617 } 4618 }); 4619 4620 // Specify transaction-level options, which will apply to all requests 4621 // within the transaction. 4622 Y.Get.js(urls, { 4623 attributes: {'class': 'my-js'}, 4624 timeout : 5000 4625 }); 4626 4627 // Specify per-request options, which override transaction-level and 4628 // default options. 4629 Y.Get.js([ 4630 {url: 'foo.js', attributes: {id: 'foo'}}, 4631 {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}} 4632 ]); 4633 4634 @method js 4635 @param {String|Object|Array} urls URL string, request object, or array 4636 of URLs and/or request objects to load. 4637 @param {Object} [options] Options for this transaction. See the 4638 `Y.Get.options` property for a complete list of available options. 4639 @param {Function} [callback] Callback function to be called on completion. 4640 This is a general callback and will be called before any more granular 4641 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4642 object. 4643 4644 @param {Array|null} callback.err Array of errors that occurred during 4645 the transaction, or `null` on success. 4646 @param {Get.Transaction} callback.transaction Transaction object. 4647 4648 @return {Get.Transaction} Transaction object. 4649 @since 3.5.0 4650 @static 4651 **/ 4652 js: function (urls, options, callback) { 4653 return this._load('js', urls, options, callback); 4654 }, 4655 4656 /** 4657 Loads one or more CSS and/or JavaScript resources in the same transaction. 4658 4659 Use this method when you want to load both CSS and JavaScript in a single 4660 transaction and be notified when all requested URLs have finished loading, 4661 regardless of type. 4662 4663 Behavior and options are the same as for the `css()` and `js()` methods. If 4664 a resource type isn't specified in per-request options or transaction-level 4665 options, Get will guess the file type based on the URL's extension (`.css` 4666 or `.js`, with or without a following query string). If the file type can't 4667 be guessed from the URL, a warning will be logged and Get will assume the 4668 URL is a JavaScript resource. 4669 4670 @example 4671 4672 // Load both CSS and JS files in a single transaction, and log a message 4673 // when all files have finished loading. 4674 Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) { 4675 if (err) { 4676 Y.log('one or more files failed to load!'); 4677 } else { 4678 Y.log('all files loaded successfully'); 4679 } 4680 }); 4681 4682 @method load 4683 @param {String|Object|Array} urls URL string, request object, or array 4684 of URLs and/or request objects to load. 4685 @param {Object} [options] Options for this transaction. See the 4686 `Y.Get.options` property for a complete list of available options. 4687 @param {Function} [callback] Callback function to be called on completion. 4688 This is a general callback and will be called before any more granular 4689 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4690 object. 4691 4692 @param {Array|null} err Array of errors that occurred during the 4693 transaction, or `null` on success. 4694 @param {Get.Transaction} Transaction object. 4695 4696 @return {Get.Transaction} Transaction object. 4697 @since 3.5.0 4698 @static 4699 **/ 4700 load: function (urls, options, callback) { 4701 return this._load(null, urls, options, callback); 4702 }, 4703 4704 // -- Protected Methods ---------------------------------------------------- 4705 4706 /** 4707 Triggers an automatic purge if the purge threshold has been reached. 4708 4709 @method _autoPurge 4710 @param {Number} threshold Purge threshold to use, in milliseconds. 4711 @protected 4712 @since 3.5.0 4713 @static 4714 **/ 4715 _autoPurge: function (threshold) { 4716 if (threshold && this._purgeNodes.length >= threshold) { 4717 Y.log('autopurge triggered after ' + this._purgeNodes.length + ' nodes', 'info', 'get'); 4718 this._purge(this._purgeNodes); 4719 } 4720 }, 4721 4722 /** 4723 Populates the `_env` property with information about the current 4724 environment. 4725 4726 @method _getEnv 4727 @return {Object} Environment information. 4728 @protected 4729 @since 3.5.0 4730 @static 4731 **/ 4732 _getEnv: function () { 4733 var doc = Y.config.doc, 4734 ua = Y.UA; 4735 4736 // Note: some of these checks require browser sniffs since it's not 4737 // feasible to load test files on every pageview just to perform a 4738 // feature test. I'm sorry if this makes you sad. 4739 return (this._env = { 4740 4741 // True if this is a browser that supports disabling async mode on 4742 // dynamically created script nodes. See 4743 // https://developer.mozilla.org/En/HTML/Element/Script#Attributes 4744 4745 // IE10 doesn't return true for the MDN feature test, so setting it explicitly, 4746 // because it is async by default, and allows you to disable async by setting it to false 4747 async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10), 4748 4749 // True if this browser fires an event when a dynamically injected 4750 // link node fails to load. This is currently true for Firefox 9+ 4751 // and WebKit 535.24+ 4752 cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0, 4753 4754 // True if this browser fires an event when a dynamically injected 4755 // link node finishes loading. This is currently true for IE, Opera, 4756 // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the 4757 // DOM 0 "onload" event, but not "load". All versions of IE fire 4758 // "onload". 4759 // davglass: Seems that Chrome on Android needs this to be false. 4760 cssLoad: ( 4761 (!ua.gecko && !ua.webkit) || ua.gecko >= 9 || 4762 ua.compareVersions(ua.webkit, 535.24) >= 0 4763 ) && !(ua.chrome && ua.chrome <= 18), 4764 4765 // True if this browser preserves script execution order while 4766 // loading scripts in parallel as long as the script node's `async` 4767 // attribute is set to false to explicitly disable async execution. 4768 preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10)) 4769 }); 4770 }, 4771 4772 _getTransaction: function (urls, options) { 4773 var requests = [], 4774 i, len, req, url; 4775 4776 if (!Lang.isArray(urls)) { 4777 urls = [urls]; 4778 } 4779 4780 options = Y.merge(this.options, options); 4781 4782 // Clone the attributes object so we don't end up modifying it by ref. 4783 options.attributes = Y.merge(this.options.attributes, 4784 options.attributes); 4785 4786 for (i = 0, len = urls.length; i < len; ++i) { 4787 url = urls[i]; 4788 req = {attributes: {}}; 4789 4790 // If `url` is a string, we create a URL object for it, then mix in 4791 // global options and request-specific options. If it's an object 4792 // with a "url" property, we assume it's a request object containing 4793 // URL-specific options. 4794 if (typeof url === 'string') { 4795 req.url = url; 4796 } else if (url.url) { 4797 // URL-specific options override both global defaults and 4798 // request-specific options. 4799 Y.mix(req, url, false, null, 0, true); 4800 url = url.url; // Make url a string so we can use it later. 4801 } else { 4802 Y.log('URL must be a string or an object with a `url` property.', 'error', 'get'); 4803 continue; 4804 } 4805 4806 Y.mix(req, options, false, null, 0, true); 4807 4808 // If we didn't get an explicit type for this URL either in the 4809 // request options or the URL-specific options, try to determine 4810 // one from the file extension. 4811 if (!req.type) { 4812 if (this.REGEX_CSS.test(url)) { 4813 req.type = 'css'; 4814 } else { 4815 if (!this.REGEX_JS.test(url)) { 4816 Y.log("Can't guess file type from URL. Assuming JS: " + url, 'warn', 'get'); 4817 } 4818 4819 req.type = 'js'; 4820 } 4821 } 4822 4823 // Mix in type-specific default options, but don't overwrite any 4824 // options that have already been set. 4825 Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions, 4826 false, null, 0, true); 4827 4828 // Give the node an id attribute if it doesn't already have one. 4829 req.attributes.id || (req.attributes.id = Y.guid()); 4830 4831 // Backcompat for <3.5.0 behavior. 4832 if (req.win) { 4833 Y.log('The `win` option is deprecated as of 3.5.0. Use `doc` instead.', 'warn', 'get'); 4834 req.doc = req.win.document; 4835 } else { 4836 req.win = req.doc.defaultView || req.doc.parentWindow; 4837 } 4838 4839 if (req.charset) { 4840 Y.log('The `charset` option is deprecated as of 3.5.0. Set `attributes.charset` instead.', 'warn', 'get'); 4841 req.attributes.charset = req.charset; 4842 } 4843 4844 requests.push(req); 4845 } 4846 4847 return new Transaction(requests, options); 4848 }, 4849 4850 _load: function (type, urls, options, callback) { 4851 var transaction; 4852 4853 // Allow callback as third param. 4854 if (typeof options === 'function') { 4855 callback = options; 4856 options = {}; 4857 } 4858 4859 options || (options = {}); 4860 options.type = type; 4861 4862 options._onFinish = Get._onTransactionFinish; 4863 4864 if (!this._env) { 4865 this._getEnv(); 4866 } 4867 4868 transaction = this._getTransaction(urls, options); 4869 4870 this._queue.push({ 4871 callback : callback, 4872 transaction: transaction 4873 }); 4874 4875 this._next(); 4876 4877 return transaction; 4878 }, 4879 4880 _onTransactionFinish : function() { 4881 Get._pending = null; 4882 Get._next(); 4883 }, 4884 4885 _next: function () { 4886 var item; 4887 4888 if (this._pending) { 4889 return; 4890 } 4891 4892 item = this._queue.shift(); 4893 4894 if (item) { 4895 this._pending = item; 4896 item.transaction.execute(item.callback); 4897 } 4898 }, 4899 4900 _purge: function (nodes) { 4901 var purgeNodes = this._purgeNodes, 4902 isTransaction = nodes !== purgeNodes, 4903 index, node; 4904 4905 while (node = nodes.pop()) { // assignment 4906 // Don't purge nodes that haven't finished loading (or errored out), 4907 // since this can hang the transaction. 4908 if (!node._yuiget_finished) { 4909 continue; 4910 } 4911 4912 node.parentNode && node.parentNode.removeChild(node); 4913 4914 // If this is a transaction-level purge and this node also exists in 4915 // the Get-level _purgeNodes array, we need to remove it from 4916 // _purgeNodes to avoid creating a memory leak. The indexOf lookup 4917 // sucks, but until we get WeakMaps, this is the least troublesome 4918 // way to do this (we can't just hold onto node ids because they may 4919 // not be in the same document). 4920 if (isTransaction) { 4921 index = Y.Array.indexOf(purgeNodes, node); 4922 4923 if (index > -1) { 4924 purgeNodes.splice(index, 1); 4925 } 4926 } 4927 } 4928 } 4929 }; 4930 4931 /** 4932 Alias for `js()`. 4933 4934 @method script 4935 @static 4936 **/ 4937 Get.script = Get.js; 4938 4939 /** 4940 Represents a Get transaction, which may contain requests for one or more JS or 4941 CSS files. 4942 4943 This class should not be instantiated manually. Instances will be created and 4944 returned as needed by Y.Get's `css()`, `js()`, and `load()` methods. 4945 4946 @class Get.Transaction 4947 @constructor 4948 @since 3.5.0 4949 **/ 4950 Get.Transaction = Transaction = function (requests, options) { 4951 var self = this; 4952 4953 self.id = Transaction._lastId += 1; 4954 self.data = options.data; 4955 self.errors = []; 4956 self.nodes = []; 4957 self.options = options; 4958 self.requests = requests; 4959 4960 self._callbacks = []; // callbacks to call after execution finishes 4961 self._queue = []; 4962 self._reqsWaiting = 0; 4963 4964 // Deprecated pre-3.5.0 properties. 4965 self.tId = self.id; // Use `id` instead. 4966 self.win = options.win || Y.config.win; 4967 }; 4968 4969 /** 4970 Arbitrary data object associated with this transaction. 4971 4972 This object comes from the options passed to `Get.css()`, `Get.js()`, or 4973 `Get.load()`, and will be `undefined` if no data object was specified. 4974 4975 @property {Object} data 4976 **/ 4977 4978 /** 4979 Array of errors that have occurred during this transaction, if any. Each error 4980 object has the following properties: 4981 `errors.error`: Error message. 4982 `errors.request`: Request object related to the error. 4983 4984 @since 3.5.0 4985 @property {Object[]} errors 4986 **/ 4987 4988 /** 4989 Numeric id for this transaction, unique among all transactions within the same 4990 YUI sandbox in the current pageview. 4991 4992 @property {Number} id 4993 @since 3.5.0 4994 **/ 4995 4996 /** 4997 HTMLElement nodes (native ones, not YUI Node instances) that have been inserted 4998 during the current transaction. 4999 5000 @property {HTMLElement[]} nodes 5001 **/ 5002 5003 /** 5004 Options associated with this transaction. 5005 5006 See `Get.options` for the full list of available options. 5007 5008 @property {Object} options 5009 @since 3.5.0 5010 **/ 5011 5012 /** 5013 Request objects contained in this transaction. Each request object represents 5014 one CSS or JS URL that will be (or has been) requested and loaded into the page. 5015 5016 @property {Object} requests 5017 @since 3.5.0 5018 **/ 5019 5020 /** 5021 Id of the most recent transaction. 5022 5023 @property _lastId 5024 @type Number 5025 @protected 5026 @static 5027 **/ 5028 Transaction._lastId = 0; 5029 5030 Transaction.prototype = { 5031 // -- Public Properties ---------------------------------------------------- 5032 5033 /** 5034 Current state of this transaction. One of "new", "executing", or "done". 5035 5036 @property _state 5037 @type String 5038 @protected 5039 **/ 5040 _state: 'new', // "new", "executing", or "done" 5041 5042 // -- Public Methods ------------------------------------------------------- 5043 5044 /** 5045 Aborts this transaction. 5046 5047 This will cause the transaction's `onFailure` callback to be called and 5048 will prevent any new script and link nodes from being added to the document, 5049 but any resources that have already been requested will continue loading 5050 (there's no safe way to prevent this, unfortunately). 5051 5052 @method abort 5053 @param {String} [msg="Aborted."] Optional message to use in the `errors` 5054 array describing why the transaction was aborted. 5055 **/ 5056 abort: function (msg) { 5057 this._pending = null; 5058 this._pendingCSS = null; 5059 this._pollTimer = clearTimeout(this._pollTimer); 5060 this._queue = []; 5061 this._reqsWaiting = 0; 5062 5063 this.errors.push({error: msg || 'Aborted'}); 5064 this._finish(); 5065 }, 5066 5067 /** 5068 Begins execting the transaction. 5069 5070 There's usually no reason to call this manually, since Get will call it 5071 automatically when other pending transactions have finished. If you really 5072 want to execute your transaction before Get does, you can, but be aware that 5073 this transaction's scripts may end up executing before the scripts in other 5074 pending transactions. 5075 5076 If the transaction is already executing, the specified callback (if any) 5077 will be queued and called after execution finishes. If the transaction has 5078 already finished, the callback will be called immediately (the transaction 5079 will not be executed again). 5080 5081 @method execute 5082 @param {Function} callback Callback function to execute after all requests 5083 in the transaction are complete, or after the transaction is aborted. 5084 **/ 5085 execute: function (callback) { 5086 var self = this, 5087 requests = self.requests, 5088 state = self._state, 5089 i, len, queue, req; 5090 5091 if (state === 'done') { 5092 callback && callback(self.errors.length ? self.errors : null, self); 5093 return; 5094 } else { 5095 callback && self._callbacks.push(callback); 5096 5097 if (state === 'executing') { 5098 return; 5099 } 5100 } 5101 5102 self._state = 'executing'; 5103 self._queue = queue = []; 5104 5105 if (self.options.timeout) { 5106 self._timeout = setTimeout(function () { 5107 self.abort('Timeout'); 5108 }, self.options.timeout); 5109 } 5110 5111 self._reqsWaiting = requests.length; 5112 5113 for (i = 0, len = requests.length; i < len; ++i) { 5114 req = requests[i]; 5115 5116 if (req.async || req.type === 'css') { 5117 // No need to queue CSS or fully async JS. 5118 self._insert(req); 5119 } else { 5120 queue.push(req); 5121 } 5122 } 5123 5124 self._next(); 5125 }, 5126 5127 /** 5128 Manually purges any `<script>` or `<link>` nodes this transaction has 5129 created. 5130 5131 Be careful when purging a transaction that contains CSS requests, since 5132 removing `<link>` nodes will also remove any styles they applied. 5133 5134 @method purge 5135 **/ 5136 purge: function () { 5137 Get._purge(this.nodes); 5138 }, 5139 5140 // -- Protected Methods ---------------------------------------------------- 5141 _createNode: function (name, attrs, doc) { 5142 var node = doc.createElement(name), 5143 attr, testEl; 5144 5145 if (!CUSTOM_ATTRS) { 5146 // IE6 and IE7 expect property names rather than attribute names for 5147 // certain attributes. Rather than sniffing, we do a quick feature 5148 // test the first time _createNode() runs to determine whether we 5149 // need to provide a workaround. 5150 testEl = doc.createElement('div'); 5151 testEl.setAttribute('class', 'a'); 5152 5153 CUSTOM_ATTRS = testEl.className === 'a' ? {} : { 5154 'for' : 'htmlFor', 5155 'class': 'className' 5156 }; 5157 } 5158 5159 for (attr in attrs) { 5160 if (attrs.hasOwnProperty(attr)) { 5161 node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]); 5162 } 5163 } 5164 5165 return node; 5166 }, 5167 5168 _finish: function () { 5169 var errors = this.errors.length ? this.errors : null, 5170 options = this.options, 5171 thisObj = options.context || this, 5172 data, i, len; 5173 5174 if (this._state === 'done') { 5175 return; 5176 } 5177 5178 this._state = 'done'; 5179 5180 for (i = 0, len = this._callbacks.length; i < len; ++i) { 5181 this._callbacks[i].call(thisObj, errors, this); 5182 } 5183 5184 data = this._getEventData(); 5185 5186 if (errors) { 5187 if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') { 5188 options.onTimeout.call(thisObj, data); 5189 } 5190 5191 if (options.onFailure) { 5192 options.onFailure.call(thisObj, data); 5193 } 5194 } else if (options.onSuccess) { 5195 options.onSuccess.call(thisObj, data); 5196 } 5197 5198 if (options.onEnd) { 5199 options.onEnd.call(thisObj, data); 5200 } 5201 5202 if (options._onFinish) { 5203 options._onFinish(); 5204 } 5205 }, 5206 5207 _getEventData: function (req) { 5208 if (req) { 5209 // This merge is necessary for backcompat. I hate it. 5210 return Y.merge(this, { 5211 abort : this.abort, // have to copy these because the prototype isn't preserved 5212 purge : this.purge, 5213 request: req, 5214 url : req.url, 5215 win : req.win 5216 }); 5217 } else { 5218 return this; 5219 } 5220 }, 5221 5222 _getInsertBefore: function (req) { 5223 var doc = req.doc, 5224 el = req.insertBefore, 5225 cache, docStamp; 5226 5227 if (el) { 5228 return typeof el === 'string' ? doc.getElementById(el) : el; 5229 } 5230 5231 cache = Get._insertCache; 5232 docStamp = Y.stamp(doc); 5233 5234 if ((el = cache[docStamp])) { // assignment 5235 return el; 5236 } 5237 5238 // Inserting before a <base> tag apparently works around an IE bug 5239 // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what 5240 // bug that is, exactly. Better safe than sorry? 5241 if ((el = doc.getElementsByTagName('base')[0])) { // assignment 5242 return (cache[docStamp] = el); 5243 } 5244 5245 // Look for a <head> element. 5246 el = doc.head || doc.getElementsByTagName('head')[0]; 5247 5248 if (el) { 5249 // Create a marker node at the end of <head> to use as an insertion 5250 // point. Inserting before this node will ensure that all our CSS 5251 // gets inserted in the correct order, to maintain style precedence. 5252 el.appendChild(doc.createTextNode('')); 5253 return (cache[docStamp] = el.lastChild); 5254 } 5255 5256 // If all else fails, just insert before the first script node on the 5257 // page, which is virtually guaranteed to exist. 5258 return (cache[docStamp] = doc.getElementsByTagName('script')[0]); 5259 }, 5260 5261 _insert: function (req) { 5262 var env = Get._env, 5263 insertBefore = this._getInsertBefore(req), 5264 isScript = req.type === 'js', 5265 node = req.node, 5266 self = this, 5267 ua = Y.UA, 5268 cssTimeout, nodeType; 5269 5270 if (!node) { 5271 if (isScript) { 5272 nodeType = 'script'; 5273 } else if (!env.cssLoad && ua.gecko) { 5274 nodeType = 'style'; 5275 } else { 5276 nodeType = 'link'; 5277 } 5278 5279 node = req.node = this._createNode(nodeType, req.attributes, 5280 req.doc); 5281 } 5282 5283 function onError() { 5284 self._progress('Failed to load ' + req.url, req); 5285 } 5286 5287 function onLoad() { 5288 if (cssTimeout) { 5289 clearTimeout(cssTimeout); 5290 } 5291 5292 self._progress(null, req); 5293 } 5294 5295 // Deal with script asynchronicity. 5296 if (isScript) { 5297 node.setAttribute('src', req.url); 5298 5299 if (req.async) { 5300 // Explicitly indicate that we want the browser to execute this 5301 // script asynchronously. This is necessary for older browsers 5302 // like Firefox <4. 5303 node.async = true; 5304 } else { 5305 if (env.async) { 5306 // This browser treats injected scripts as async by default 5307 // (standard HTML5 behavior) but asynchronous loading isn't 5308 // desired, so tell the browser not to mark this script as 5309 // async. 5310 node.async = false; 5311 } 5312 5313 // If this browser doesn't preserve script execution order based 5314 // on insertion order, we'll need to avoid inserting other 5315 // scripts until this one finishes loading. 5316 if (!env.preservesScriptOrder) { 5317 this._pending = req; 5318 } 5319 } 5320 } else { 5321 if (!env.cssLoad && ua.gecko) { 5322 // In Firefox <9, we can import the requested URL into a <style> 5323 // node and poll for the existence of node.sheet.cssRules. This 5324 // gives us a reliable way to determine CSS load completion that 5325 // also works for cross-domain stylesheets. 5326 // 5327 // Props to Zach Leatherman for calling my attention to this 5328 // technique. 5329 node.innerHTML = (req.attributes.charset ? 5330 '@charset "' + req.attributes.charset + '";' : '') + 5331 '@import "' + req.url + '";'; 5332 } else { 5333 node.setAttribute('href', req.url); 5334 } 5335 } 5336 5337 // Inject the node. 5338 if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) { 5339 // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode. 5340 node.onreadystatechange = function () { 5341 if (/loaded|complete/.test(node.readyState)) { 5342 node.onreadystatechange = null; 5343 onLoad(); 5344 } 5345 }; 5346 } else if (!isScript && !env.cssLoad) { 5347 // CSS on Firefox <9 or WebKit. 5348 this._poll(req); 5349 } else { 5350 // Script or CSS on everything else. Using DOM 0 events because that 5351 // evens the playing field with older IEs. 5352 5353 if (ua.ie >= 10) { 5354 5355 // We currently need to introduce a timeout for IE10, since it 5356 // calls onerror/onload synchronously for 304s - messing up existing 5357 // program flow. 5358 5359 // Remove this block if the following bug gets fixed by GA 5360 /*jshint maxlen: 1500 */ 5361 // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload 5362 node.onerror = function() { setTimeout(onError, 0); }; 5363 node.onload = function() { setTimeout(onLoad, 0); }; 5364 } else { 5365 node.onerror = onError; 5366 node.onload = onLoad; 5367 } 5368 5369 // If this browser doesn't fire an event when CSS fails to load, 5370 // fail after a timeout to avoid blocking the transaction queue. 5371 if (!env.cssFail && !isScript) { 5372 cssTimeout = setTimeout(onError, req.timeout || 3000); 5373 } 5374 } 5375 5376 this.nodes.push(node); 5377 insertBefore.parentNode.insertBefore(node, insertBefore); 5378 }, 5379 5380 _next: function () { 5381 if (this._pending) { 5382 return; 5383 } 5384 5385 // If there are requests in the queue, insert the next queued request. 5386 // Otherwise, if we're waiting on already-inserted requests to finish, 5387 // wait longer. If there are no queued requests and we're not waiting 5388 // for anything to load, then we're done! 5389 if (this._queue.length) { 5390 this._insert(this._queue.shift()); 5391 } else if (!this._reqsWaiting) { 5392 this._finish(); 5393 } 5394 }, 5395 5396 _poll: function (newReq) { 5397 var self = this, 5398 pendingCSS = self._pendingCSS, 5399 isWebKit = Y.UA.webkit, 5400 i, hasRules, j, nodeHref, req, sheets; 5401 5402 if (newReq) { 5403 pendingCSS || (pendingCSS = self._pendingCSS = []); 5404 pendingCSS.push(newReq); 5405 5406 if (self._pollTimer) { 5407 // A poll timeout is already pending, so no need to create a 5408 // new one. 5409 return; 5410 } 5411 } 5412 5413 self._pollTimer = null; 5414 5415 // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s 5416 // will still be treated as a success. There's no good workaround for 5417 // this. 5418 5419 for (i = 0; i < pendingCSS.length; ++i) { 5420 req = pendingCSS[i]; 5421 5422 if (isWebKit) { 5423 // Look for a stylesheet matching the pending URL. 5424 sheets = req.doc.styleSheets; 5425 j = sheets.length; 5426 nodeHref = req.node.href; 5427 5428 while (--j >= 0) { 5429 if (sheets[j].href === nodeHref) { 5430 pendingCSS.splice(i, 1); 5431 i -= 1; 5432 self._progress(null, req); 5433 break; 5434 } 5435 } 5436 } else { 5437 // Many thanks to Zach Leatherman for calling my attention to 5438 // the @import-based cross-domain technique used here, and to 5439 // Oleg Slobodskoi for an earlier same-domain implementation. 5440 // 5441 // See Zach's blog for more details: 5442 // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/ 5443 try { 5444 // We don't really need to store this value since we never 5445 // use it again, but if we don't store it, Closure Compiler 5446 // assumes the code is useless and removes it. 5447 hasRules = !!req.node.sheet.cssRules; 5448 5449 // If we get here, the stylesheet has loaded. 5450 pendingCSS.splice(i, 1); 5451 i -= 1; 5452 self._progress(null, req); 5453 } catch (ex) { 5454 // An exception means the stylesheet is still loading. 5455 } 5456 } 5457 } 5458 5459 if (pendingCSS.length) { 5460 self._pollTimer = setTimeout(function () { 5461 self._poll.call(self); 5462 }, self.options.pollInterval); 5463 } 5464 }, 5465 5466 _progress: function (err, req) { 5467 var options = this.options; 5468 5469 if (err) { 5470 req.error = err; 5471 5472 this.errors.push({ 5473 error : err, 5474 request: req 5475 }); 5476 5477 Y.log(err, 'error', 'get'); 5478 } 5479 5480 req.node._yuiget_finished = req.finished = true; 5481 5482 if (options.onProgress) { 5483 options.onProgress.call(options.context || this, 5484 this._getEventData(req)); 5485 } 5486 5487 if (req.autopurge) { 5488 // Pre-3.5.0 Get always excludes the most recent node from an 5489 // autopurge. I find this odd, but I'm keeping that behavior for 5490 // the sake of backcompat. 5491 Get._autoPurge(this.options.purgethreshold); 5492 Get._purgeNodes.push(req.node); 5493 } 5494 5495 if (this._pending === req) { 5496 this._pending = null; 5497 } 5498 5499 this._reqsWaiting -= 1; 5500 5501 this._next(); 5502 } 5503 }; 5504 5505 5506 }, '3.17.2', {"requires": ["yui-base"]}); 5507 YUI.add('features', function (Y, NAME) { 5508 5509 var feature_tests = {}; 5510 5511 /** 5512 Contains the core of YUI's feature test architecture. 5513 @module features 5514 */ 5515 5516 /** 5517 * Feature detection 5518 * @class Features 5519 * @static 5520 */ 5521 5522 Y.mix(Y.namespace('Features'), { 5523 5524 /** 5525 * Object hash of all registered feature tests 5526 * @property tests 5527 * @type Object 5528 */ 5529 tests: feature_tests, 5530 5531 /** 5532 * Add a test to the system 5533 * 5534 * ``` 5535 * Y.Features.add("load", "1", {}); 5536 * ``` 5537 * 5538 * @method add 5539 * @param {String} cat The category, right now only 'load' is supported 5540 * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3 5541 * @param {Object} o Object containing test properties 5542 * @param {String} o.name The name of the test 5543 * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance 5544 * @param {String} o.trigger The module that triggers this test. 5545 */ 5546 add: function(cat, name, o) { 5547 feature_tests[cat] = feature_tests[cat] || {}; 5548 feature_tests[cat][name] = o; 5549 }, 5550 /** 5551 * Execute all tests of a given category and return the serialized results 5552 * 5553 * ``` 5554 * caps=1:1;2:1;3:0 5555 * ``` 5556 * @method all 5557 * @param {String} cat The category to execute 5558 * @param {Array} args The arguments to pass to the test function 5559 * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0 5560 */ 5561 all: function(cat, args) { 5562 var cat_o = feature_tests[cat], 5563 // results = {}; 5564 result = []; 5565 if (cat_o) { 5566 Y.Object.each(cat_o, function(v, k) { 5567 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0)); 5568 }); 5569 } 5570 5571 return (result.length) ? result.join(';') : ''; 5572 }, 5573 /** 5574 * Run a specific test and return a Boolean response. 5575 * 5576 * ``` 5577 * Y.Features.test("load", "1"); 5578 * ``` 5579 * 5580 * @method test 5581 * @param {String} cat The category of the test to run 5582 * @param {String} name The name of the test to run 5583 * @param {Array} args The arguments to pass to the test function 5584 * @return {Boolean} True or false if the test passed/failed. 5585 */ 5586 test: function(cat, name, args) { 5587 args = args || []; 5588 var result, ua, test, 5589 cat_o = feature_tests[cat], 5590 feature = cat_o && cat_o[name]; 5591 5592 if (!feature) { 5593 Y.log('Feature test ' + cat + ', ' + name + ' not found'); 5594 } else { 5595 5596 result = feature.result; 5597 5598 if (Y.Lang.isUndefined(result)) { 5599 5600 ua = feature.ua; 5601 if (ua) { 5602 result = (Y.UA[ua]); 5603 } 5604 5605 test = feature.test; 5606 if (test && ((!ua) || result)) { 5607 result = test.apply(Y, args); 5608 } 5609 5610 feature.result = result; 5611 } 5612 } 5613 5614 return result; 5615 } 5616 }); 5617 5618 // Y.Features.add("load", "1", {}); 5619 // Y.Features.test("load", "1"); 5620 // caps=1:1;2:0;3:1; 5621 5622 /* This file is auto-generated by (yogi.js loader --mix --yes) */ 5623 /*jshint maxlen:900, eqeqeq: false */ 5624 var add = Y.Features.add; 5625 // app-transitions-native 5626 add('load', '0', { 5627 "name": "app-transitions-native", 5628 "test": function (Y) { 5629 var doc = Y.config.doc, 5630 node = doc ? doc.documentElement : null; 5631 5632 if (node && node.style) { 5633 return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 5634 } 5635 5636 return false; 5637 }, 5638 "trigger": "app-transitions" 5639 }); 5640 // autocomplete-list-keys 5641 add('load', '1', { 5642 "name": "autocomplete-list-keys", 5643 "test": function (Y) { 5644 // Only add keyboard support to autocomplete-list if this doesn't appear to 5645 // be an iOS or Android-based mobile device. 5646 // 5647 // There's currently no feasible way to actually detect whether a device has 5648 // a hardware keyboard, so this sniff will have to do. It can easily be 5649 // overridden by manually loading the autocomplete-list-keys module. 5650 // 5651 // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari 5652 // doesn't fire the keyboard events used by AutoCompleteList, so there's 5653 // no point loading the -keys module even when a bluetooth keyboard may be 5654 // available. 5655 return !(Y.UA.ios || Y.UA.android); 5656 }, 5657 "trigger": "autocomplete-list" 5658 }); 5659 // dd-gestures 5660 add('load', '2', { 5661 "name": "dd-gestures", 5662 "trigger": "dd-drag", 5663 "ua": "touchEnabled" 5664 }); 5665 // dom-style-ie 5666 add('load', '3', { 5667 "name": "dom-style-ie", 5668 "test": function (Y) { 5669 5670 var testFeature = Y.Features.test, 5671 addFeature = Y.Features.add, 5672 WINDOW = Y.config.win, 5673 DOCUMENT = Y.config.doc, 5674 DOCUMENT_ELEMENT = 'documentElement', 5675 ret = false; 5676 5677 addFeature('style', 'computedStyle', { 5678 test: function() { 5679 return WINDOW && 'getComputedStyle' in WINDOW; 5680 } 5681 }); 5682 5683 addFeature('style', 'opacity', { 5684 test: function() { 5685 return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style; 5686 } 5687 }); 5688 5689 ret = (!testFeature('style', 'opacity') && 5690 !testFeature('style', 'computedStyle')); 5691 5692 return ret; 5693 }, 5694 "trigger": "dom-style" 5695 }); 5696 // editor-para-ie 5697 add('load', '4', { 5698 "name": "editor-para-ie", 5699 "trigger": "editor-para", 5700 "ua": "ie", 5701 "when": "instead" 5702 }); 5703 // event-base-ie 5704 add('load', '5', { 5705 "name": "event-base-ie", 5706 "test": function(Y) { 5707 var imp = Y.config.doc && Y.config.doc.implementation; 5708 return (imp && (!imp.hasFeature('Events', '2.0'))); 5709 }, 5710 "trigger": "node-base" 5711 }); 5712 // graphics-canvas 5713 add('load', '6', { 5714 "name": "graphics-canvas", 5715 "test": function(Y) { 5716 var DOCUMENT = Y.config.doc, 5717 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 5718 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5719 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5720 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 5721 }, 5722 "trigger": "graphics" 5723 }); 5724 // graphics-canvas-default 5725 add('load', '7', { 5726 "name": "graphics-canvas-default", 5727 "test": function(Y) { 5728 var DOCUMENT = Y.config.doc, 5729 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 5730 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5731 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5732 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 5733 }, 5734 "trigger": "graphics" 5735 }); 5736 // graphics-svg 5737 add('load', '8', { 5738 "name": "graphics-svg", 5739 "test": function(Y) { 5740 var DOCUMENT = Y.config.doc, 5741 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 5742 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5743 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5744 5745 return svg && (useSVG || !canvas); 5746 }, 5747 "trigger": "graphics" 5748 }); 5749 // graphics-svg-default 5750 add('load', '9', { 5751 "name": "graphics-svg-default", 5752 "test": function(Y) { 5753 var DOCUMENT = Y.config.doc, 5754 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 5755 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5756 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5757 5758 return svg && (useSVG || !canvas); 5759 }, 5760 "trigger": "graphics" 5761 }); 5762 // graphics-vml 5763 add('load', '10', { 5764 "name": "graphics-vml", 5765 "test": function(Y) { 5766 var DOCUMENT = Y.config.doc, 5767 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 5768 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 5769 }, 5770 "trigger": "graphics" 5771 }); 5772 // graphics-vml-default 5773 add('load', '11', { 5774 "name": "graphics-vml-default", 5775 "test": function(Y) { 5776 var DOCUMENT = Y.config.doc, 5777 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 5778 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 5779 }, 5780 "trigger": "graphics" 5781 }); 5782 // history-hash-ie 5783 add('load', '12', { 5784 "name": "history-hash-ie", 5785 "test": function (Y) { 5786 var docMode = Y.config.doc && Y.config.doc.documentMode; 5787 5788 return Y.UA.ie && (!('onhashchange' in Y.config.win) || 5789 !docMode || docMode < 8); 5790 }, 5791 "trigger": "history-hash" 5792 }); 5793 // io-nodejs 5794 add('load', '13', { 5795 "name": "io-nodejs", 5796 "trigger": "io-base", 5797 "ua": "nodejs" 5798 }); 5799 // json-parse-shim 5800 add('load', '14', { 5801 "name": "json-parse-shim", 5802 "test": function (Y) { 5803 var _JSON = Y.config.global.JSON, 5804 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 5805 nativeSupport = Y.config.useNativeJSONParse !== false && !!Native; 5806 5807 function workingNative( k, v ) { 5808 return k === "ok" ? true : v; 5809 } 5810 5811 // Double check basic functionality. This is mainly to catch early broken 5812 // implementations of the JSON API in Firefox 3.1 beta1 and beta2 5813 if ( nativeSupport ) { 5814 try { 5815 nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok; 5816 } 5817 catch ( e ) { 5818 nativeSupport = false; 5819 } 5820 } 5821 5822 return !nativeSupport; 5823 }, 5824 "trigger": "json-parse" 5825 }); 5826 // json-stringify-shim 5827 add('load', '15', { 5828 "name": "json-stringify-shim", 5829 "test": function (Y) { 5830 var _JSON = Y.config.global.JSON, 5831 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 5832 nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native; 5833 5834 // Double check basic native functionality. This is primarily to catch broken 5835 // early JSON API implementations in Firefox 3.1 beta1 and beta2. 5836 if ( nativeSupport ) { 5837 try { 5838 nativeSupport = ( '0' === Native.stringify(0) ); 5839 } catch ( e ) { 5840 nativeSupport = false; 5841 } 5842 } 5843 5844 5845 return !nativeSupport; 5846 }, 5847 "trigger": "json-stringify" 5848 }); 5849 // scrollview-base-ie 5850 add('load', '16', { 5851 "name": "scrollview-base-ie", 5852 "trigger": "scrollview-base", 5853 "ua": "ie" 5854 }); 5855 // selector-css2 5856 add('load', '17', { 5857 "name": "selector-css2", 5858 "test": function (Y) { 5859 var DOCUMENT = Y.config.doc, 5860 ret = DOCUMENT && !('querySelectorAll' in DOCUMENT); 5861 5862 return ret; 5863 }, 5864 "trigger": "selector" 5865 }); 5866 // transition-timer 5867 add('load', '18', { 5868 "name": "transition-timer", 5869 "test": function (Y) { 5870 var DOCUMENT = Y.config.doc, 5871 node = (DOCUMENT) ? DOCUMENT.documentElement: null, 5872 ret = true; 5873 5874 if (node && node.style) { 5875 ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 5876 } 5877 5878 return ret; 5879 }, 5880 "trigger": "transition" 5881 }); 5882 // widget-base-ie 5883 add('load', '19', { 5884 "name": "widget-base-ie", 5885 "trigger": "widget-base", 5886 "ua": "ie" 5887 }); 5888 // yql-jsonp 5889 add('load', '20', { 5890 "name": "yql-jsonp", 5891 "test": function (Y) { 5892 /* Only load the JSONP module when not in nodejs or winjs 5893 TODO Make the winjs module a CORS module 5894 */ 5895 return (!Y.UA.nodejs && !Y.UA.winjs); 5896 }, 5897 "trigger": "yql" 5898 }); 5899 // yql-nodejs 5900 add('load', '21', { 5901 "name": "yql-nodejs", 5902 "trigger": "yql", 5903 "ua": "nodejs" 5904 }); 5905 // yql-winjs 5906 add('load', '22', { 5907 "name": "yql-winjs", 5908 "trigger": "yql", 5909 "ua": "winjs" 5910 }); 5911 5912 }, '3.17.2', {"requires": ["yui-base"]}); 5913 YUI.add('intl-base', function (Y, NAME) { 5914 5915 /** 5916 * The Intl utility provides a central location for managing sets of 5917 * localized resources (strings and formatting patterns). 5918 * 5919 * @class Intl 5920 * @uses EventTarget 5921 * @static 5922 */ 5923 5924 var SPLIT_REGEX = /[, ]/; 5925 5926 Y.mix(Y.namespace('Intl'), { 5927 5928 /** 5929 * Returns the language among those available that 5930 * best matches the preferred language list, using the Lookup 5931 * algorithm of BCP 47. 5932 * If none of the available languages meets the user's preferences, 5933 * then "" is returned. 5934 * Extended language ranges are not supported. 5935 * 5936 * @method lookupBestLang 5937 * @param {String[] | String} preferredLanguages The list of preferred 5938 * languages in descending preference order, represented as BCP 47 5939 * language tags. A string array or a comma-separated list. 5940 * @param {String[]} availableLanguages The list of languages 5941 * that the application supports, represented as BCP 47 language 5942 * tags. 5943 * 5944 * @return {String} The available language that best matches the 5945 * preferred language list, or "". 5946 * @since 3.1.0 5947 */ 5948 lookupBestLang: function(preferredLanguages, availableLanguages) { 5949 5950 var i, language, result, index; 5951 5952 // check whether the list of available languages contains language; 5953 // if so return it 5954 function scan(language) { 5955 var i; 5956 for (i = 0; i < availableLanguages.length; i += 1) { 5957 if (language.toLowerCase() === 5958 availableLanguages[i].toLowerCase()) { 5959 return availableLanguages[i]; 5960 } 5961 } 5962 } 5963 5964 if (Y.Lang.isString(preferredLanguages)) { 5965 preferredLanguages = preferredLanguages.split(SPLIT_REGEX); 5966 } 5967 5968 for (i = 0; i < preferredLanguages.length; i += 1) { 5969 language = preferredLanguages[i]; 5970 if (!language || language === '*') { 5971 continue; 5972 } 5973 // check the fallback sequence for one language 5974 while (language.length > 0) { 5975 result = scan(language); 5976 if (result) { 5977 return result; 5978 } else { 5979 index = language.lastIndexOf('-'); 5980 if (index >= 0) { 5981 language = language.substring(0, index); 5982 // one-character subtags get cut along with the 5983 // following subtag 5984 if (index >= 2 && language.charAt(index - 2) === '-') { 5985 language = language.substring(0, index - 2); 5986 } 5987 } else { 5988 // nothing available for this language 5989 break; 5990 } 5991 } 5992 } 5993 } 5994 5995 return ''; 5996 } 5997 }); 5998 5999 6000 }, '3.17.2', {"requires": ["yui-base"]}); 6001 YUI.add('yui-log', function (Y, NAME) { 6002 6003 /** 6004 * Provides console log capability and exposes a custom event for 6005 * console implementations. This module is a `core` YUI module, 6006 * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>. 6007 * 6008 * @module yui 6009 * @submodule yui-log 6010 */ 6011 6012 var INSTANCE = Y, 6013 LOGEVENT = 'yui:log', 6014 UNDEFINED = 'undefined', 6015 LEVELS = { debug: 1, 6016 info: 2, 6017 warn: 4, 6018 error: 8 }; 6019 6020 /** 6021 * If the 'debug' config is true, a 'yui:log' event will be 6022 * dispatched, which the Console widget and anything else 6023 * can consume. If the 'useBrowserConsole' config is true, it will 6024 * write to the browser console if available. YUI-specific log 6025 * messages will only be present in the -debug versions of the 6026 * JS files. The build system is supposed to remove log statements 6027 * from the raw and minified versions of the files. 6028 * 6029 * @method log 6030 * @for YUI 6031 * @param {String} msg The message to log. 6032 * @param {String} cat The log category for the message. Default 6033 * categories are "info", "warn", "error", "debug". 6034 * Custom categories can be used as well. (opt). 6035 * @param {String} src The source of the the message (opt). 6036 * @param {boolean} silent If true, the log event won't fire. 6037 * @return {YUI} YUI instance. 6038 */ 6039 INSTANCE.log = function(msg, cat, src, silent) { 6040 var bail, excl, incl, m, f, minlevel, 6041 Y = INSTANCE, 6042 c = Y.config, 6043 publisher = (Y.fire) ? Y : YUI.Env.globalEvents; 6044 // suppress log message if the config is off or the event stack 6045 // or the event call stack contains a consumer of the yui:log event 6046 if (c.debug) { 6047 // apply source filters 6048 src = src || ""; 6049 if (typeof src !== "undefined") { 6050 excl = c.logExclude; 6051 incl = c.logInclude; 6052 if (incl && !(src in incl)) { 6053 bail = 1; 6054 } else if (incl && (src in incl)) { 6055 bail = !incl[src]; 6056 } else if (excl && (src in excl)) { 6057 bail = excl[src]; 6058 } 6059 6060 // Set a default category of info if the category was not defined. 6061 if ((typeof cat === 'undefined')) { 6062 cat = 'info'; 6063 } 6064 6065 // Determine the current minlevel as defined in configuration 6066 Y.config.logLevel = Y.config.logLevel || 'debug'; 6067 minlevel = LEVELS[Y.config.logLevel.toLowerCase()]; 6068 6069 if (cat in LEVELS && LEVELS[cat] < minlevel) { 6070 // Skip this message if the we don't meet the defined minlevel 6071 bail = 1; 6072 } 6073 } 6074 if (!bail) { 6075 if (c.useBrowserConsole) { 6076 m = (src) ? src + ': ' + msg : msg; 6077 if (Y.Lang.isFunction(c.logFn)) { 6078 c.logFn.call(Y, msg, cat, src); 6079 } else if (typeof console !== UNDEFINED && console.log) { 6080 f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log'; 6081 console[f](m); 6082 } else if (typeof opera !== UNDEFINED) { 6083 opera.postError(m); 6084 } 6085 } 6086 6087 if (publisher && !silent) { 6088 6089 if (publisher === Y && (!publisher.getEvent(LOGEVENT))) { 6090 publisher.publish(LOGEVENT, { 6091 broadcast: 2 6092 }); 6093 } 6094 6095 publisher.fire(LOGEVENT, { 6096 msg: msg, 6097 cat: cat, 6098 src: src 6099 }); 6100 } 6101 } 6102 } 6103 6104 return Y; 6105 }; 6106 6107 /** 6108 * Write a system message. This message will be preserved in the 6109 * minified and raw versions of the YUI files, unlike log statements. 6110 * @method message 6111 * @for YUI 6112 * @param {String} msg The message to log. 6113 * @param {String} cat The log category for the message. Default 6114 * categories are "info", "warn", "error", "debug". 6115 * Custom categories can be used as well. (opt). 6116 * @param {String} src The source of the the message (opt). 6117 * @param {boolean} silent If true, the log event won't fire. 6118 * @return {YUI} YUI instance. 6119 */ 6120 INSTANCE.message = function() { 6121 return INSTANCE.log.apply(INSTANCE, arguments); 6122 }; 6123 6124 6125 }, '3.17.2', {"requires": ["yui-base"]}); 6126 YUI.add('yui-later', function (Y, NAME) { 6127 6128 /** 6129 * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module, 6130 * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>. 6131 * 6132 * @module yui 6133 * @submodule yui-later 6134 */ 6135 6136 var NO_ARGS = []; 6137 6138 /** 6139 * Executes the supplied function in the context of the supplied 6140 * object 'when' milliseconds later. Executes the function a 6141 * single time unless periodic is set to true. 6142 * @for YUI 6143 * @method later 6144 * @param when {Number} the number of milliseconds to wait until the fn 6145 * is executed. 6146 * @param o the context object. 6147 * @param fn {Function|String} the function to execute or the name of 6148 * the method in the 'o' object to execute. 6149 * @param data [Array] data that is provided to the function. This 6150 * accepts either a single item or an array. If an array is provided, 6151 * the function is executed with one parameter for each array item. 6152 * If you need to pass a single array parameter, it needs to be wrapped 6153 * in an array [myarray]. 6154 * 6155 * Note: native methods in IE may not have the call and apply methods. 6156 * In this case, it will work, but you are limited to four arguments. 6157 * 6158 * @param periodic {boolean} if true, executes continuously at supplied 6159 * interval until canceled. 6160 * @return {object} a timer object. Call the cancel() method on this 6161 * object to stop the timer. 6162 */ 6163 Y.later = function(when, o, fn, data, periodic) { 6164 when = when || 0; 6165 data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS; 6166 o = o || Y.config.win || Y; 6167 6168 var cancelled = false, 6169 method = (o && Y.Lang.isString(fn)) ? o[fn] : fn, 6170 wrapper = function() { 6171 // IE 8- may execute a setInterval callback one last time 6172 // after clearInterval was called, so in order to preserve 6173 // the cancel() === no more runny-run, we have to jump through 6174 // an extra hoop. 6175 if (!cancelled) { 6176 if (!method.apply) { 6177 method(data[0], data[1], data[2], data[3]); 6178 } else { 6179 method.apply(o, data || NO_ARGS); 6180 } 6181 } 6182 }, 6183 id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when); 6184 6185 return { 6186 id: id, 6187 interval: periodic, 6188 cancel: function() { 6189 cancelled = true; 6190 if (this.interval) { 6191 clearInterval(id); 6192 } else { 6193 clearTimeout(id); 6194 } 6195 } 6196 }; 6197 }; 6198 6199 Y.Lang.later = Y.later; 6200 6201 6202 6203 }, '3.17.2', {"requires": ["yui-base"]}); 6204 YUI.add('yui', function (Y, NAME) {}, '3.17.2', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
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 |