[ 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 }, 543 544 /** 545 Executes the named method on the specified YUI instance if that method is 546 whitelisted. 547 548 @method applyTo 549 @param {String} id YUI instance id. 550 @param {String} method Name of the method to execute. For example: 551 'Object.keys'. 552 @param {Array} args Arguments to apply to the method. 553 @return {Mixed} Return value from the applied method, or `null` if the 554 specified instance was not found or the method was not whitelisted. 555 **/ 556 applyTo: function(id, method, args) { 557 if (!(method in APPLY_TO_AUTH)) { 558 this.log(method + ': applyTo not allowed', 'warn', 'yui'); 559 return null; 560 } 561 562 var instance = instances[id], nest, m, i; 563 if (instance) { 564 nest = method.split('.'); 565 m = instance; 566 for (i = 0; i < nest.length; i = i + 1) { 567 m = m[nest[i]]; 568 if (!m) { 569 this.log('applyTo not found: ' + method, 'warn', 'yui'); 570 } 571 } 572 return m && m.apply(instance, args); 573 } 574 575 return null; 576 }, 577 578 /** 579 Registers a YUI module and makes it available for use in a `YUI().use()` call or 580 as a dependency for other modules. 581 582 The easiest way to create a first-class YUI module is to use 583 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build 584 tool. 585 586 Shifter will automatically wrap your module code in a `YUI.add()` call along 587 with any configuration info required for the module. 588 589 @example 590 591 YUI.add('davglass', function (Y) { 592 Y.davglass = function () { 593 }; 594 }, '3.4.0', { 595 requires: ['harley-davidson', 'mt-dew'] 596 }); 597 598 @method add 599 @param {String} name Module name. 600 @param {Function} fn Function containing module code. This function will be 601 executed whenever the module is attached to a specific YUI instance. 602 603 @param {YUI} fn.Y The YUI instance to which this module is attached. 604 @param {String} fn.name Name of the module 605 606 @param {String} version Module version number. This is currently used only for 607 informational purposes, and is not used internally by YUI. 608 609 @param {Object} [details] Module config. 610 @param {Array} [details.requires] Array of other module names that must be 611 attached before this module can be attached. 612 @param {Array} [details.optional] Array of optional module names that should 613 be attached before this module is attached if they've already been 614 loaded. If the `loadOptional` YUI option is `true`, optional modules 615 that have not yet been loaded will be loaded just as if they were hard 616 requirements. 617 @param {Array} [details.use] Array of module names that are included within 618 or otherwise provided by this module, and which should be attached 619 automatically when this module is attached. This makes it possible to 620 create "virtual rollup" modules that simply attach a collection of other 621 modules or submodules. 622 623 @return {YUI} This YUI instance. 624 **/ 625 add: function(name, fn, version, details) { 626 details = details || {}; 627 var env = YUI.Env, 628 mod = { 629 name: name, 630 fn: fn, 631 version: version, 632 details: details 633 }, 634 //Instance hash so we don't apply it to the same instance twice 635 applied = {}, 636 loader, inst, modInfo, 637 i, versions = env.versions; 638 639 env.mods[name] = mod; 640 versions[version] = versions[version] || {}; 641 versions[version][name] = mod; 642 643 for (i in instances) { 644 if (instances.hasOwnProperty(i)) { 645 inst = instances[i]; 646 if (!applied[inst.id]) { 647 applied[inst.id] = true; 648 loader = inst.Env._loader; 649 if (loader) { 650 modInfo = loader.getModuleInfo(name); 651 if (!modInfo || modInfo.temp) { 652 loader.addModule(details, name); 653 } 654 } 655 } 656 } 657 } 658 659 return this; 660 }, 661 662 /** 663 Executes the callback function associated with each required module, 664 attaching the module to this YUI instance. 665 666 @method _attach 667 @param {Array} r The array of modules to attach 668 @param {Boolean} [moot=false] If `true`, don't throw a warning if the module 669 is not attached. 670 @private 671 **/ 672 _attach: function(r, moot) { 673 var i, name, mod, details, req, use, after, 674 mods = YUI.Env.mods, 675 aliases = YUI.Env.aliases, 676 Y = this, j, 677 cache = YUI.Env._renderedMods, 678 loader = Y.Env._loader, 679 done = Y.Env._attached, 680 exported = Y.Env._exported, 681 len = r.length, loader, def, go, 682 c = [], 683 modArgs, esCompat, reqlen, modInfo, 684 condition, 685 __exports__, __imports__; 686 687 //Check for conditional modules (in a second+ instance) and add their requirements 688 //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass 689 for (i = 0; i < len; i++) { 690 name = r[i]; 691 mod = mods[name]; 692 c.push(name); 693 if (loader && loader.conditions[name]) { 694 for (j in loader.conditions[name]) { 695 if (loader.conditions[name].hasOwnProperty(j)) { 696 def = loader.conditions[name][j]; 697 go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y))); 698 if (go) { 699 c.push(def.name); 700 } 701 } 702 } 703 } 704 } 705 r = c; 706 len = r.length; 707 708 for (i = 0; i < len; i++) { 709 if (!done[r[i]]) { 710 name = r[i]; 711 mod = mods[name]; 712 713 if (aliases && aliases[name] && !mod) { 714 Y._attach(aliases[name]); 715 continue; 716 } 717 if (!mod) { 718 modInfo = loader && loader.getModuleInfo(name); 719 if (modInfo) { 720 mod = modInfo; 721 moot = true; 722 } 723 724 725 //if (!loader || !loader.moduleInfo[name]) { 726 //if ((!loader || !loader.moduleInfo[name]) && !moot) { 727 if (!moot && name) { 728 if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) { 729 Y.Env._missed.push(name); 730 Y.Env._missed = Y.Array.dedupe(Y.Env._missed); 731 Y.message('NOT loaded: ' + name, 'warn', 'yui'); 732 } 733 } 734 } else { 735 done[name] = true; 736 //Don't like this, but in case a mod was asked for once, then we fetch it 737 //We need to remove it from the missed list ^davglass 738 for (j = 0; j < Y.Env._missed.length; j++) { 739 if (Y.Env._missed[j] === name) { 740 Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui'); 741 Y.Env._missed.splice(j, 1); 742 } 743 } 744 745 // Optional dependencies normally work by modifying the 746 // dependency list of a module. If the dependency's test 747 // passes it is added to the list. If not, it's not loaded. 748 // This following check ensures that optional dependencies 749 // are not attached when they were already loaded into the 750 // page (when bundling for example) 751 if (loader && !loader._canBeAttached(name)) { 752 return true; 753 } 754 755 /* 756 If it's a temp module, we need to redo it's requirements if it's already loaded 757 since it may have been loaded by another instance and it's dependencies might 758 have been redefined inside the fetched file. 759 */ 760 if (loader && cache && cache[name] && cache[name].temp) { 761 loader.getRequires(cache[name]); 762 req = []; 763 modInfo = loader.getModuleInfo(name); 764 for (j in modInfo.expanded_map) { 765 if (modInfo.expanded_map.hasOwnProperty(j)) { 766 req.push(j); 767 } 768 } 769 Y._attach(req); 770 } 771 772 details = mod.details; 773 req = details.requires; 774 esCompat = details.es; 775 use = details.use; 776 after = details.after; 777 //Force Intl load if there is a language (Loader logic) @todo fix this shit 778 if (details.lang) { 779 req = req || []; 780 req.unshift('intl'); 781 } 782 783 if (req) { 784 reqlen = req.length; 785 for (j = 0; j < reqlen; j++) { 786 if (!done[req[j]]) { 787 if (!Y._attach(req)) { 788 return false; 789 } 790 break; 791 } 792 } 793 } 794 795 if (after) { 796 for (j = 0; j < after.length; j++) { 797 if (!done[after[j]]) { 798 if (!Y._attach(after, true)) { 799 return false; 800 } 801 break; 802 } 803 } 804 } 805 806 if (mod.fn) { 807 modArgs = [Y, name]; 808 if (esCompat) { 809 __imports__ = {}; 810 __exports__ = {}; 811 // passing `exports` and `imports` onto the module function 812 modArgs.push(__imports__, __exports__); 813 if (req) { 814 reqlen = req.length; 815 for (j = 0; j < reqlen; j++) { 816 __imports__[req[j]] = exported.hasOwnProperty(req[j]) ? exported[req[j]] : Y; 817 } 818 } 819 } 820 if (Y.config.throwFail) { 821 __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); 822 } else { 823 try { 824 __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); 825 } catch (e) { 826 Y.error('Attach error: ' + name, e, name); 827 return false; 828 } 829 } 830 if (esCompat) { 831 // store the `exports` in case others `es` modules requires it 832 exported[name] = __exports__; 833 834 // If an ES module is conditionally loaded and set 835 // to be used "instead" another module, replace the 836 // trigger module's content with the conditionally 837 // loaded one so the values returned by require() 838 // still makes sense 839 condition = mod.details.condition; 840 if (condition && condition.when === 'instead') { 841 exported[condition.trigger] = __exports__; 842 } 843 } 844 } 845 846 if (use) { 847 for (j = 0; j < use.length; j++) { 848 if (!done[use[j]]) { 849 if (!Y._attach(use)) { 850 return false; 851 } 852 break; 853 } 854 } 855 } 856 857 858 859 } 860 } 861 } 862 863 return true; 864 }, 865 866 /** 867 Delays the `use` callback until another event has taken place such as 868 `window.onload`, `domready`, `contentready`, or `available`. 869 870 @private 871 @method _delayCallback 872 @param {Function} cb The original `use` callback. 873 @param {String|Object} until Either an event name ('load', 'domready', etc.) 874 or an object containing event/args keys for contentready/available. 875 @return {Function} 876 **/ 877 _delayCallback: function(cb, until) { 878 879 var Y = this, 880 mod = ['event-base']; 881 882 until = (Y.Lang.isObject(until) ? until : { event: until }); 883 884 if (until.event === 'load') { 885 mod.push('event-synthetic'); 886 } 887 888 return function() { 889 var args = arguments; 890 Y._use(mod, function() { 891 Y.on(until.event, function() { 892 args[1].delayUntil = until.event; 893 cb.apply(Y, args); 894 }, until.args); 895 }); 896 }; 897 }, 898 899 /** 900 Attaches one or more modules to this YUI instance. When this is executed, 901 the requirements of the desired modules are analyzed, and one of several 902 things can happen: 903 904 905 * All required modules have already been loaded, and just need to be 906 attached to this YUI instance. In this case, the `use()` callback will 907 be executed synchronously after the modules are attached. 908 909 * One or more modules have not yet been loaded, or the Get utility is not 910 available, or the `bootstrap` config option is `false`. In this case, 911 a warning is issued indicating that modules are missing, but all 912 available modules will still be attached and the `use()` callback will 913 be executed synchronously. 914 915 * One or more modules are missing and the Loader is not available but the 916 Get utility is, and `bootstrap` is not `false`. In this case, the Get 917 utility will be used to load the Loader, and we will then proceed to 918 the following state: 919 920 * One or more modules are missing and the Loader is available. In this 921 case, the Loader will be used to resolve the dependency tree for the 922 missing modules and load them and their dependencies. When the Loader is 923 finished loading modules, the `use()` callback will be executed 924 asynchronously. 925 926 @example 927 928 // Loads and attaches dd and its dependencies. 929 YUI().use('dd', function (Y) { 930 // ... 931 }); 932 933 // Loads and attaches dd and node as well as all of their dependencies. 934 YUI().use(['dd', 'node'], function (Y) { 935 // ... 936 }); 937 938 // Attaches all modules that have already been loaded. 939 YUI().use('*', function (Y) { 940 // ... 941 }); 942 943 // Attaches a gallery module. 944 YUI().use('gallery-yql', function (Y) { 945 // ... 946 }); 947 948 // Attaches a YUI 2in3 module. 949 YUI().use('yui2-datatable', function (Y) { 950 // ... 951 }); 952 953 @method use 954 @param {String|Array} modules* One or more module names to attach. 955 @param {Function} [callback] Callback function to be executed once all 956 specified modules and their dependencies have been attached. 957 @param {YUI} callback.Y The YUI instance created for this sandbox. 958 @param {Object} callback.status Object containing `success`, `msg` and 959 `data` properties. 960 @chainable 961 **/ 962 use: function() { 963 var args = SLICE.call(arguments, 0), 964 callback = args[args.length - 1], 965 Y = this, 966 i = 0, 967 name, 968 Env = Y.Env, 969 provisioned = true; 970 971 // The last argument supplied to use can be a load complete callback 972 if (Y.Lang.isFunction(callback)) { 973 args.pop(); 974 if (Y.config.delayUntil) { 975 callback = Y._delayCallback(callback, Y.config.delayUntil); 976 } 977 } else { 978 callback = null; 979 } 980 if (Y.Lang.isArray(args[0])) { 981 args = args[0]; 982 } 983 984 if (Y.config.cacheUse) { 985 while ((name = args[i++])) { 986 if (!Env._attached[name]) { 987 provisioned = false; 988 break; 989 } 990 } 991 992 if (provisioned) { 993 if (args.length) { 994 } 995 Y._notify(callback, ALREADY_DONE, args); 996 return Y; 997 } 998 } 999 1000 if (Y._loading) { 1001 Y._useQueue = Y._useQueue || new Y.Queue(); 1002 Y._useQueue.add([args, callback]); 1003 } else { 1004 Y._use(args, function(Y, response) { 1005 Y._notify(callback, response, args); 1006 }); 1007 } 1008 1009 return Y; 1010 }, 1011 1012 /** 1013 Sugar for loading both legacy and ES6-based YUI modules. 1014 1015 @method require 1016 @param {String} [modules*] List of module names to import or a single 1017 module name. 1018 @param {Function} callback Callback that gets called once all the modules 1019 were loaded. Each parameter of the callback is the export value of the 1020 corresponding module in the list. If the module is a legacy YUI module, 1021 the YUI instance is used instead of the module exports. 1022 @example 1023 ``` 1024 YUI().require(['es6-set'], function (Y, imports) { 1025 var Set = imports.Set, 1026 set = new Set(); 1027 }); 1028 ``` 1029 **/ 1030 require: function () { 1031 var args = SLICE.call(arguments), 1032 callback; 1033 1034 if (typeof args[args.length - 1] === 'function') { 1035 callback = args.pop(); 1036 1037 // only add the callback if one was provided 1038 // YUI().require('foo'); is valid 1039 args.push(function (Y) { 1040 var i, length = args.length, 1041 exported = Y.Env._exported, 1042 __imports__ = {}; 1043 1044 // Get only the imports requested as arguments 1045 for (i = 0; i < length; i++) { 1046 if (exported.hasOwnProperty(args[i])) { 1047 __imports__[args[i]] = exported[args[i]]; 1048 } 1049 } 1050 1051 // Using `undefined` because: 1052 // - Using `Y.config.global` would force the value of `this` to be 1053 // the global object even in strict mode 1054 // - Using `Y` goes against the goal of moving away from a shared 1055 // object and start thinking in terms of imported and exported 1056 // objects 1057 callback.call(undefined, Y, __imports__); 1058 }); 1059 } 1060 // Do not return the Y object. This makes it hard to follow this 1061 // traditional pattern: 1062 // var Y = YUI().use(...); 1063 // This is a good idea in the light of ES6 modules, to avoid working 1064 // in the global scope. 1065 // This also leaves the door open for returning a promise, once the 1066 // YUI loader is based on the ES6 loader which uses 1067 // loader.import(...).then(...) 1068 this.use.apply(this, args); 1069 }, 1070 1071 /** 1072 Handles Loader notifications about attachment/load errors. 1073 1074 @method _notify 1075 @param {Function} callback Callback to pass to `Y.config.loadErrorFn`. 1076 @param {Object} response Response returned from Loader. 1077 @param {Array} args Arguments passed from Loader. 1078 @private 1079 **/ 1080 _notify: function(callback, response, args) { 1081 if (!response.success && this.config.loadErrorFn) { 1082 this.config.loadErrorFn.call(this, this, callback, response, args); 1083 } else if (callback) { 1084 if (this.Env._missed && this.Env._missed.length) { 1085 response.msg = 'Missing modules: ' + this.Env._missed.join(); 1086 response.success = false; 1087 } 1088 if (this.config.throwFail) { 1089 callback(this, response); 1090 } else { 1091 try { 1092 callback(this, response); 1093 } catch (e) { 1094 this.error('use callback error', e, args); 1095 } 1096 } 1097 } 1098 }, 1099 1100 /** 1101 Called from the `use` method queue to ensure that only one set of loading 1102 logic is performed at a time. 1103 1104 @method _use 1105 @param {String} args* One or more modules to attach. 1106 @param {Function} [callback] Function to call once all required modules have 1107 been attached. 1108 @private 1109 **/ 1110 _use: function(args, callback) { 1111 1112 if (!this.Array) { 1113 this._attach(['yui-base']); 1114 } 1115 1116 var len, loader, handleBoot, 1117 Y = this, 1118 G_ENV = YUI.Env, 1119 mods = G_ENV.mods, 1120 Env = Y.Env, 1121 used = Env._used, 1122 aliases = G_ENV.aliases, 1123 queue = G_ENV._loaderQueue, 1124 firstArg = args[0], 1125 YArray = Y.Array, 1126 config = Y.config, 1127 boot = config.bootstrap, 1128 missing = [], 1129 i, 1130 r = [], 1131 ret = true, 1132 fetchCSS = config.fetchCSS, 1133 process = function(names, skip) { 1134 1135 var i = 0, a = [], name, len, m, req, use; 1136 1137 if (!names.length) { 1138 return; 1139 } 1140 1141 if (aliases) { 1142 len = names.length; 1143 for (i = 0; i < len; i++) { 1144 if (aliases[names[i]] && !mods[names[i]]) { 1145 a = [].concat(a, aliases[names[i]]); 1146 } else { 1147 a.push(names[i]); 1148 } 1149 } 1150 names = a; 1151 } 1152 1153 len = names.length; 1154 1155 for (i = 0; i < len; i++) { 1156 name = names[i]; 1157 if (!skip) { 1158 r.push(name); 1159 } 1160 1161 // only attach a module once 1162 if (used[name]) { 1163 continue; 1164 } 1165 1166 m = mods[name]; 1167 req = null; 1168 use = null; 1169 1170 if (m) { 1171 used[name] = true; 1172 req = m.details.requires; 1173 use = m.details.use; 1174 } else { 1175 // CSS files don't register themselves, see if it has 1176 // been loaded 1177 if (!G_ENV._loaded[VERSION][name]) { 1178 missing.push(name); 1179 } else { 1180 used[name] = true; // probably css 1181 } 1182 } 1183 1184 // make sure requirements are attached 1185 if (req && req.length) { 1186 process(req); 1187 } 1188 1189 // make sure we grab the submodule dependencies too 1190 if (use && use.length) { 1191 process(use, 1); 1192 } 1193 } 1194 1195 }, 1196 1197 handleLoader = function(fromLoader) { 1198 var response = fromLoader || { 1199 success: true, 1200 msg: 'not dynamic' 1201 }, 1202 redo, origMissing, 1203 ret = true, 1204 data = response.data; 1205 1206 Y._loading = false; 1207 1208 if (data) { 1209 origMissing = missing; 1210 missing = []; 1211 r = []; 1212 process(data); 1213 redo = missing.length; 1214 if (redo) { 1215 if ([].concat(missing).sort().join() == 1216 origMissing.sort().join()) { 1217 redo = false; 1218 } 1219 } 1220 } 1221 1222 if (redo && data) { 1223 Y._loading = true; 1224 Y._use(missing, function() { 1225 if (Y._attach(data)) { 1226 Y._notify(callback, response, data); 1227 } 1228 }); 1229 } else { 1230 if (data) { 1231 ret = Y._attach(data); 1232 } 1233 if (ret) { 1234 Y._notify(callback, response, args); 1235 } 1236 } 1237 1238 if (Y._useQueue && Y._useQueue.size() && !Y._loading) { 1239 Y._use.apply(Y, Y._useQueue.next()); 1240 } 1241 1242 }; 1243 1244 1245 // YUI().use('*'); // bind everything available 1246 if (firstArg === '*') { 1247 args = []; 1248 for (i in mods) { 1249 if (mods.hasOwnProperty(i)) { 1250 args.push(i); 1251 } 1252 } 1253 ret = Y._attach(args); 1254 if (ret) { 1255 handleLoader(); 1256 } 1257 return Y; 1258 } 1259 1260 if ((mods.loader || mods['loader-base']) && !Y.Loader) { 1261 Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]); 1262 } 1263 1264 1265 // use loader to expand dependencies and sort the 1266 // requirements if it is available. 1267 if (boot && Y.Loader && args.length) { 1268 loader = getLoader(Y); 1269 loader.require(args); 1270 loader.ignoreRegistered = true; 1271 loader._boot = true; 1272 loader.calculate(null, (fetchCSS) ? null : 'js'); 1273 args = loader.sorted; 1274 loader._boot = false; 1275 } 1276 1277 process(args); 1278 1279 len = missing.length; 1280 1281 1282 if (len) { 1283 missing = YArray.dedupe(missing); 1284 len = missing.length; 1285 } 1286 1287 1288 // dynamic load 1289 if (boot && len && Y.Loader) { 1290 Y._loading = true; 1291 loader = getLoader(Y); 1292 loader.onEnd = handleLoader; 1293 loader.context = Y; 1294 loader.data = args; 1295 loader.ignoreRegistered = false; 1296 loader.require(missing); 1297 loader.insert(null, (fetchCSS) ? null : 'js'); 1298 1299 } else if (boot && len && Y.Get && !Env.bootstrapped) { 1300 1301 Y._loading = true; 1302 1303 handleBoot = function() { 1304 Y._loading = false; 1305 queue.running = false; 1306 Env.bootstrapped = true; 1307 G_ENV._bootstrapping = false; 1308 if (Y._attach(['loader'])) { 1309 Y._use(args, callback); 1310 } 1311 }; 1312 1313 if (G_ENV._bootstrapping) { 1314 queue.add(handleBoot); 1315 } else { 1316 G_ENV._bootstrapping = true; 1317 Y.Get.script(config.base + config.loaderPath, { 1318 onEnd: handleBoot 1319 }); 1320 } 1321 1322 } else { 1323 ret = Y._attach(args); 1324 if (ret) { 1325 handleLoader(); 1326 } 1327 } 1328 1329 return Y; 1330 }, 1331 1332 1333 /** 1334 Utility method for safely creating namespaces if they don't already exist. 1335 May be called statically on the YUI global object or as a method on a YUI 1336 instance. 1337 1338 When called statically, a namespace will be created on the YUI global 1339 object: 1340 1341 // Create `YUI.your.namespace.here` as nested objects, preserving any 1342 // objects that already exist instead of overwriting them. 1343 YUI.namespace('your.namespace.here'); 1344 1345 When called as a method on a YUI instance, a namespace will be created on 1346 that instance: 1347 1348 // Creates `Y.property.package`. 1349 Y.namespace('property.package'); 1350 1351 Dots in the input string cause `namespace` to create nested objects for each 1352 token. If any part of the requested namespace already exists, the current 1353 object will be left in place and will not be overwritten. This allows 1354 multiple calls to `namespace` to preserve existing namespaced properties. 1355 1356 If the first token in the namespace string is "YAHOO", that token is 1357 discarded. This is legacy behavior for backwards compatibility with YUI 2. 1358 1359 Be careful with namespace tokens. Reserved words may work in some browsers 1360 and not others. For instance, the following will fail in some browsers 1361 because the supported version of JavaScript reserves the word "long": 1362 1363 Y.namespace('really.long.nested.namespace'); 1364 1365 Note: If you pass multiple arguments to create multiple namespaces, only the 1366 last one created is returned from this function. 1367 1368 @method namespace 1369 @param {String} namespace* One or more namespaces to create. 1370 @return {Object} Reference to the last namespace object created. 1371 **/ 1372 namespace: function() { 1373 var a = arguments, o, i = 0, j, d, arg; 1374 1375 for (; i < a.length; i++) { 1376 o = this; //Reset base object per argument or it will get reused from the last 1377 arg = a[i]; 1378 if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present 1379 d = arg.split(PERIOD); 1380 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) { 1381 o[d[j]] = o[d[j]] || {}; 1382 o = o[d[j]]; 1383 } 1384 } else { 1385 o[arg] = o[arg] || {}; 1386 o = o[arg]; //Reset base object to the new object so it's returned 1387 } 1388 } 1389 return o; 1390 }, 1391 1392 // this is replaced if the log module is included 1393 log: NOOP, 1394 message: NOOP, 1395 // this is replaced if the dump module is included 1396 dump: function (o) { return ''+o; }, 1397 1398 /** 1399 Reports an error. 1400 1401 The reporting mechanism is controlled by the `throwFail` configuration 1402 attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is 1403 truthy, a JS exception is thrown. 1404 1405 If an `errorFn` is specified in the config it must return `true` to indicate 1406 that the exception was handled and keep it from being thrown. 1407 1408 @method error 1409 @param {String} msg Error message. 1410 @param {Error|String} [e] JavaScript error object or an error string. 1411 @param {String} [src] Source of the error (such as the name of the module in 1412 which the error occurred). 1413 @chainable 1414 **/ 1415 error: function(msg, e, src) { 1416 //TODO Add check for window.onerror here 1417 1418 var Y = this, ret; 1419 1420 if (Y.config.errorFn) { 1421 ret = Y.config.errorFn.apply(Y, arguments); 1422 } 1423 1424 if (!ret) { 1425 throw (e || new Error(msg)); 1426 } else { 1427 Y.message(msg, 'error', ''+src); // don't scrub this one 1428 } 1429 1430 return Y; 1431 }, 1432 1433 /** 1434 Generates an id string that is unique among all YUI instances in this 1435 execution context. 1436 1437 @method guid 1438 @param {String} [pre] Prefix. 1439 @return {String} Unique id. 1440 **/ 1441 guid: function(pre) { 1442 var id = this.Env._guidp + '_' + (++this.Env._uidx); 1443 return (pre) ? (pre + id) : id; 1444 }, 1445 1446 /** 1447 Returns a unique id associated with the given object and (if *readOnly* is 1448 falsy) stamps the object with that id so it can be identified in the future. 1449 1450 Stamping an object involves adding a `_yuid` property to it that contains 1451 the object's id. One exception to this is that in Internet Explorer, DOM 1452 nodes have a `uniqueID` property that contains a browser-generated unique 1453 id, which will be used instead of a YUI-generated id when available. 1454 1455 @method stamp 1456 @param {Object} o Object to stamp. 1457 @param {Boolean} readOnly If truthy and the given object has not already 1458 been stamped, the object will not be modified and `null` will be 1459 returned. 1460 @return {String} Object's unique id, or `null` if *readOnly* was truthy and 1461 the given object was not already stamped. 1462 **/ 1463 stamp: function(o, readOnly) { 1464 var uid; 1465 if (!o) { 1466 return o; 1467 } 1468 1469 // IE generates its own unique ID for dom nodes 1470 // The uniqueID property of a document node returns a new ID 1471 if (o.uniqueID && o.nodeType && o.nodeType !== 9) { 1472 uid = o.uniqueID; 1473 } else { 1474 uid = (typeof o === 'string') ? o : o._yuid; 1475 } 1476 1477 if (!uid) { 1478 uid = this.guid(); 1479 if (!readOnly) { 1480 try { 1481 o._yuid = uid; 1482 } catch (e) { 1483 uid = null; 1484 } 1485 } 1486 } 1487 return uid; 1488 }, 1489 1490 /** 1491 Destroys this YUI instance. 1492 1493 @method destroy 1494 @since 3.3.0 1495 **/ 1496 destroy: function() { 1497 var Y = this; 1498 if (Y.Event) { 1499 Y.Event._unload(); 1500 } 1501 delete instances[Y.id]; 1502 delete Y.Env; 1503 delete Y.config; 1504 } 1505 1506 /** 1507 Safe `instanceof` wrapper that works around a memory leak in IE when the 1508 object being tested is `window` or `document`. 1509 1510 Unless you are testing objects that may be `window` or `document`, you 1511 should use the native `instanceof` operator instead of this method. 1512 1513 @method instanceOf 1514 @param {Object} o Object to check. 1515 @param {Object} type Class to check against. 1516 @since 3.3.0 1517 **/ 1518 }; 1519 1520 YUI.prototype = proto; 1521 1522 // inheritance utilities are not available yet 1523 for (prop in proto) { 1524 if (proto.hasOwnProperty(prop)) { 1525 YUI[prop] = proto[prop]; 1526 } 1527 } 1528 1529 /** 1530 Applies a configuration to all YUI instances in this execution context. 1531 1532 The main use case for this method is in "mashups" where several third-party 1533 scripts need to write to a global YUI config, but cannot share a single 1534 centrally-managed config object. This way they can all call 1535 `YUI.applyConfig({})` instead of overwriting the single global config. 1536 1537 @example 1538 1539 YUI.applyConfig({ 1540 modules: { 1541 davglass: { 1542 fullpath: './davglass.js' 1543 } 1544 } 1545 }); 1546 1547 YUI.applyConfig({ 1548 modules: { 1549 foo: { 1550 fullpath: './foo.js' 1551 } 1552 } 1553 }); 1554 1555 YUI().use('davglass', function (Y) { 1556 // Module davglass will be available here. 1557 }); 1558 1559 @method applyConfig 1560 @param {Object} o Configuration object to apply. 1561 @static 1562 @since 3.5.0 1563 **/ 1564 YUI.applyConfig = function(o) { 1565 if (!o) { 1566 return; 1567 } 1568 //If there is a GlobalConfig, apply it first to set the defaults 1569 if (YUI.GlobalConfig) { 1570 this.prototype.applyConfig.call(this, YUI.GlobalConfig); 1571 } 1572 //Apply this config to it 1573 this.prototype.applyConfig.call(this, o); 1574 //Reset GlobalConfig to the combined config 1575 YUI.GlobalConfig = this.config; 1576 }; 1577 1578 // set up the environment 1579 YUI._init(); 1580 1581 if (hasWin) { 1582 add(doc, 'DOMContentLoaded', handleReady); 1583 1584 // add a window load event at load time so we can capture 1585 // the case where it fires before dynamic loading is 1586 // complete. 1587 add(window, 'load', handleLoad); 1588 } else { 1589 handleReady(); 1590 handleLoad(); 1591 } 1592 1593 YUI.Env.add = add; 1594 YUI.Env.remove = remove; 1595 1596 /*global exports*/ 1597 // Support the CommonJS method for exporting our single global 1598 if (typeof exports == 'object') { 1599 exports.YUI = YUI; 1600 /** 1601 * Set a method to be called when `Get.script` is called in Node.js 1602 * `Get` will open the file, then pass it's content and it's path 1603 * to this method before attaching it. Commonly used for code coverage 1604 * instrumentation. <strong>Calling this multiple times will only 1605 * attach the last hook method</strong>. This method is only 1606 * available in Node.js. 1607 * @method setLoadHook 1608 * @static 1609 * @param {Function} fn The function to set 1610 * @param {String} fn.data The content of the file 1611 * @param {String} fn.path The file path of the file 1612 */ 1613 YUI.setLoadHook = function(fn) { 1614 YUI._getLoadHook = fn; 1615 }; 1616 /** 1617 * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook` 1618 * @method _getLoadHook 1619 * @private 1620 * @param {String} data The content of the file 1621 * @param {String} path The file path of the file 1622 */ 1623 YUI._getLoadHook = null; 1624 } 1625 1626 YUI.Env[VERSION] = {}; 1627 }()); 1628 1629 1630 /** 1631 Config object that contains all of the configuration options for 1632 this `YUI` instance. 1633 1634 This object is supplied by the implementer when instantiating YUI. Some 1635 properties have default values if they are not supplied by the implementer. 1636 1637 This object should not be updated directly because some values are cached. Use 1638 `applyConfig()` to update the config object on a YUI instance that has already 1639 been configured. 1640 1641 @class config 1642 @static 1643 **/ 1644 1645 /** 1646 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata 1647 if they're needed to load additional dependencies and aren't already available. 1648 1649 Setting this to `false` will prevent YUI from automatically loading the Loader 1650 and module metadata, so you will need to manually ensure that they're available 1651 or handle dependency resolution yourself. 1652 1653 @property {Boolean} bootstrap 1654 @default true 1655 **/ 1656 1657 /** 1658 1659 @property {Object} filters 1660 **/ 1661 1662 /** 1663 If `true`, YUI will use a combo handler to load multiple modules in as few 1664 requests as possible. 1665 1666 The YUI CDN (which YUI uses by default) supports combo handling, but other 1667 servers may not. If the server from which you're loading YUI does not support 1668 combo handling, set this to `false`. 1669 1670 Providing a value for the `base` config property will cause `combine` to default 1671 to `false` instead of `true`. 1672 1673 @property {Boolean} combine 1674 @default true 1675 */ 1676 1677 /** 1678 Array of module names that should never be dynamically loaded. 1679 1680 @property {String[]} ignore 1681 **/ 1682 1683 /** 1684 Array of module names that should always be loaded when required, even if 1685 already present on the page. 1686 1687 @property {String[]} force 1688 **/ 1689 1690 /** 1691 DOM element or id that should be used as the insertion point for dynamically 1692 added `<script>` and `<link>` nodes. 1693 1694 @property {HTMLElement|String} insertBefore 1695 **/ 1696 1697 /** 1698 Object hash containing attributes to add to dynamically added `<script>` nodes. 1699 1700 @property {Object} jsAttributes 1701 **/ 1702 1703 /** 1704 Object hash containing attributes to add to dynamically added `<link>` nodes. 1705 1706 @property {Object} cssAttributes 1707 **/ 1708 1709 /** 1710 Timeout in milliseconds before a dynamic JS or CSS request will be considered a 1711 failure. If not set, no timeout will be enforced. 1712 1713 @property {Number} timeout 1714 **/ 1715 1716 /** 1717 A hash of module definitions to add to the list of available YUI modules. These 1718 modules can then be dynamically loaded via the `use()` method. 1719 1720 This is a hash in which keys are module names and values are objects containing 1721 module metadata. 1722 1723 See `Loader.addModule()` for the supported module metadata fields. Also see 1724 `groups`, which provides a way to configure the base and combo spec for a set of 1725 modules. 1726 1727 @example 1728 1729 modules: { 1730 mymod1: { 1731 requires: ['node'], 1732 fullpath: '/mymod1/mymod1.js' 1733 }, 1734 1735 mymod2: { 1736 requires: ['mymod1'], 1737 fullpath: '/mymod2/mymod2.js' 1738 }, 1739 1740 mymod3: '/js/mymod3.js', 1741 mycssmod: '/css/mycssmod.css' 1742 } 1743 1744 @property {Object} modules 1745 **/ 1746 1747 /** 1748 Aliases are dynamic groups of modules that can be used as shortcuts. 1749 1750 @example 1751 1752 YUI({ 1753 aliases: { 1754 davglass: [ 'node', 'yql', 'dd' ], 1755 mine: [ 'davglass', 'autocomplete'] 1756 } 1757 }).use('mine', function (Y) { 1758 // Node, YQL, DD & AutoComplete available here. 1759 }); 1760 1761 @property {Object} aliases 1762 **/ 1763 1764 /** 1765 A hash of module group definitions. 1766 1767 For each group you can specify a list of modules and the base path and 1768 combo spec to use when dynamically loading the modules. 1769 1770 @example 1771 1772 groups: { 1773 yui2: { 1774 // specify whether or not this group has a combo service 1775 combine: true, 1776 1777 // The comboSeperator to use with this group's combo handler 1778 comboSep: ';', 1779 1780 // The maxURLLength for this server 1781 maxURLLength: 500, 1782 1783 // the base path for non-combo paths 1784 base: 'http://yui.yahooapis.com/2.8.0r4/build/', 1785 1786 // the path to the combo service 1787 comboBase: 'http://yui.yahooapis.com/combo?', 1788 1789 // a fragment to prepend to the path attribute when 1790 // when building combo urls 1791 root: '2.8.0r4/build/', 1792 1793 // the module definitions 1794 modules: { 1795 yui2_yde: { 1796 path: "yahoo-dom-event/yahoo-dom-event.js" 1797 }, 1798 yui2_anim: { 1799 path: "animation/animation.js", 1800 requires: ['yui2_yde'] 1801 } 1802 } 1803 } 1804 } 1805 1806 @property {Object} groups 1807 **/ 1808 1809 /** 1810 Path to the Loader JS file, relative to the `base` path. 1811 1812 This is used to dynamically bootstrap the Loader when it's needed and isn't yet 1813 available. 1814 1815 @property {String} loaderPath 1816 @default "loader/loader-min.js" 1817 **/ 1818 1819 /** 1820 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to 1821 `false` to prevent YUI from loading any CSS, or set it to the string `"force"` 1822 to force CSS dependencies to be loaded even if their associated JS modules are 1823 already loaded. 1824 1825 @property {Boolean|String} fetchCSS 1826 @default true 1827 **/ 1828 1829 /** 1830 Default gallery version used to build gallery module urls. 1831 1832 @property {String} gallery 1833 @since 3.1.0 1834 **/ 1835 1836 /** 1837 Default YUI 2 version used to build YUI 2 module urls. 1838 1839 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the 1840 `2in3` config for pulling different revisions of the wrapped YUI 2 modules. 1841 1842 @property {String} yui2 1843 @default "2.9.0" 1844 @since 3.1.0 1845 **/ 1846 1847 /** 1848 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3. 1849 1850 @property {String} 2in3 1851 @default "4" 1852 @since 3.1.0 1853 **/ 1854 1855 /** 1856 Alternate console log function that should be used in environments without a 1857 supported native console. This function is executed with the YUI instance as its 1858 `this` object. 1859 1860 @property {Function} logFn 1861 @since 3.1.0 1862 **/ 1863 1864 /** 1865 The minimum log level to log messages for. Log levels are defined 1866 incrementally. Messages greater than or equal to the level specified will 1867 be shown. All others will be discarded. The order of log levels in 1868 increasing priority is: 1869 1870 debug 1871 info 1872 warn 1873 error 1874 1875 @property {String} logLevel 1876 @default 'debug' 1877 @since 3.10.0 1878 **/ 1879 1880 /** 1881 Callback to execute when `Y.error()` is called. It receives the error message 1882 and a JavaScript error object if one was provided. 1883 1884 This function is executed with the YUI instance as its `this` object. 1885 1886 Returning `true` from this function will prevent an exception from being thrown. 1887 1888 @property {Function} errorFn 1889 @param {String} errorFn.msg Error message 1890 @param {Object} [errorFn.err] Error object (if one was provided). 1891 @since 3.2.0 1892 **/ 1893 1894 /** 1895 A callback to execute when Loader fails to load one or more resources. 1896 1897 This could be because of a script load failure. It could also be because a 1898 module fails to register itself when the `requireRegistration` config is `true`. 1899 1900 If this function is defined, the `use()` callback will only be called when the 1901 loader succeeds. Otherwise, `use()` will always executes unless there was a 1902 JavaScript error when attaching a module. 1903 1904 @property {Function} loadErrorFn 1905 @since 3.3.0 1906 **/ 1907 1908 /** 1909 If `true`, Loader will expect all loaded scripts to be first-class YUI modules 1910 that register themselves with the YUI global, and will trigger a failure if a 1911 loaded script does not register a YUI module. 1912 1913 @property {Boolean} requireRegistration 1914 @default false 1915 @since 3.3.0 1916 **/ 1917 1918 /** 1919 Cache serviced use() requests. 1920 1921 @property {Boolean} cacheUse 1922 @default true 1923 @since 3.3.0 1924 @deprecated No longer used. 1925 **/ 1926 1927 /** 1928 Whether or not YUI should use native ES5 functionality when available for 1929 features like `Y.Array.each()`, `Y.Object()`, etc. 1930 1931 When `false`, YUI will always use its own fallback implementations instead of 1932 relying on ES5 functionality, even when ES5 functionality is available. 1933 1934 @property {Boolean} useNativeES5 1935 @default true 1936 @since 3.5.0 1937 **/ 1938 1939 /** 1940 * Leverage native JSON stringify if the browser has a native 1941 * implementation. In general, this is a good idea. See the Known Issues 1942 * section in the JSON user guide for caveats. The default value is true 1943 * for browsers with native JSON support. 1944 * 1945 * @property useNativeJSONStringify 1946 * @type Boolean 1947 * @default true 1948 * @since 3.8.0 1949 */ 1950 1951 /** 1952 * Leverage native JSON parse if the browser has a native implementation. 1953 * In general, this is a good idea. See the Known Issues section in the 1954 * JSON user guide for caveats. The default value is true for browsers with 1955 * native JSON support. 1956 * 1957 * @property useNativeJSONParse 1958 * @type Boolean 1959 * @default true 1960 * @since 3.8.0 1961 */ 1962 1963 /** 1964 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`) 1965 1966 @property {Object|String} delayUntil 1967 @since 3.6.0 1968 @example 1969 1970 You can use `load` or `domready` strings by default: 1971 1972 YUI({ 1973 delayUntil: 'domready' 1974 }, function (Y) { 1975 // This will not execute until 'domeready' occurs. 1976 }); 1977 1978 Or you can delay until a node is available (with `available` or `contentready`): 1979 1980 YUI({ 1981 delayUntil: { 1982 event: 'available', 1983 args : '#foo' 1984 } 1985 }, function (Y) { 1986 // This will not execute until a node matching the selector "#foo" is 1987 // available in the DOM. 1988 }); 1989 1990 **/ 1991 YUI.add('yui-base', function (Y, NAME) { 1992 1993 /* 1994 * YUI stub 1995 * @module yui 1996 * @submodule yui-base 1997 */ 1998 /** 1999 * The YUI module contains the components required for building the YUI 2000 * seed file. This includes the script loading mechanism, a simple queue, 2001 * and the core utilities for the library. 2002 * @module yui 2003 * @submodule yui-base 2004 */ 2005 2006 /** 2007 * Provides core language utilites and extensions used throughout YUI. 2008 * 2009 * @class Lang 2010 * @static 2011 */ 2012 2013 var L = Y.Lang || (Y.Lang = {}), 2014 2015 STRING_PROTO = String.prototype, 2016 TOSTRING = Object.prototype.toString, 2017 2018 TYPES = { 2019 'undefined' : 'undefined', 2020 'number' : 'number', 2021 'boolean' : 'boolean', 2022 'string' : 'string', 2023 '[object Function]': 'function', 2024 '[object RegExp]' : 'regexp', 2025 '[object Array]' : 'array', 2026 '[object Date]' : 'date', 2027 '[object Error]' : 'error' 2028 }, 2029 2030 SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g, 2031 2032 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", 2033 WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+", 2034 TRIM_LEFT_REGEX = new RegExp("^" + WHITESPACE_CLASS), 2035 TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"), 2036 TRIMREGEX = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"), 2037 2038 NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i; 2039 2040 // -- Protected Methods -------------------------------------------------------- 2041 2042 /** 2043 Returns `true` if the given function appears to be implemented in native code, 2044 `false` otherwise. Will always return `false` -- even in ES5-capable browsers -- 2045 if the `useNativeES5` YUI config option is set to `false`. 2046 2047 This isn't guaranteed to be 100% accurate and won't work for anything other than 2048 functions, but it can be useful for determining whether a function like 2049 `Array.prototype.forEach` is native or a JS shim provided by another library. 2050 2051 There's a great article by @kangax discussing certain flaws with this technique: 2052 <http://perfectionkills.com/detecting-built-in-host-methods/> 2053 2054 While his points are valid, it's still possible to benefit from this function 2055 as long as it's used carefully and sparingly, and in such a way that false 2056 negatives have minimal consequences. It's used internally to avoid using 2057 potentially broken non-native ES5 shims that have been added to the page by 2058 other libraries. 2059 2060 @method _isNative 2061 @param {Function} fn Function to test. 2062 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise. 2063 @static 2064 @protected 2065 @since 3.5.0 2066 **/ 2067 L._isNative = function (fn) { 2068 return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn)); 2069 }; 2070 2071 // -- Public Methods ----------------------------------------------------------- 2072 2073 /** 2074 * Determines whether or not the provided item is an array. 2075 * 2076 * Returns `false` for array-like collections such as the function `arguments` 2077 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to 2078 * test for an array-like collection. 2079 * 2080 * @method isArray 2081 * @param o The object to test. 2082 * @return {boolean} true if o is an array. 2083 * @static 2084 */ 2085 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) { 2086 return L.type(o) === 'array'; 2087 }; 2088 2089 /** 2090 * Determines whether or not the provided item is a boolean. 2091 * @method isBoolean 2092 * @static 2093 * @param o The object to test. 2094 * @return {boolean} true if o is a boolean. 2095 */ 2096 L.isBoolean = function(o) { 2097 return typeof o === 'boolean'; 2098 }; 2099 2100 /** 2101 * Determines whether or not the supplied item is a date instance. 2102 * @method isDate 2103 * @static 2104 * @param o The object to test. 2105 * @return {boolean} true if o is a date. 2106 */ 2107 L.isDate = function(o) { 2108 return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o); 2109 }; 2110 2111 /** 2112 * <p> 2113 * Determines whether or not the provided item is a function. 2114 * Note: Internet Explorer thinks certain functions are objects: 2115 * </p> 2116 * 2117 * <pre> 2118 * var obj = document.createElement("object"); 2119 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE 2120 * 2121 * var input = document.createElement("input"); // append to body 2122 * Y.Lang.isFunction(input.focus) // reports false in IE 2123 * </pre> 2124 * 2125 * <p> 2126 * You will have to implement additional tests if these functions 2127 * matter to you. 2128 * </p> 2129 * 2130 * @method isFunction 2131 * @static 2132 * @param o The object to test. 2133 * @return {boolean} true if o is a function. 2134 */ 2135 L.isFunction = function(o) { 2136 return L.type(o) === 'function'; 2137 }; 2138 2139 /** 2140 * Determines whether or not the provided item is null. 2141 * @method isNull 2142 * @static 2143 * @param o The object to test. 2144 * @return {boolean} true if o is null. 2145 */ 2146 L.isNull = function(o) { 2147 return o === null; 2148 }; 2149 2150 /** 2151 * Determines whether or not the provided item is a legal number. 2152 * @method isNumber 2153 * @static 2154 * @param o The object to test. 2155 * @return {boolean} true if o is a number. 2156 */ 2157 L.isNumber = function(o) { 2158 return typeof o === 'number' && isFinite(o); 2159 }; 2160 2161 /** 2162 * Determines whether or not the provided item is of type object 2163 * or function. Note that arrays are also objects, so 2164 * <code>Y.Lang.isObject([]) === true</code>. 2165 * @method isObject 2166 * @static 2167 * @param o The object to test. 2168 * @param failfn {boolean} fail if the input is a function. 2169 * @return {boolean} true if o is an object. 2170 * @see isPlainObject 2171 */ 2172 L.isObject = function(o, failfn) { 2173 var t = typeof o; 2174 return (o && (t === 'object' || 2175 (!failfn && (t === 'function' || L.isFunction(o))))) || false; 2176 }; 2177 2178 /** 2179 * Determines whether or not the provided value is a regexp. 2180 * @method isRegExp 2181 * @static 2182 * @param value The value or object to test. 2183 * @return {boolean} true if value is a regexp. 2184 */ 2185 L.isRegExp = function(value) { 2186 return L.type(value) === 'regexp'; 2187 }; 2188 2189 /** 2190 * Determines whether or not the provided item is a string. 2191 * @method isString 2192 * @static 2193 * @param o The object to test. 2194 * @return {boolean} true if o is a string. 2195 */ 2196 L.isString = function(o) { 2197 return typeof o === 'string'; 2198 }; 2199 2200 /** 2201 * Determines whether or not the provided item is undefined. 2202 * @method isUndefined 2203 * @static 2204 * @param o The object to test. 2205 * @return {boolean} true if o is undefined. 2206 */ 2207 L.isUndefined = function(o) { 2208 return typeof o === 'undefined'; 2209 }; 2210 2211 /** 2212 * A convenience method for detecting a legitimate non-null value. 2213 * Returns false for null/undefined/NaN, true for other values, 2214 * including 0/false/'' 2215 * @method isValue 2216 * @static 2217 * @param o The item to test. 2218 * @return {boolean} true if it is not null/undefined/NaN || false. 2219 */ 2220 L.isValue = function(o) { 2221 var t = L.type(o); 2222 2223 switch (t) { 2224 case 'number': 2225 return isFinite(o); 2226 2227 case 'null': // fallthru 2228 case 'undefined': 2229 return false; 2230 2231 default: 2232 return !!t; 2233 } 2234 }; 2235 2236 /** 2237 * Returns the current time in milliseconds. 2238 * 2239 * @method now 2240 * @return {Number} Current time in milliseconds. 2241 * @static 2242 * @since 3.3.0 2243 */ 2244 L.now = Date.now || function () { 2245 return new Date().getTime(); 2246 }; 2247 2248 /** 2249 * Performs `{placeholder}` substitution on a string. The object passed as the 2250 * second parameter provides values to replace the `{placeholder}`s. 2251 * `{placeholder}` token names must match property names of the object. For example, 2252 * 2253 *`var greeting = Y.Lang.sub("Hello, {who}!", { who: "World" });` 2254 * 2255 * `{placeholder}` tokens that are undefined on the object map will be left 2256 * in tact (leaving unsightly `{placeholder}`'s in the output string). 2257 * 2258 * @method sub 2259 * @param {string} s String to be modified. 2260 * @param {object} o Object containing replacement values. 2261 * @return {string} the substitute result. 2262 * @static 2263 * @since 3.2.0 2264 */ 2265 L.sub = function(s, o) { 2266 return s.replace ? s.replace(SUBREGEX, function (match, key) { 2267 return L.isUndefined(o[key]) ? match : o[key]; 2268 }) : s; 2269 }; 2270 2271 /** 2272 * Returns a string without any leading or trailing whitespace. If 2273 * the input is not a string, the input will be returned untouched. 2274 * @method trim 2275 * @static 2276 * @param s {string} the string to trim. 2277 * @return {string} the trimmed string. 2278 */ 2279 L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) { 2280 return s && s.trim ? s.trim() : s; 2281 } : function (s) { 2282 try { 2283 return s.replace(TRIMREGEX, ''); 2284 } catch (e) { 2285 return s; 2286 } 2287 }; 2288 2289 /** 2290 * Returns a string without any leading whitespace. 2291 * @method trimLeft 2292 * @static 2293 * @param s {string} the string to trim. 2294 * @return {string} the trimmed string. 2295 */ 2296 L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) { 2297 return s.trimLeft(); 2298 } : function (s) { 2299 return s.replace(TRIM_LEFT_REGEX, ''); 2300 }; 2301 2302 /** 2303 * Returns a string without any trailing whitespace. 2304 * @method trimRight 2305 * @static 2306 * @param s {string} the string to trim. 2307 * @return {string} the trimmed string. 2308 */ 2309 L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) { 2310 return s.trimRight(); 2311 } : function (s) { 2312 return s.replace(TRIM_RIGHT_REGEX, ''); 2313 }; 2314 2315 /** 2316 Returns one of the following strings, representing the type of the item passed 2317 in: 2318 2319 * "array" 2320 * "boolean" 2321 * "date" 2322 * "error" 2323 * "function" 2324 * "null" 2325 * "number" 2326 * "object" 2327 * "regexp" 2328 * "string" 2329 * "undefined" 2330 2331 Known issues: 2332 2333 * `typeof HTMLElementCollection` returns function in Safari, but 2334 `Y.Lang.type()` reports "object", which could be a good thing -- 2335 but it actually caused the logic in <code>Y.Lang.isObject</code> to fail. 2336 2337 @method type 2338 @param o the item to test. 2339 @return {string} the detected type. 2340 @static 2341 **/ 2342 L.type = function(o) { 2343 return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null'); 2344 }; 2345 /** 2346 @module yui 2347 @submodule yui-base 2348 */ 2349 2350 var Lang = Y.Lang, 2351 Native = Array.prototype, 2352 2353 hasOwn = Object.prototype.hasOwnProperty; 2354 2355 /** 2356 Provides utility methods for working with arrays. Additional array helpers can 2357 be found in the `collection` and `array-extras` modules. 2358 2359 `Y.Array(thing)` returns a native array created from _thing_. Depending on 2360 _thing_'s type, one of the following will happen: 2361 2362 * Arrays are returned unmodified unless a non-zero _startIndex_ is 2363 specified. 2364 * Array-like collections (see `Array.test()`) are converted to arrays. 2365 * For everything else, a new array is created with _thing_ as the sole 2366 item. 2367 2368 Note: elements that are also collections, such as `<form>` and `<select>` 2369 elements, are not automatically converted to arrays. To force a conversion, 2370 pass `true` as the value of the _force_ parameter. 2371 2372 @class Array 2373 @constructor 2374 @param {Any} thing The thing to arrayify. 2375 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like 2376 collection, a subset of items starting at the specified index will be 2377 returned. 2378 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an 2379 array-like collection no matter what. 2380 @return {Array} A native array created from _thing_, according to the rules 2381 described above. 2382 **/ 2383 function YArray(thing, startIndex, force) { 2384 var len, result; 2385 2386 /*jshint expr: true*/ 2387 startIndex || (startIndex = 0); 2388 2389 if (force || YArray.test(thing)) { 2390 // IE throws when trying to slice HTMLElement collections. 2391 try { 2392 return Native.slice.call(thing, startIndex); 2393 } catch (ex) { 2394 result = []; 2395 2396 for (len = thing.length; startIndex < len; ++startIndex) { 2397 result.push(thing[startIndex]); 2398 } 2399 2400 return result; 2401 } 2402 } 2403 2404 return [thing]; 2405 } 2406 2407 Y.Array = YArray; 2408 2409 /** 2410 Dedupes an array of strings, returning an array that's guaranteed to contain 2411 only one copy of a given string. 2412 2413 This method differs from `Array.unique()` in that it's optimized for use only 2414 with arrays consisting entirely of strings or entirely of numbers, whereas 2415 `unique` may be used with other value types (but is slower). 2416 2417 Using `dedupe()` with values other than strings or numbers, or with arrays 2418 containing a mix of strings and numbers, may result in unexpected behavior. 2419 2420 @method dedupe 2421 @param {String[]|Number[]} array Array of strings or numbers to dedupe. 2422 @return {Array} Copy of _array_ containing no duplicate values. 2423 @static 2424 @since 3.4.0 2425 **/ 2426 YArray.dedupe = Lang._isNative(Object.create) ? function (array) { 2427 var hash = Object.create(null), 2428 results = [], 2429 i, item, len; 2430 2431 for (i = 0, len = array.length; i < len; ++i) { 2432 item = array[i]; 2433 2434 if (!hash[item]) { 2435 hash[item] = 1; 2436 results.push(item); 2437 } 2438 } 2439 2440 return results; 2441 } : function (array) { 2442 var hash = {}, 2443 results = [], 2444 i, item, len; 2445 2446 for (i = 0, len = array.length; i < len; ++i) { 2447 item = array[i]; 2448 2449 if (!hasOwn.call(hash, item)) { 2450 hash[item] = 1; 2451 results.push(item); 2452 } 2453 } 2454 2455 return results; 2456 }; 2457 2458 /** 2459 Executes the supplied function on each item in the array. This method wraps 2460 the native ES5 `Array.forEach()` method if available. 2461 2462 @method each 2463 @param {Array} array Array to iterate. 2464 @param {Function} fn Function to execute on each item in the array. The function 2465 will receive the following arguments: 2466 @param {Any} fn.item Current array item. 2467 @param {Number} fn.index Current array index. 2468 @param {Array} fn.array Array being iterated. 2469 @param {Object} [thisObj] `this` object to use when calling _fn_. 2470 @return {YUI} The YUI instance. 2471 @static 2472 **/ 2473 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) { 2474 Native.forEach.call(array || [], fn, thisObj || Y); 2475 return Y; 2476 } : function (array, fn, thisObj) { 2477 for (var i = 0, len = (array && array.length) || 0; i < len; ++i) { 2478 if (i in array) { 2479 fn.call(thisObj || Y, array[i], i, array); 2480 } 2481 } 2482 2483 return Y; 2484 }; 2485 2486 /** 2487 Alias for `each()`. 2488 2489 @method forEach 2490 @static 2491 **/ 2492 2493 /** 2494 Returns an object using the first array as keys and the second as values. If 2495 the second array is not provided, or if it doesn't contain the same number of 2496 values as the first array, then `true` will be used in place of the missing 2497 values. 2498 2499 @example 2500 2501 Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']); 2502 // => {a: 'foo', b: 'bar', c: true} 2503 2504 @method hash 2505 @param {String[]} keys Array of strings to use as keys. 2506 @param {Array} [values] Array to use as values. 2507 @return {Object} Hash using the first array as keys and the second as values. 2508 @static 2509 **/ 2510 YArray.hash = function (keys, values) { 2511 var hash = {}, 2512 vlen = (values && values.length) || 0, 2513 i, len; 2514 2515 for (i = 0, len = keys.length; i < len; ++i) { 2516 if (i in keys) { 2517 hash[keys[i]] = vlen > i && i in values ? values[i] : true; 2518 } 2519 } 2520 2521 return hash; 2522 }; 2523 2524 /** 2525 Returns the index of the first item in the array that's equal (using a strict 2526 equality check) to the specified _value_, or `-1` if the value isn't found. 2527 2528 This method wraps the native ES5 `Array.indexOf()` method if available. 2529 2530 @method indexOf 2531 @param {Array} array Array to search. 2532 @param {Any} value Value to search for. 2533 @param {Number} [from=0] The index at which to begin the search. 2534 @return {Number} Index of the item strictly equal to _value_, or `-1` if not 2535 found. 2536 @static 2537 **/ 2538 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) { 2539 return Native.indexOf.call(array, value, from); 2540 } : function (array, value, from) { 2541 // http://es5.github.com/#x15.4.4.14 2542 var len = array.length; 2543 2544 from = +from || 0; 2545 from = (from > 0 || -1) * Math.floor(Math.abs(from)); 2546 2547 if (from < 0) { 2548 from += len; 2549 2550 if (from < 0) { 2551 from = 0; 2552 } 2553 } 2554 2555 for (; from < len; ++from) { 2556 if (from in array && array[from] === value) { 2557 return from; 2558 } 2559 } 2560 2561 return -1; 2562 }; 2563 2564 /** 2565 Numeric sort convenience function. 2566 2567 The native `Array.prototype.sort()` function converts values to strings and 2568 sorts them in lexicographic order, which is unsuitable for sorting numeric 2569 values. Provide `Array.numericSort` as a custom sort function when you want 2570 to sort values in numeric order. 2571 2572 @example 2573 2574 [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort); 2575 // => [4, 8, 15, 16, 23, 42] 2576 2577 @method numericSort 2578 @param {Number} a First value to compare. 2579 @param {Number} b Second value to compare. 2580 @return {Number} Difference between _a_ and _b_. 2581 @static 2582 **/ 2583 YArray.numericSort = function (a, b) { 2584 return a - b; 2585 }; 2586 2587 /** 2588 Executes the supplied function on each item in the array. Returning a truthy 2589 value from the function will stop the processing of remaining items. 2590 2591 @method some 2592 @param {Array} array Array to iterate over. 2593 @param {Function} fn Function to execute on each item. The function will receive 2594 the following arguments: 2595 @param {Any} fn.value Current array item. 2596 @param {Number} fn.index Current array index. 2597 @param {Array} fn.array Array being iterated over. 2598 @param {Object} [thisObj] `this` object to use when calling _fn_. 2599 @return {Boolean} `true` if the function returns a truthy value on any of the 2600 items in the array; `false` otherwise. 2601 @static 2602 **/ 2603 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) { 2604 return Native.some.call(array, fn, thisObj); 2605 } : function (array, fn, thisObj) { 2606 for (var i = 0, len = array.length; i < len; ++i) { 2607 if (i in array && fn.call(thisObj, array[i], i, array)) { 2608 return true; 2609 } 2610 } 2611 2612 return false; 2613 }; 2614 2615 /** 2616 Evaluates _obj_ to determine if it's an array, an array-like collection, or 2617 something else. This is useful when working with the function `arguments` 2618 collection and `HTMLElement` collections. 2619 2620 Note: This implementation doesn't consider elements that are also 2621 collections, such as `<form>` and `<select>`, to be array-like. 2622 2623 @method test 2624 @param {Object} obj Object to test. 2625 @return {Number} A number indicating the results of the test: 2626 2627 * 0: Neither an array nor an array-like collection. 2628 * 1: Real array. 2629 * 2: Array-like collection. 2630 2631 @static 2632 **/ 2633 YArray.test = function (obj) { 2634 var result = 0; 2635 2636 if (Lang.isArray(obj)) { 2637 result = 1; 2638 } else if (Lang.isObject(obj)) { 2639 try { 2640 // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here), 2641 // or functions without apply/call (Safari 2642 // HTMLElementCollection bug). 2643 if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) { 2644 result = 2; 2645 } 2646 } catch (ex) {} 2647 } 2648 2649 return result; 2650 }; 2651 /** 2652 * The YUI module contains the components required for building the YUI 2653 * seed file. This includes the script loading mechanism, a simple queue, 2654 * and the core utilities for the library. 2655 * @module yui 2656 * @submodule yui-base 2657 */ 2658 2659 /** 2660 * A simple FIFO queue. Items are added to the Queue with add(1..n items) and 2661 * removed using next(). 2662 * 2663 * @class Queue 2664 * @constructor 2665 * @param {MIXED} item* 0..n items to seed the queue. 2666 */ 2667 function Queue() { 2668 this._init(); 2669 this.add.apply(this, arguments); 2670 } 2671 2672 Queue.prototype = { 2673 /** 2674 * Initialize the queue 2675 * 2676 * @method _init 2677 * @protected 2678 */ 2679 _init: function() { 2680 /** 2681 * The collection of enqueued items 2682 * 2683 * @property _q 2684 * @type Array 2685 * @protected 2686 */ 2687 this._q = []; 2688 }, 2689 2690 /** 2691 * Get the next item in the queue. FIFO support 2692 * 2693 * @method next 2694 * @return {MIXED} the next item in the queue. 2695 */ 2696 next: function() { 2697 return this._q.shift(); 2698 }, 2699 2700 /** 2701 * Get the last in the queue. LIFO support. 2702 * 2703 * @method last 2704 * @return {MIXED} the last item in the queue. 2705 */ 2706 last: function() { 2707 return this._q.pop(); 2708 }, 2709 2710 /** 2711 * Add 0..n items to the end of the queue. 2712 * 2713 * @method add 2714 * @param {MIXED} item* 0..n items. 2715 * @return {object} this queue. 2716 */ 2717 add: function() { 2718 this._q.push.apply(this._q, arguments); 2719 2720 return this; 2721 }, 2722 2723 /** 2724 * Returns the current number of queued items. 2725 * 2726 * @method size 2727 * @return {Number} The size. 2728 */ 2729 size: function() { 2730 return this._q.length; 2731 } 2732 }; 2733 2734 Y.Queue = Queue; 2735 2736 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue(); 2737 2738 /** 2739 The YUI module contains the components required for building the YUI seed file. 2740 This includes the script loading mechanism, a simple queue, and the core 2741 utilities for the library. 2742 2743 @module yui 2744 @submodule yui-base 2745 **/ 2746 2747 var CACHED_DELIMITER = '__', 2748 2749 hasOwn = Object.prototype.hasOwnProperty, 2750 isObject = Y.Lang.isObject; 2751 2752 /** 2753 Returns a wrapper for a function which caches the return value of that function, 2754 keyed off of the combined string representation of the argument values provided 2755 when the wrapper is called. 2756 2757 Calling this function again with the same arguments will return the cached value 2758 rather than executing the wrapped function. 2759 2760 Note that since the cache is keyed off of the string representation of arguments 2761 passed to the wrapper function, arguments that aren't strings and don't provide 2762 a meaningful `toString()` method may result in unexpected caching behavior. For 2763 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the 2764 string `[object Object]` when used as a cache key. 2765 2766 @method cached 2767 @param {Function} source The function to memoize. 2768 @param {Object} [cache={}] Object in which to store cached values. You may seed 2769 this object with pre-existing cached values if desired. 2770 @param {any} [refetch] If supplied, this value is compared with the cached value 2771 using a `==` comparison. If the values are equal, the wrapped function is 2772 executed again even though a cached value exists. 2773 @return {Function} Wrapped function. 2774 @for YUI 2775 **/ 2776 Y.cached = function (source, cache, refetch) { 2777 /*jshint expr: true*/ 2778 cache || (cache = {}); 2779 2780 return function (arg) { 2781 var key = arguments.length > 1 ? 2782 Array.prototype.join.call(arguments, CACHED_DELIMITER) : 2783 String(arg); 2784 2785 /*jshint eqeqeq: false*/ 2786 if (!(key in cache) || (refetch && cache[key] == refetch)) { 2787 cache[key] = source.apply(source, arguments); 2788 } 2789 2790 return cache[key]; 2791 }; 2792 }; 2793 2794 /** 2795 Returns the `location` object from the window/frame in which this YUI instance 2796 operates, or `undefined` when executing in a non-browser environment 2797 (e.g. Node.js). 2798 2799 It is _not_ recommended to hold references to the `window.location` object 2800 outside of the scope of a function in which its properties are being accessed or 2801 its methods are being called. This is because of a nasty bug/issue that exists 2802 in both Safari and MobileSafari browsers: 2803 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679). 2804 2805 @method getLocation 2806 @return {location} The `location` object from the window/frame in which this YUI 2807 instance operates. 2808 @since 3.5.0 2809 **/ 2810 Y.getLocation = function () { 2811 // It is safer to look this up every time because yui-base is attached to a 2812 // YUI instance before a user's config is applied; i.e. `Y.config.win` does 2813 // not point the correct window object when this file is loaded. 2814 var win = Y.config.win; 2815 2816 // It is not safe to hold a reference to the `location` object outside the 2817 // scope in which it is being used. The WebKit engine used in Safari and 2818 // MobileSafari will "disconnect" the `location` object from the `window` 2819 // when a page is restored from back/forward history cache. 2820 return win && win.location; 2821 }; 2822 2823 /** 2824 Returns a new object containing all of the properties of all the supplied 2825 objects. The properties from later objects will overwrite those in earlier 2826 objects. 2827 2828 Passing in a single object will create a shallow copy of it. For a deep copy, 2829 use `clone()`. 2830 2831 @method merge 2832 @param {Object} objects* One or more objects to merge. 2833 @return {Object} A new merged object. 2834 **/ 2835 Y.merge = function () { 2836 var i = 0, 2837 len = arguments.length, 2838 result = {}, 2839 key, 2840 obj; 2841 2842 for (; i < len; ++i) { 2843 obj = arguments[i]; 2844 2845 for (key in obj) { 2846 if (hasOwn.call(obj, key)) { 2847 result[key] = obj[key]; 2848 } 2849 } 2850 } 2851 2852 return result; 2853 }; 2854 2855 /** 2856 Mixes _supplier_'s properties into _receiver_. 2857 2858 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or 2859 shadowed unless the _overwrite_ parameter is `true`, and will not be merged 2860 unless the _merge_ parameter is `true`. 2861 2862 In the default mode (0), only properties the supplier owns are copied (prototype 2863 properties are not copied). The following copying modes are available: 2864 2865 * `0`: _Default_. Object to object. 2866 * `1`: Prototype to prototype. 2867 * `2`: Prototype to prototype and object to object. 2868 * `3`: Prototype to object. 2869 * `4`: Object to prototype. 2870 2871 @method mix 2872 @param {Function|Object} receiver The object or function to receive the mixed 2873 properties. 2874 @param {Function|Object} supplier The object or function supplying the 2875 properties to be mixed. 2876 @param {Boolean} [overwrite=false] If `true`, properties that already exist 2877 on the receiver will be overwritten with properties from the supplier. 2878 @param {String[]} [whitelist] An array of property names to copy. If 2879 specified, only the whitelisted properties will be copied, and all others 2880 will be ignored. 2881 @param {Number} [mode=0] Mix mode to use. See above for available modes. 2882 @param {Boolean} [merge=false] If `true`, objects and arrays that already 2883 exist on the receiver will have the corresponding object/array from the 2884 supplier merged into them, rather than being skipped or overwritten. When 2885 both _overwrite_ and _merge_ are `true`, _merge_ takes precedence. 2886 @return {Function|Object|YUI} The receiver, or the YUI instance if the 2887 specified receiver is falsy. 2888 **/ 2889 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { 2890 var alwaysOverwrite, exists, from, i, key, len, to; 2891 2892 // If no supplier is given, we return the receiver. If no receiver is given, 2893 // we return Y. Returning Y doesn't make much sense to me, but it's 2894 // grandfathered in for backcompat reasons. 2895 if (!receiver || !supplier) { 2896 return receiver || Y; 2897 } 2898 2899 if (mode) { 2900 // In mode 2 (prototype to prototype and object to object), we recurse 2901 // once to do the proto to proto mix. The object to object mix will be 2902 // handled later on. 2903 if (mode === 2) { 2904 Y.mix(receiver.prototype, supplier.prototype, overwrite, 2905 whitelist, 0, merge); 2906 } 2907 2908 // Depending on which mode is specified, we may be copying from or to 2909 // the prototypes of the supplier and receiver. 2910 from = mode === 1 || mode === 3 ? supplier.prototype : supplier; 2911 to = mode === 1 || mode === 4 ? receiver.prototype : receiver; 2912 2913 // If either the supplier or receiver doesn't actually have a 2914 // prototype property, then we could end up with an undefined `from` 2915 // or `to`. If that happens, we abort and return the receiver. 2916 if (!from || !to) { 2917 return receiver; 2918 } 2919 } else { 2920 from = supplier; 2921 to = receiver; 2922 } 2923 2924 // If `overwrite` is truthy and `merge` is falsy, then we can skip a 2925 // property existence check on each iteration and save some time. 2926 alwaysOverwrite = overwrite && !merge; 2927 2928 if (whitelist) { 2929 for (i = 0, len = whitelist.length; i < len; ++i) { 2930 key = whitelist[i]; 2931 2932 // We call `Object.prototype.hasOwnProperty` instead of calling 2933 // `hasOwnProperty` on the object itself, since the object's 2934 // `hasOwnProperty` method may have been overridden or removed. 2935 // Also, some native objects don't implement a `hasOwnProperty` 2936 // method. 2937 if (!hasOwn.call(from, key)) { 2938 continue; 2939 } 2940 2941 // The `key in to` check here is (sadly) intentional for backwards 2942 // compatibility reasons. It prevents undesired shadowing of 2943 // prototype members on `to`. 2944 exists = alwaysOverwrite ? false : key in to; 2945 2946 if (merge && exists && isObject(to[key], true) 2947 && isObject(from[key], true)) { 2948 // If we're in merge mode, and the key is present on both 2949 // objects, and the value on both objects is either an object or 2950 // an array (but not a function), then we recurse to merge the 2951 // `from` value into the `to` value instead of overwriting it. 2952 // 2953 // Note: It's intentional that the whitelist isn't passed to the 2954 // recursive call here. This is legacy behavior that lots of 2955 // code still depends on. 2956 Y.mix(to[key], from[key], overwrite, null, 0, merge); 2957 } else if (overwrite || !exists) { 2958 // We're not in merge mode, so we'll only copy the `from` value 2959 // to the `to` value if we're in overwrite mode or if the 2960 // current key doesn't exist on the `to` object. 2961 to[key] = from[key]; 2962 } 2963 } 2964 } else { 2965 for (key in from) { 2966 // The code duplication here is for runtime performance reasons. 2967 // Combining whitelist and non-whitelist operations into a single 2968 // loop or breaking the shared logic out into a function both result 2969 // in worse performance, and Y.mix is critical enough that the byte 2970 // tradeoff is worth it. 2971 if (!hasOwn.call(from, key)) { 2972 continue; 2973 } 2974 2975 // The `key in to` check here is (sadly) intentional for backwards 2976 // compatibility reasons. It prevents undesired shadowing of 2977 // prototype members on `to`. 2978 exists = alwaysOverwrite ? false : key in to; 2979 2980 if (merge && exists && isObject(to[key], true) 2981 && isObject(from[key], true)) { 2982 Y.mix(to[key], from[key], overwrite, null, 0, merge); 2983 } else if (overwrite || !exists) { 2984 to[key] = from[key]; 2985 } 2986 } 2987 2988 // If this is an IE browser with the JScript enumeration bug, force 2989 // enumeration of the buggy properties by making a recursive call with 2990 // the buggy properties as the whitelist. 2991 if (Y.Object._hasEnumBug) { 2992 Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge); 2993 } 2994 } 2995 2996 return receiver; 2997 }; 2998 /** 2999 * The YUI module contains the components required for building the YUI 3000 * seed file. This includes the script loading mechanism, a simple queue, 3001 * and the core utilities for the library. 3002 * @module yui 3003 * @submodule yui-base 3004 */ 3005 3006 /** 3007 * Adds utilities to the YUI instance for working with objects. 3008 * 3009 * @class Object 3010 */ 3011 3012 var Lang = Y.Lang, 3013 hasOwn = Object.prototype.hasOwnProperty, 3014 3015 UNDEFINED, // <-- Note the comma. We're still declaring vars. 3016 3017 /** 3018 * Returns a new object that uses _obj_ as its prototype. This method wraps the 3019 * native ES5 `Object.create()` method if available, but doesn't currently 3020 * pass through `Object.create()`'s second argument (properties) in order to 3021 * ensure compatibility with older browsers. 3022 * 3023 * @method () 3024 * @param {Object} obj Prototype object. 3025 * @return {Object} New object using _obj_ as its prototype. 3026 * @static 3027 */ 3028 O = Y.Object = Lang._isNative(Object.create) ? function (obj) { 3029 // We currently wrap the native Object.create instead of simply aliasing it 3030 // to ensure consistency with our fallback shim, which currently doesn't 3031 // support Object.create()'s second argument (properties). Once we have a 3032 // safe fallback for the properties arg, we can stop wrapping 3033 // Object.create(). 3034 return Object.create(obj); 3035 } : (function () { 3036 // Reusable constructor function for the Object.create() shim. 3037 function F() {} 3038 3039 // The actual shim. 3040 return function (obj) { 3041 F.prototype = obj; 3042 return new F(); 3043 }; 3044 }()), 3045 3046 /** 3047 * Property names that IE doesn't enumerate in for..in loops, even when they 3048 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to 3049 * manually enumerate these properties. 3050 * 3051 * @property _forceEnum 3052 * @type String[] 3053 * @protected 3054 * @static 3055 */ 3056 forceEnum = O._forceEnum = [ 3057 'hasOwnProperty', 3058 'isPrototypeOf', 3059 'propertyIsEnumerable', 3060 'toString', 3061 'toLocaleString', 3062 'valueOf' 3063 ], 3064 3065 /** 3066 * `true` if this browser has the JScript enumeration bug that prevents 3067 * enumeration of the properties named in the `_forceEnum` array, `false` 3068 * otherwise. 3069 * 3070 * See: 3071 * - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug> 3072 * - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation> 3073 * 3074 * @property _hasEnumBug 3075 * @type Boolean 3076 * @protected 3077 * @static 3078 */ 3079 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'), 3080 3081 /** 3082 * `true` if this browser incorrectly considers the `prototype` property of 3083 * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x. 3084 * 3085 * @property _hasProtoEnumBug 3086 * @type Boolean 3087 * @protected 3088 * @static 3089 */ 3090 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'), 3091 3092 /** 3093 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or 3094 * exists only on _obj_'s prototype. This is essentially a safer version of 3095 * `obj.hasOwnProperty()`. 3096 * 3097 * @method owns 3098 * @param {Object} obj Object to test. 3099 * @param {String} key Property name to look for. 3100 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise. 3101 * @static 3102 */ 3103 owns = O.owns = function (obj, key) { 3104 return !!obj && hasOwn.call(obj, key); 3105 }; // <-- End of var declarations. 3106 3107 /** 3108 * Alias for `owns()`. 3109 * 3110 * @method hasKey 3111 * @param {Object} obj Object to test. 3112 * @param {String} key Property name to look for. 3113 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise. 3114 * @static 3115 */ 3116 O.hasKey = owns; 3117 3118 /** 3119 * Returns an array containing the object's enumerable keys. Does not include 3120 * prototype keys or non-enumerable keys. 3121 * 3122 * Note that keys are returned in enumeration order (that is, in the same order 3123 * that they would be enumerated by a `for-in` loop), which may not be the same 3124 * as the order in which they were defined. 3125 * 3126 * This method is an alias for the native ES5 `Object.keys()` method if 3127 * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of 3128 * `Object.keys()` have an inconsistency as they consider `prototype` to be 3129 * enumerable, so a non-native shim is used to rectify the difference. 3130 * 3131 * @example 3132 * 3133 * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'}); 3134 * // => ['a', 'b', 'c'] 3135 * 3136 * @method keys 3137 * @param {Object} obj An object. 3138 * @return {String[]} Array of keys. 3139 * @static 3140 */ 3141 O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) { 3142 if (!Lang.isObject(obj)) { 3143 throw new TypeError('Object.keys called on a non-object'); 3144 } 3145 3146 var keys = [], 3147 i, key, len; 3148 3149 if (hasProtoEnumBug && typeof obj === 'function') { 3150 for (key in obj) { 3151 if (owns(obj, key) && key !== 'prototype') { 3152 keys.push(key); 3153 } 3154 } 3155 } else { 3156 for (key in obj) { 3157 if (owns(obj, key)) { 3158 keys.push(key); 3159 } 3160 } 3161 } 3162 3163 if (hasEnumBug) { 3164 for (i = 0, len = forceEnum.length; i < len; ++i) { 3165 key = forceEnum[i]; 3166 3167 if (owns(obj, key)) { 3168 keys.push(key); 3169 } 3170 } 3171 } 3172 3173 return keys; 3174 }; 3175 3176 /** 3177 * Returns an array containing the values of the object's enumerable keys. 3178 * 3179 * Note that values are returned in enumeration order (that is, in the same 3180 * order that they would be enumerated by a `for-in` loop), which may not be the 3181 * same as the order in which they were defined. 3182 * 3183 * @example 3184 * 3185 * Y.Object.values({a: 'foo', b: 'bar', c: 'baz'}); 3186 * // => ['foo', 'bar', 'baz'] 3187 * 3188 * @method values 3189 * @param {Object} obj An object. 3190 * @return {Array} Array of values. 3191 * @static 3192 */ 3193 O.values = function (obj) { 3194 var keys = O.keys(obj), 3195 i = 0, 3196 len = keys.length, 3197 values = []; 3198 3199 for (; i < len; ++i) { 3200 values.push(obj[keys[i]]); 3201 } 3202 3203 return values; 3204 }; 3205 3206 /** 3207 * Returns the number of enumerable keys owned by an object. 3208 * 3209 * @method size 3210 * @param {Object} obj An object. 3211 * @return {Number} The object's size. 3212 * @static 3213 */ 3214 O.size = function (obj) { 3215 try { 3216 return O.keys(obj).length; 3217 } catch (ex) { 3218 return 0; // Legacy behavior for non-objects. 3219 } 3220 }; 3221 3222 /** 3223 * Returns `true` if the object owns an enumerable property with the specified 3224 * value. 3225 * 3226 * @method hasValue 3227 * @param {Object} obj An object. 3228 * @param {any} value The value to search for. 3229 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise. 3230 * @static 3231 */ 3232 O.hasValue = function (obj, value) { 3233 return Y.Array.indexOf(O.values(obj), value) > -1; 3234 }; 3235 3236 /** 3237 * Executes a function on each enumerable property in _obj_. The function 3238 * receives the value, the key, and the object itself as parameters (in that 3239 * order). 3240 * 3241 * By default, only properties owned by _obj_ are enumerated. To include 3242 * prototype properties, set the _proto_ parameter to `true`. 3243 * 3244 * @method each 3245 * @param {Object} obj Object to enumerate. 3246 * @param {Function} fn Function to execute on each enumerable property. 3247 * @param {mixed} fn.value Value of the current property. 3248 * @param {String} fn.key Key of the current property. 3249 * @param {Object} fn.obj Object being enumerated. 3250 * @param {Object} [thisObj] `this` object to use when calling _fn_. 3251 * @param {Boolean} [proto=false] Include prototype properties. 3252 * @return {YUI} the YUI instance. 3253 * @chainable 3254 * @static 3255 */ 3256 O.each = function (obj, fn, thisObj, proto) { 3257 var key; 3258 3259 for (key in obj) { 3260 if (proto || owns(obj, key)) { 3261 fn.call(thisObj || Y, obj[key], key, obj); 3262 } 3263 } 3264 3265 return Y; 3266 }; 3267 3268 /** 3269 * Executes a function on each enumerable property in _obj_, but halts if the 3270 * function returns a truthy value. The function receives the value, the key, 3271 * and the object itself as paramters (in that order). 3272 * 3273 * By default, only properties owned by _obj_ are enumerated. To include 3274 * prototype properties, set the _proto_ parameter to `true`. 3275 * 3276 * @method some 3277 * @param {Object} obj Object to enumerate. 3278 * @param {Function} fn Function to execute on each enumerable property. 3279 * @param {mixed} fn.value Value of the current property. 3280 * @param {String} fn.key Key of the current property. 3281 * @param {Object} fn.obj Object being enumerated. 3282 * @param {Object} [thisObj] `this` object to use when calling _fn_. 3283 * @param {Boolean} [proto=false] Include prototype properties. 3284 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value, 3285 * `false` otherwise. 3286 * @static 3287 */ 3288 O.some = function (obj, fn, thisObj, proto) { 3289 var key; 3290 3291 for (key in obj) { 3292 if (proto || owns(obj, key)) { 3293 if (fn.call(thisObj || Y, obj[key], key, obj)) { 3294 return true; 3295 } 3296 } 3297 } 3298 3299 return false; 3300 }; 3301 3302 /** 3303 * Retrieves the sub value at the provided path, 3304 * from the value object provided. 3305 * 3306 * @method getValue 3307 * @static 3308 * @param o The object from which to extract the property value. 3309 * @param path {Array} A path array, specifying the object traversal path 3310 * from which to obtain the sub value. 3311 * @return {Any} The value stored in the path, undefined if not found, 3312 * undefined if the source is not an object. Returns the source object 3313 * if an empty path is provided. 3314 */ 3315 O.getValue = function(o, path) { 3316 if (!Lang.isObject(o)) { 3317 return UNDEFINED; 3318 } 3319 3320 var i, 3321 p = Y.Array(path), 3322 l = p.length; 3323 3324 for (i = 0; o !== UNDEFINED && i < l; i++) { 3325 o = o[p[i]]; 3326 } 3327 3328 return o; 3329 }; 3330 3331 /** 3332 * Sets the sub-attribute value at the provided path on the 3333 * value object. Returns the modified value object, or 3334 * undefined if the path is invalid. 3335 * 3336 * @method setValue 3337 * @static 3338 * @param o The object on which to set the sub value. 3339 * @param path {Array} A path array, specifying the object traversal path 3340 * at which to set the sub value. 3341 * @param val {Any} The new value for the sub-attribute. 3342 * @return {Object} The modified object, with the new sub value set, or 3343 * undefined, if the path was invalid. 3344 */ 3345 O.setValue = function(o, path, val) { 3346 var i, 3347 p = Y.Array(path), 3348 leafIdx = p.length - 1, 3349 ref = o; 3350 3351 if (leafIdx >= 0) { 3352 for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) { 3353 ref = ref[p[i]]; 3354 } 3355 3356 if (ref !== UNDEFINED) { 3357 ref[p[i]] = val; 3358 } else { 3359 return UNDEFINED; 3360 } 3361 } 3362 3363 return o; 3364 }; 3365 3366 /** 3367 * Returns `true` if the object has no enumerable properties of its own. 3368 * 3369 * @method isEmpty 3370 * @param {Object} obj An object. 3371 * @return {Boolean} `true` if the object is empty. 3372 * @static 3373 * @since 3.2.0 3374 */ 3375 O.isEmpty = function (obj) { 3376 return !O.keys(Object(obj)).length; 3377 }; 3378 /** 3379 * The YUI module contains the components required for building the YUI seed 3380 * file. This includes the script loading mechanism, a simple queue, and the 3381 * core utilities for the library. 3382 * @module yui 3383 * @submodule yui-base 3384 */ 3385 3386 /** 3387 * YUI user agent detection. 3388 * Do not fork for a browser if it can be avoided. Use feature detection when 3389 * you can. Use the user agent as a last resort. For all fields listed 3390 * as @type float, UA stores a version number for the browser engine, 3391 * 0 otherwise. This value may or may not map to the version number of 3392 * the browser using the engine. The value is presented as a float so 3393 * that it can easily be used for boolean evaluation as well as for 3394 * looking for a particular range of versions. Because of this, 3395 * some of the granularity of the version info may be lost. The fields that 3396 * are @type string default to null. The API docs list the values that 3397 * these fields can have. 3398 * @class UA 3399 * @static 3400 */ 3401 3402 /** 3403 * Static method on `YUI.Env` for parsing a UA string. Called at instantiation 3404 * to populate `Y.UA`. 3405 * 3406 * @static 3407 * @method parseUA 3408 * @param {String} [subUA=navigator.userAgent] UA string to parse 3409 * @return {Object} The Y.UA object 3410 */ 3411 YUI.Env.parseUA = function(subUA) { 3412 3413 var numberify = function(s) { 3414 var c = 0; 3415 return parseFloat(s.replace(/\./g, function() { 3416 return (c++ === 1) ? '' : '.'; 3417 })); 3418 }, 3419 3420 win = Y.config.win, 3421 3422 nav = win && win.navigator, 3423 3424 o = { 3425 3426 /** 3427 * Internet Explorer version number or 0. Example: 6 3428 * @property ie 3429 * @type float 3430 * @static 3431 */ 3432 ie: 0, 3433 3434 /** 3435 * Opera version number or 0. Example: 9.2 3436 * @property opera 3437 * @type float 3438 * @static 3439 */ 3440 opera: 0, 3441 3442 /** 3443 * Gecko engine revision number. Will evaluate to 1 if Gecko 3444 * is detected but the revision could not be found. Other browsers 3445 * will be 0. Example: 1.8 3446 * <pre> 3447 * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7 3448 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8 3449 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81 3450 * Firefox 3.0 <-- 1.9 3451 * Firefox 3.5 <-- 1.91 3452 * </pre> 3453 * @property gecko 3454 * @type float 3455 * @static 3456 */ 3457 gecko: 0, 3458 3459 /** 3460 * AppleWebKit version. KHTML browsers that are not WebKit browsers 3461 * will evaluate to 1, other browsers 0. Example: 418.9 3462 * <pre> 3463 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the 3464 * latest available for Mac OSX 10.3. 3465 * Safari 2.0.2: 416 <-- hasOwnProperty introduced 3466 * Safari 2.0.4: 418 <-- preventDefault fixed 3467 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run 3468 * different versions of webkit 3469 * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been 3470 * updated, but not updated 3471 * to the latest patch. 3472 * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native 3473 * SVG and many major issues fixed). 3474 * Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic 3475 * update from 2.x via the 10.4.11 OS patch. 3476 * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event. 3477 * yahoo.com user agent hack removed. 3478 * </pre> 3479 * http://en.wikipedia.org/wiki/Safari_version_history 3480 * @property webkit 3481 * @type float 3482 * @static 3483 */ 3484 webkit: 0, 3485 3486 /** 3487 * Safari will be detected as webkit, but this property will also 3488 * be populated with the Safari version number 3489 * @property safari 3490 * @type float 3491 * @static 3492 */ 3493 safari: 0, 3494 3495 /** 3496 * Chrome will be detected as webkit, but this property will also 3497 * be populated with the Chrome version number 3498 * @property chrome 3499 * @type float 3500 * @static 3501 */ 3502 chrome: 0, 3503 3504 /** 3505 * The mobile property will be set to a string containing any relevant 3506 * user agent information when a modern mobile browser is detected. 3507 * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series 3508 * devices with the WebKit-based browser, and Opera Mini. 3509 * @property mobile 3510 * @type string 3511 * @default null 3512 * @static 3513 */ 3514 mobile: null, 3515 3516 /** 3517 * Adobe AIR version number or 0. Only populated if webkit is detected. 3518 * Example: 1.0 3519 * @property air 3520 * @type float 3521 */ 3522 air: 0, 3523 /** 3524 * PhantomJS version number or 0. Only populated if webkit is detected. 3525 * Example: 1.0 3526 * @property phantomjs 3527 * @type float 3528 */ 3529 phantomjs: 0, 3530 /** 3531 * Detects Apple iPad's OS version 3532 * @property ipad 3533 * @type float 3534 * @static 3535 */ 3536 ipad: 0, 3537 /** 3538 * Detects Apple iPhone's OS version 3539 * @property iphone 3540 * @type float 3541 * @static 3542 */ 3543 iphone: 0, 3544 /** 3545 * Detects Apples iPod's OS version 3546 * @property ipod 3547 * @type float 3548 * @static 3549 */ 3550 ipod: 0, 3551 /** 3552 * General truthy check for iPad, iPhone or iPod 3553 * @property ios 3554 * @type Boolean 3555 * @default null 3556 * @static 3557 */ 3558 ios: null, 3559 /** 3560 * Detects Googles Android OS version 3561 * @property android 3562 * @type float 3563 * @static 3564 */ 3565 android: 0, 3566 /** 3567 * Detects Kindle Silk 3568 * @property silk 3569 * @type float 3570 * @static 3571 */ 3572 silk: 0, 3573 /** 3574 * Detects Ubuntu version 3575 * @property ubuntu 3576 * @type float 3577 * @static 3578 */ 3579 ubuntu: 0, 3580 /** 3581 * Detects Kindle Silk Acceleration 3582 * @property accel 3583 * @type Boolean 3584 * @static 3585 */ 3586 accel: false, 3587 /** 3588 * Detects Palms WebOS version 3589 * @property webos 3590 * @type float 3591 * @static 3592 */ 3593 webos: 0, 3594 3595 /** 3596 * Google Caja version number or 0. 3597 * @property caja 3598 * @type float 3599 */ 3600 caja: nav && nav.cajaVersion, 3601 3602 /** 3603 * Set to true if the page appears to be in SSL 3604 * @property secure 3605 * @type boolean 3606 * @static 3607 */ 3608 secure: false, 3609 3610 /** 3611 * The operating system. Currently only detecting windows or macintosh 3612 * @property os 3613 * @type string 3614 * @default null 3615 * @static 3616 */ 3617 os: null, 3618 3619 /** 3620 * The Nodejs Version 3621 * @property nodejs 3622 * @type float 3623 * @default 0 3624 * @static 3625 */ 3626 nodejs: 0, 3627 /** 3628 * Window8/IE10 Application host environment 3629 * @property winjs 3630 * @type Boolean 3631 * @static 3632 */ 3633 winjs: !!((typeof Windows !== "undefined") && Windows.System), 3634 /** 3635 * Are touch/msPointer events available on this device 3636 * @property touchEnabled 3637 * @type Boolean 3638 * @static 3639 */ 3640 touchEnabled: false 3641 }, 3642 3643 ua = subUA || nav && nav.userAgent, 3644 3645 loc = win && win.location, 3646 3647 href = loc && loc.href, 3648 3649 m; 3650 3651 /** 3652 * The User Agent string that was parsed 3653 * @property userAgent 3654 * @type String 3655 * @static 3656 */ 3657 o.userAgent = ua; 3658 3659 3660 o.secure = href && (href.toLowerCase().indexOf('https') === 0); 3661 3662 if (ua) { 3663 3664 if ((/windows|win32/i).test(ua)) { 3665 o.os = 'windows'; 3666 } else if ((/macintosh|mac_powerpc/i).test(ua)) { 3667 o.os = 'macintosh'; 3668 } else if ((/android/i).test(ua)) { 3669 o.os = 'android'; 3670 } else if ((/symbos/i).test(ua)) { 3671 o.os = 'symbos'; 3672 } else if ((/linux/i).test(ua)) { 3673 o.os = 'linux'; 3674 } else if ((/rhino/i).test(ua)) { 3675 o.os = 'rhino'; 3676 } 3677 3678 // Modern KHTML browsers should qualify as Safari X-Grade 3679 if ((/KHTML/).test(ua)) { 3680 o.webkit = 1; 3681 } 3682 if ((/IEMobile|XBLWP7/).test(ua)) { 3683 o.mobile = 'windows'; 3684 } 3685 if ((/Fennec/).test(ua)) { 3686 o.mobile = 'gecko'; 3687 } 3688 // Modern WebKit browsers are at least X-Grade 3689 m = ua.match(/AppleWebKit\/([^\s]*)/); 3690 if (m && m[1]) { 3691 o.webkit = numberify(m[1]); 3692 o.safari = o.webkit; 3693 3694 if (/PhantomJS/.test(ua)) { 3695 m = ua.match(/PhantomJS\/([^\s]*)/); 3696 if (m && m[1]) { 3697 o.phantomjs = numberify(m[1]); 3698 } 3699 } 3700 3701 // Mobile browser check 3702 if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) { 3703 o.mobile = 'Apple'; // iPhone or iPod Touch 3704 3705 m = ua.match(/OS ([^\s]*)/); 3706 if (m && m[1]) { 3707 m = numberify(m[1].replace('_', '.')); 3708 } 3709 o.ios = m; 3710 o.os = 'ios'; 3711 o.ipad = o.ipod = o.iphone = 0; 3712 3713 m = ua.match(/iPad|iPod|iPhone/); 3714 if (m && m[0]) { 3715 o[m[0].toLowerCase()] = o.ios; 3716 } 3717 } else { 3718 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/); 3719 if (m) { 3720 // Nokia N-series, webOS, ex: NokiaN95 3721 o.mobile = m[0]; 3722 } 3723 if (/webOS/.test(ua)) { 3724 o.mobile = 'WebOS'; 3725 m = ua.match(/webOS\/([^\s]*);/); 3726 if (m && m[1]) { 3727 o.webos = numberify(m[1]); 3728 } 3729 } 3730 if (/ Android/.test(ua)) { 3731 if (/Mobile/.test(ua)) { 3732 o.mobile = 'Android'; 3733 } 3734 m = ua.match(/Android ([^\s]*);/); 3735 if (m && m[1]) { 3736 o.android = numberify(m[1]); 3737 } 3738 3739 } 3740 if (/Silk/.test(ua)) { 3741 m = ua.match(/Silk\/([^\s]*)/); 3742 if (m && m[1]) { 3743 o.silk = numberify(m[1]); 3744 } 3745 if (!o.android) { 3746 o.android = 2.34; //Hack for desktop mode in Kindle 3747 o.os = 'Android'; 3748 } 3749 if (/Accelerated=true/.test(ua)) { 3750 o.accel = true; 3751 } 3752 } 3753 } 3754 3755 m = ua.match(/OPR\/(\d+\.\d+)/); 3756 3757 if (m && m[1]) { 3758 // Opera 15+ with Blink (pretends to be both Chrome and Safari) 3759 o.opera = numberify(m[1]); 3760 } else { 3761 m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/); 3762 3763 if (m && m[1] && m[2]) { 3764 o.chrome = numberify(m[2]); // Chrome 3765 o.safari = 0; //Reset safari back to 0 3766 if (m[1] === 'CrMo') { 3767 o.mobile = 'chrome'; 3768 } 3769 } else { 3770 m = ua.match(/AdobeAIR\/([^\s]*)/); 3771 if (m) { 3772 o.air = m[0]; // Adobe AIR 1.0 or better 3773 } 3774 } 3775 } 3776 } 3777 3778 m = ua.match(/Ubuntu\ (\d+\.\d+)/); 3779 if (m && m[1]) { 3780 3781 o.os = 'linux'; 3782 o.ubuntu = numberify(m[1]); 3783 3784 m = ua.match(/\ WebKit\/([^\s]*)/); 3785 if (m && m[1]) { 3786 o.webkit = numberify(m[1]); 3787 } 3788 m = ua.match(/\ Chromium\/([^\s]*)/); 3789 if (m && m[1]) { 3790 o.chrome = numberify(m[1]); 3791 } 3792 if (/ Mobile$/.test(ua)) { 3793 o.mobile = 'Ubuntu'; 3794 } 3795 } 3796 3797 if (!o.webkit) { // not webkit 3798 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) 3799 if (/Opera/.test(ua)) { 3800 m = ua.match(/Opera[\s\/]([^\s]*)/); 3801 if (m && m[1]) { 3802 o.opera = numberify(m[1]); 3803 } 3804 m = ua.match(/Version\/([^\s]*)/); 3805 if (m && m[1]) { 3806 o.opera = numberify(m[1]); // opera 10+ 3807 } 3808 3809 if (/Opera Mobi/.test(ua)) { 3810 o.mobile = 'opera'; 3811 m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/); 3812 if (m && m[1]) { 3813 o.opera = numberify(m[1]); 3814 } 3815 } 3816 m = ua.match(/Opera Mini[^;]*/); 3817 3818 if (m) { 3819 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 3820 } 3821 } else { // not opera or webkit 3822 m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/); 3823 3824 if (m && (m[1] || m[2])) { 3825 o.ie = numberify(m[1] || m[2]); 3826 } else { // not opera, webkit, or ie 3827 m = ua.match(/Gecko\/([^\s]*)/); 3828 3829 if (m) { 3830 o.gecko = 1; // Gecko detected, look for revision 3831 m = ua.match(/rv:([^\s\)]*)/); 3832 if (m && m[1]) { 3833 o.gecko = numberify(m[1]); 3834 if (/Mobile|Tablet/.test(ua)) { 3835 o.mobile = "ffos"; 3836 } 3837 } 3838 } 3839 } 3840 } 3841 } 3842 } 3843 3844 //Check for known properties to tell if touch events are enabled on this device or if 3845 //the number of MSPointer touchpoints on this device is greater than 0. 3846 if (win && nav && !(o.chrome && o.chrome < 6)) { 3847 o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0))); 3848 } 3849 3850 //It was a parsed UA, do not assign the global value. 3851 if (!subUA) { 3852 3853 if (typeof process === 'object') { 3854 3855 if (process.versions && process.versions.node) { 3856 //NodeJS 3857 o.os = process.platform; 3858 o.nodejs = numberify(process.versions.node); 3859 } 3860 } 3861 3862 YUI.Env.UA = o; 3863 3864 } 3865 3866 return o; 3867 }; 3868 3869 3870 Y.UA = YUI.Env.UA || YUI.Env.parseUA(); 3871 3872 /** 3873 Performs a simple comparison between two version numbers, accounting for 3874 standard versioning logic such as the fact that "535.8" is a lower version than 3875 "535.24", even though a simple numerical comparison would indicate that it's 3876 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are 3877 considered equivalent. 3878 3879 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent, 3880 1 if _a_ is higher than _b_. 3881 3882 Versions may be numbers or strings containing numbers and dots. For example, 3883 both `535` and `"535.8.10"` are acceptable. A version string containing 3884 non-numeric characters, like `"535.8.beta"`, may produce unexpected results. 3885 3886 @method compareVersions 3887 @param {Number|String} a First version number to compare. 3888 @param {Number|String} b Second version number to compare. 3889 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is 3890 higher than _b_. 3891 **/ 3892 Y.UA.compareVersions = function (a, b) { 3893 var aPart, aParts, bPart, bParts, i, len; 3894 3895 if (a === b) { 3896 return 0; 3897 } 3898 3899 aParts = (a + '').split('.'); 3900 bParts = (b + '').split('.'); 3901 3902 for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) { 3903 aPart = parseInt(aParts[i], 10); 3904 bPart = parseInt(bParts[i], 10); 3905 3906 /*jshint expr: true*/ 3907 isNaN(aPart) && (aPart = 0); 3908 isNaN(bPart) && (bPart = 0); 3909 3910 if (aPart < bPart) { 3911 return -1; 3912 } 3913 3914 if (aPart > bPart) { 3915 return 1; 3916 } 3917 } 3918 3919 return 0; 3920 }; 3921 YUI.Env.aliases = { 3922 "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"], 3923 "anim-shape-transform": ["anim-shape"], 3924 "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"], 3925 "attribute": ["attribute-base","attribute-complex"], 3926 "attribute-events": ["attribute-observable"], 3927 "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"], 3928 "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"], 3929 "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"], 3930 "base": ["base-base","base-pluginhost","base-build"], 3931 "cache": ["cache-base","cache-offline","cache-plugin"], 3932 "charts": ["charts-base"], 3933 "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"], 3934 "color": ["color-base","color-hsl","color-harmony"], 3935 "controller": ["router"], 3936 "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"], 3937 "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"], 3938 "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"], 3939 "datatype": ["datatype-date","datatype-number","datatype-xml"], 3940 "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"], 3941 "datatype-number": ["datatype-number-parse","datatype-number-format"], 3942 "datatype-xml": ["datatype-xml-parse","datatype-xml-format"], 3943 "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"], 3944 "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"], 3945 "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"], 3946 "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"], 3947 "event-custom": ["event-custom-base","event-custom-complex"], 3948 "event-gestures": ["event-flick","event-move"], 3949 "handlebars": ["handlebars-compiler"], 3950 "highlight": ["highlight-base","highlight-accentfold"], 3951 "history": ["history-base","history-hash","history-html5"], 3952 "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"], 3953 "json": ["json-parse","json-stringify"], 3954 "loader": ["loader-base","loader-rollup","loader-yui3"], 3955 "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"], 3956 "pluginhost": ["pluginhost-base","pluginhost-config"], 3957 "querystring": ["querystring-parse","querystring-stringify"], 3958 "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"], 3959 "resize": ["resize-base","resize-proxy","resize-constrain"], 3960 "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"], 3961 "template": ["template-base","template-micro"], 3962 "text": ["text-accentfold","text-wordbreak"], 3963 "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"] 3964 }; 3965 3966 3967 }, '3.17.2', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]}); 3968 YUI.add('get', function (Y, NAME) { 3969 3970 /*jslint boss:true, expr:true, laxbreak: true */ 3971 3972 /** 3973 Provides dynamic loading of remote JavaScript and CSS resources. 3974 3975 @module get 3976 @class Get 3977 @static 3978 **/ 3979 3980 var Lang = Y.Lang, 3981 3982 CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode() 3983 3984 Get, Transaction; 3985 3986 Y.Get = Get = { 3987 // -- Public Properties ---------------------------------------------------- 3988 3989 /** 3990 Default options for CSS requests. Options specified here will override 3991 global defaults for CSS requests. 3992 3993 See the `options` property for all available options. 3994 3995 @property cssOptions 3996 @type Object 3997 @static 3998 @since 3.5.0 3999 **/ 4000 cssOptions: { 4001 attributes: { 4002 rel: 'stylesheet' 4003 }, 4004 4005 doc : Y.config.linkDoc || Y.config.doc, 4006 pollInterval: 50 4007 }, 4008 4009 /** 4010 Default options for JS requests. Options specified here will override global 4011 defaults for JS requests. 4012 4013 See the `options` property for all available options. 4014 4015 @property jsOptions 4016 @type Object 4017 @static 4018 @since 3.5.0 4019 **/ 4020 jsOptions: { 4021 autopurge: true, 4022 doc : Y.config.scriptDoc || Y.config.doc 4023 }, 4024 4025 /** 4026 Default options to use for all requests. 4027 4028 Note that while all available options are documented here for ease of 4029 discovery, some options (like callback functions) only make sense at the 4030 transaction level. 4031 4032 Callback functions specified via the options object or the `options` 4033 parameter of the `css()`, `js()`, or `load()` methods will receive the 4034 transaction object as a parameter. See `Y.Get.Transaction` for details on 4035 the properties and methods available on transactions. 4036 4037 @static 4038 @since 3.5.0 4039 @property {Object} options 4040 4041 @property {Boolean} [options.async=false] Whether or not to load scripts 4042 asynchronously, meaning they're requested in parallel and execution 4043 order is not guaranteed. Has no effect on CSS, since CSS is always 4044 loaded asynchronously. 4045 4046 @property {Object} [options.attributes] HTML attribute name/value pairs that 4047 should be added to inserted nodes. By default, the `charset` attribute 4048 will be set to "utf-8" and nodes will be given an auto-generated `id` 4049 attribute, but you can override these with your own values if desired. 4050 4051 @property {Boolean} [options.autopurge] Whether or not to automatically 4052 purge inserted nodes after the purge threshold is reached. This is 4053 `true` by default for JavaScript, but `false` for CSS since purging a 4054 CSS node will also remove any styling applied by the referenced file. 4055 4056 @property {Object} [options.context] `this` object to use when calling 4057 callback functions. Defaults to the transaction object. 4058 4059 @property {Mixed} [options.data] Arbitrary data object to pass to "on*" 4060 callbacks. 4061 4062 @property {Document} [options.doc] Document into which nodes should be 4063 inserted. By default, the current document is used. 4064 4065 @property {HTMLElement|String} [options.insertBefore] HTML element or id 4066 string of an element before which all generated nodes should be 4067 inserted. If not specified, Get will automatically determine the best 4068 place to insert nodes for maximum compatibility. 4069 4070 @property {Function} [options.onEnd] Callback to execute after a transaction 4071 is complete, regardless of whether it succeeded or failed. 4072 4073 @property {Function} [options.onFailure] Callback to execute after a 4074 transaction fails, times out, or is aborted. 4075 4076 @property {Function} [options.onProgress] Callback to execute after each 4077 individual request in a transaction either succeeds or fails. 4078 4079 @property {Function} [options.onSuccess] Callback to execute after a 4080 transaction completes successfully with no errors. Note that in browsers 4081 that don't support the `error` event on CSS `<link>` nodes, a failed CSS 4082 request may still be reported as a success because in these browsers 4083 it can be difficult or impossible to distinguish between success and 4084 failure for CSS resources. 4085 4086 @property {Function} [options.onTimeout] Callback to execute after a 4087 transaction times out. 4088 4089 @property {Number} [options.pollInterval=50] Polling interval (in 4090 milliseconds) for detecting CSS load completion in browsers that don't 4091 support the `load` event on `<link>` nodes. This isn't used for 4092 JavaScript. 4093 4094 @property {Number} [options.purgethreshold=20] Number of nodes to insert 4095 before triggering an automatic purge when `autopurge` is `true`. 4096 4097 @property {Number} [options.timeout] Number of milliseconds to wait before 4098 aborting a transaction. When a timeout occurs, the `onTimeout` callback 4099 is called, followed by `onFailure` and finally `onEnd`. By default, 4100 there is no timeout. 4101 4102 @property {String} [options.type] Resource type ("css" or "js"). This option 4103 is set automatically by the `css()` and `js()` functions and will be 4104 ignored there, but may be useful when using the `load()` function. If 4105 not specified, the type will be inferred from the URL, defaulting to 4106 "js" if the URL doesn't contain a recognizable file extension. 4107 **/ 4108 options: { 4109 attributes: { 4110 charset: 'utf-8' 4111 }, 4112 4113 purgethreshold: 20 4114 }, 4115 4116 // -- Protected Properties ------------------------------------------------- 4117 4118 /** 4119 Regex that matches a CSS URL. Used to guess the file type when it's not 4120 specified. 4121 4122 @property REGEX_CSS 4123 @type RegExp 4124 @final 4125 @protected 4126 @static 4127 @since 3.5.0 4128 **/ 4129 REGEX_CSS: /\.css(?:[?;].*)?$/i, 4130 4131 /** 4132 Regex that matches a JS URL. Used to guess the file type when it's not 4133 specified. 4134 4135 @property REGEX_JS 4136 @type RegExp 4137 @final 4138 @protected 4139 @static 4140 @since 3.5.0 4141 **/ 4142 REGEX_JS : /\.js(?:[?;].*)?$/i, 4143 4144 /** 4145 Contains information about the current environment, such as what script and 4146 link injection features it supports. 4147 4148 This object is created and populated the first time the `_getEnv()` method 4149 is called. 4150 4151 @property _env 4152 @type Object 4153 @protected 4154 @static 4155 @since 3.5.0 4156 **/ 4157 4158 /** 4159 Mapping of document _yuid strings to <head> or <base> node references so we 4160 don't have to look the node up each time we want to insert a request node. 4161 4162 @property _insertCache 4163 @type Object 4164 @protected 4165 @static 4166 @since 3.5.0 4167 **/ 4168 _insertCache: {}, 4169 4170 /** 4171 Information about the currently pending transaction, if any. 4172 4173 This is actually an object with two properties: `callback`, containing the 4174 optional callback passed to `css()`, `load()`, or `js()`; and `transaction`, 4175 containing the actual transaction instance. 4176 4177 @property _pending 4178 @type Object 4179 @protected 4180 @static 4181 @since 3.5.0 4182 **/ 4183 _pending: null, 4184 4185 /** 4186 HTML nodes eligible to be purged next time autopurge is triggered. 4187 4188 @property _purgeNodes 4189 @type HTMLElement[] 4190 @protected 4191 @static 4192 @since 3.5.0 4193 **/ 4194 _purgeNodes: [], 4195 4196 /** 4197 Queued transactions and associated callbacks. 4198 4199 @property _queue 4200 @type Object[] 4201 @protected 4202 @static 4203 @since 3.5.0 4204 **/ 4205 _queue: [], 4206 4207 // -- Public Methods ------------------------------------------------------- 4208 4209 /** 4210 Aborts the specified transaction. 4211 4212 This will cause the transaction's `onFailure` callback to be called and 4213 will prevent any new script and link nodes from being added to the document, 4214 but any resources that have already been requested will continue loading 4215 (there's no safe way to prevent this, unfortunately). 4216 4217 *Note:* This method is deprecated as of 3.5.0, and will be removed in a 4218 future version of YUI. Use the transaction-level `abort()` method instead. 4219 4220 @method abort 4221 @param {Get.Transaction} transaction Transaction to abort. 4222 @deprecated Use the `abort()` method on the transaction instead. 4223 @static 4224 **/ 4225 abort: function (transaction) { 4226 var i, id, item, len, pending; 4227 4228 4229 if (!transaction.abort) { 4230 id = transaction; 4231 pending = this._pending; 4232 transaction = null; 4233 4234 if (pending && pending.transaction.id === id) { 4235 transaction = pending.transaction; 4236 this._pending = null; 4237 } else { 4238 for (i = 0, len = this._queue.length; i < len; ++i) { 4239 item = this._queue[i].transaction; 4240 4241 if (item.id === id) { 4242 transaction = item; 4243 this._queue.splice(i, 1); 4244 break; 4245 } 4246 } 4247 } 4248 } 4249 4250 transaction && transaction.abort(); 4251 }, 4252 4253 /** 4254 Loads one or more CSS files. 4255 4256 The _urls_ parameter may be provided as a URL string, a request object, 4257 or an array of URL strings and/or request objects. 4258 4259 A request object is just an object that contains a `url` property and zero 4260 or more options that should apply specifically to that request. 4261 Request-specific options take priority over transaction-level options and 4262 default options. 4263 4264 URLs may be relative or absolute, and do not have to have the same origin 4265 as the current page. 4266 4267 The `options` parameter may be omitted completely and a callback passed in 4268 its place, if desired. 4269 4270 @example 4271 4272 // Load a single CSS file and log a message on completion. 4273 Y.Get.css('foo.css', function (err) { 4274 if (err) { 4275 } else { 4276 } 4277 }); 4278 4279 // Load multiple CSS files and log a message when all have finished 4280 // loading. 4281 var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css']; 4282 4283 Y.Get.css(urls, function (err) { 4284 if (err) { 4285 } else { 4286 } 4287 }); 4288 4289 // Specify transaction-level options, which will apply to all requests 4290 // within the transaction. 4291 Y.Get.css(urls, { 4292 attributes: {'class': 'my-css'}, 4293 timeout : 5000 4294 }); 4295 4296 // Specify per-request options, which override transaction-level and 4297 // default options. 4298 Y.Get.css([ 4299 {url: 'foo.css', attributes: {id: 'foo'}}, 4300 {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}} 4301 ]); 4302 4303 @method css 4304 @param {String|Object|Array} urls URL string, request object, or array 4305 of URLs and/or request objects to load. 4306 @param {Object} [options] Options for this transaction. See the 4307 `Y.Get.options` property for a complete list of available options. 4308 @param {Function} [callback] Callback function to be called on completion. 4309 This is a general callback and will be called before any more granular 4310 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4311 object. 4312 4313 @param {Array|null} callback.err Array of errors that occurred during 4314 the transaction, or `null` on success. 4315 @param {Get.Transaction} callback.transaction Transaction object. 4316 4317 @return {Get.Transaction} Transaction object. 4318 @static 4319 **/ 4320 css: function (urls, options, callback) { 4321 return this._load('css', urls, options, callback); 4322 }, 4323 4324 /** 4325 Loads one or more JavaScript resources. 4326 4327 The _urls_ parameter may be provided as a URL string, a request object, 4328 or an array of URL strings and/or request objects. 4329 4330 A request object is just an object that contains a `url` property and zero 4331 or more options that should apply specifically to that request. 4332 Request-specific options take priority over transaction-level options and 4333 default options. 4334 4335 URLs may be relative or absolute, and do not have to have the same origin 4336 as the current page. 4337 4338 The `options` parameter may be omitted completely and a callback passed in 4339 its place, if desired. 4340 4341 Scripts will be executed in the order they're specified unless the `async` 4342 option is `true`, in which case they'll be loaded in parallel and executed 4343 in whatever order they finish loading. 4344 4345 @example 4346 4347 // Load a single JS file and log a message on completion. 4348 Y.Get.js('foo.js', function (err) { 4349 if (err) { 4350 } else { 4351 } 4352 }); 4353 4354 // Load multiple JS files, execute them in order, and log a message when 4355 // all have finished loading. 4356 var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js']; 4357 4358 Y.Get.js(urls, function (err) { 4359 if (err) { 4360 } else { 4361 } 4362 }); 4363 4364 // Specify transaction-level options, which will apply to all requests 4365 // within the transaction. 4366 Y.Get.js(urls, { 4367 attributes: {'class': 'my-js'}, 4368 timeout : 5000 4369 }); 4370 4371 // Specify per-request options, which override transaction-level and 4372 // default options. 4373 Y.Get.js([ 4374 {url: 'foo.js', attributes: {id: 'foo'}}, 4375 {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}} 4376 ]); 4377 4378 @method js 4379 @param {String|Object|Array} urls URL string, request object, or array 4380 of URLs and/or request objects to load. 4381 @param {Object} [options] Options for this transaction. See the 4382 `Y.Get.options` property for a complete list of available options. 4383 @param {Function} [callback] Callback function to be called on completion. 4384 This is a general callback and will be called before any more granular 4385 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4386 object. 4387 4388 @param {Array|null} callback.err Array of errors that occurred during 4389 the transaction, or `null` on success. 4390 @param {Get.Transaction} callback.transaction Transaction object. 4391 4392 @return {Get.Transaction} Transaction object. 4393 @since 3.5.0 4394 @static 4395 **/ 4396 js: function (urls, options, callback) { 4397 return this._load('js', urls, options, callback); 4398 }, 4399 4400 /** 4401 Loads one or more CSS and/or JavaScript resources in the same transaction. 4402 4403 Use this method when you want to load both CSS and JavaScript in a single 4404 transaction and be notified when all requested URLs have finished loading, 4405 regardless of type. 4406 4407 Behavior and options are the same as for the `css()` and `js()` methods. If 4408 a resource type isn't specified in per-request options or transaction-level 4409 options, Get will guess the file type based on the URL's extension (`.css` 4410 or `.js`, with or without a following query string). If the file type can't 4411 be guessed from the URL, a warning will be logged and Get will assume the 4412 URL is a JavaScript resource. 4413 4414 @example 4415 4416 // Load both CSS and JS files in a single transaction, and log a message 4417 // when all files have finished loading. 4418 Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) { 4419 if (err) { 4420 } else { 4421 } 4422 }); 4423 4424 @method load 4425 @param {String|Object|Array} urls URL string, request object, or array 4426 of URLs and/or request objects to load. 4427 @param {Object} [options] Options for this transaction. See the 4428 `Y.Get.options` property for a complete list of available options. 4429 @param {Function} [callback] Callback function to be called on completion. 4430 This is a general callback and will be called before any more granular 4431 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4432 object. 4433 4434 @param {Array|null} err Array of errors that occurred during the 4435 transaction, or `null` on success. 4436 @param {Get.Transaction} Transaction object. 4437 4438 @return {Get.Transaction} Transaction object. 4439 @since 3.5.0 4440 @static 4441 **/ 4442 load: function (urls, options, callback) { 4443 return this._load(null, urls, options, callback); 4444 }, 4445 4446 // -- Protected Methods ---------------------------------------------------- 4447 4448 /** 4449 Triggers an automatic purge if the purge threshold has been reached. 4450 4451 @method _autoPurge 4452 @param {Number} threshold Purge threshold to use, in milliseconds. 4453 @protected 4454 @since 3.5.0 4455 @static 4456 **/ 4457 _autoPurge: function (threshold) { 4458 if (threshold && this._purgeNodes.length >= threshold) { 4459 this._purge(this._purgeNodes); 4460 } 4461 }, 4462 4463 /** 4464 Populates the `_env` property with information about the current 4465 environment. 4466 4467 @method _getEnv 4468 @return {Object} Environment information. 4469 @protected 4470 @since 3.5.0 4471 @static 4472 **/ 4473 _getEnv: function () { 4474 var doc = Y.config.doc, 4475 ua = Y.UA; 4476 4477 // Note: some of these checks require browser sniffs since it's not 4478 // feasible to load test files on every pageview just to perform a 4479 // feature test. I'm sorry if this makes you sad. 4480 return (this._env = { 4481 4482 // True if this is a browser that supports disabling async mode on 4483 // dynamically created script nodes. See 4484 // https://developer.mozilla.org/En/HTML/Element/Script#Attributes 4485 4486 // IE10 doesn't return true for the MDN feature test, so setting it explicitly, 4487 // because it is async by default, and allows you to disable async by setting it to false 4488 async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10), 4489 4490 // True if this browser fires an event when a dynamically injected 4491 // link node fails to load. This is currently true for Firefox 9+ 4492 // and WebKit 535.24+ 4493 cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0, 4494 4495 // True if this browser fires an event when a dynamically injected 4496 // link node finishes loading. This is currently true for IE, Opera, 4497 // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the 4498 // DOM 0 "onload" event, but not "load". All versions of IE fire 4499 // "onload". 4500 // davglass: Seems that Chrome on Android needs this to be false. 4501 cssLoad: ( 4502 (!ua.gecko && !ua.webkit) || ua.gecko >= 9 || 4503 ua.compareVersions(ua.webkit, 535.24) >= 0 4504 ) && !(ua.chrome && ua.chrome <= 18), 4505 4506 // True if this browser preserves script execution order while 4507 // loading scripts in parallel as long as the script node's `async` 4508 // attribute is set to false to explicitly disable async execution. 4509 preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10)) 4510 }); 4511 }, 4512 4513 _getTransaction: function (urls, options) { 4514 var requests = [], 4515 i, len, req, url; 4516 4517 if (!Lang.isArray(urls)) { 4518 urls = [urls]; 4519 } 4520 4521 options = Y.merge(this.options, options); 4522 4523 // Clone the attributes object so we don't end up modifying it by ref. 4524 options.attributes = Y.merge(this.options.attributes, 4525 options.attributes); 4526 4527 for (i = 0, len = urls.length; i < len; ++i) { 4528 url = urls[i]; 4529 req = {attributes: {}}; 4530 4531 // If `url` is a string, we create a URL object for it, then mix in 4532 // global options and request-specific options. If it's an object 4533 // with a "url" property, we assume it's a request object containing 4534 // URL-specific options. 4535 if (typeof url === 'string') { 4536 req.url = url; 4537 } else if (url.url) { 4538 // URL-specific options override both global defaults and 4539 // request-specific options. 4540 Y.mix(req, url, false, null, 0, true); 4541 url = url.url; // Make url a string so we can use it later. 4542 } else { 4543 continue; 4544 } 4545 4546 Y.mix(req, options, false, null, 0, true); 4547 4548 // If we didn't get an explicit type for this URL either in the 4549 // request options or the URL-specific options, try to determine 4550 // one from the file extension. 4551 if (!req.type) { 4552 if (this.REGEX_CSS.test(url)) { 4553 req.type = 'css'; 4554 } else { 4555 if (!this.REGEX_JS.test(url)) { 4556 } 4557 4558 req.type = 'js'; 4559 } 4560 } 4561 4562 // Mix in type-specific default options, but don't overwrite any 4563 // options that have already been set. 4564 Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions, 4565 false, null, 0, true); 4566 4567 // Give the node an id attribute if it doesn't already have one. 4568 req.attributes.id || (req.attributes.id = Y.guid()); 4569 4570 // Backcompat for <3.5.0 behavior. 4571 if (req.win) { 4572 req.doc = req.win.document; 4573 } else { 4574 req.win = req.doc.defaultView || req.doc.parentWindow; 4575 } 4576 4577 if (req.charset) { 4578 req.attributes.charset = req.charset; 4579 } 4580 4581 requests.push(req); 4582 } 4583 4584 return new Transaction(requests, options); 4585 }, 4586 4587 _load: function (type, urls, options, callback) { 4588 var transaction; 4589 4590 // Allow callback as third param. 4591 if (typeof options === 'function') { 4592 callback = options; 4593 options = {}; 4594 } 4595 4596 options || (options = {}); 4597 options.type = type; 4598 4599 options._onFinish = Get._onTransactionFinish; 4600 4601 if (!this._env) { 4602 this._getEnv(); 4603 } 4604 4605 transaction = this._getTransaction(urls, options); 4606 4607 this._queue.push({ 4608 callback : callback, 4609 transaction: transaction 4610 }); 4611 4612 this._next(); 4613 4614 return transaction; 4615 }, 4616 4617 _onTransactionFinish : function() { 4618 Get._pending = null; 4619 Get._next(); 4620 }, 4621 4622 _next: function () { 4623 var item; 4624 4625 if (this._pending) { 4626 return; 4627 } 4628 4629 item = this._queue.shift(); 4630 4631 if (item) { 4632 this._pending = item; 4633 item.transaction.execute(item.callback); 4634 } 4635 }, 4636 4637 _purge: function (nodes) { 4638 var purgeNodes = this._purgeNodes, 4639 isTransaction = nodes !== purgeNodes, 4640 index, node; 4641 4642 while (node = nodes.pop()) { // assignment 4643 // Don't purge nodes that haven't finished loading (or errored out), 4644 // since this can hang the transaction. 4645 if (!node._yuiget_finished) { 4646 continue; 4647 } 4648 4649 node.parentNode && node.parentNode.removeChild(node); 4650 4651 // If this is a transaction-level purge and this node also exists in 4652 // the Get-level _purgeNodes array, we need to remove it from 4653 // _purgeNodes to avoid creating a memory leak. The indexOf lookup 4654 // sucks, but until we get WeakMaps, this is the least troublesome 4655 // way to do this (we can't just hold onto node ids because they may 4656 // not be in the same document). 4657 if (isTransaction) { 4658 index = Y.Array.indexOf(purgeNodes, node); 4659 4660 if (index > -1) { 4661 purgeNodes.splice(index, 1); 4662 } 4663 } 4664 } 4665 } 4666 }; 4667 4668 /** 4669 Alias for `js()`. 4670 4671 @method script 4672 @static 4673 **/ 4674 Get.script = Get.js; 4675 4676 /** 4677 Represents a Get transaction, which may contain requests for one or more JS or 4678 CSS files. 4679 4680 This class should not be instantiated manually. Instances will be created and 4681 returned as needed by Y.Get's `css()`, `js()`, and `load()` methods. 4682 4683 @class Get.Transaction 4684 @constructor 4685 @since 3.5.0 4686 **/ 4687 Get.Transaction = Transaction = function (requests, options) { 4688 var self = this; 4689 4690 self.id = Transaction._lastId += 1; 4691 self.data = options.data; 4692 self.errors = []; 4693 self.nodes = []; 4694 self.options = options; 4695 self.requests = requests; 4696 4697 self._callbacks = []; // callbacks to call after execution finishes 4698 self._queue = []; 4699 self._reqsWaiting = 0; 4700 4701 // Deprecated pre-3.5.0 properties. 4702 self.tId = self.id; // Use `id` instead. 4703 self.win = options.win || Y.config.win; 4704 }; 4705 4706 /** 4707 Arbitrary data object associated with this transaction. 4708 4709 This object comes from the options passed to `Get.css()`, `Get.js()`, or 4710 `Get.load()`, and will be `undefined` if no data object was specified. 4711 4712 @property {Object} data 4713 **/ 4714 4715 /** 4716 Array of errors that have occurred during this transaction, if any. Each error 4717 object has the following properties: 4718 `errors.error`: Error message. 4719 `errors.request`: Request object related to the error. 4720 4721 @since 3.5.0 4722 @property {Object[]} errors 4723 **/ 4724 4725 /** 4726 Numeric id for this transaction, unique among all transactions within the same 4727 YUI sandbox in the current pageview. 4728 4729 @property {Number} id 4730 @since 3.5.0 4731 **/ 4732 4733 /** 4734 HTMLElement nodes (native ones, not YUI Node instances) that have been inserted 4735 during the current transaction. 4736 4737 @property {HTMLElement[]} nodes 4738 **/ 4739 4740 /** 4741 Options associated with this transaction. 4742 4743 See `Get.options` for the full list of available options. 4744 4745 @property {Object} options 4746 @since 3.5.0 4747 **/ 4748 4749 /** 4750 Request objects contained in this transaction. Each request object represents 4751 one CSS or JS URL that will be (or has been) requested and loaded into the page. 4752 4753 @property {Object} requests 4754 @since 3.5.0 4755 **/ 4756 4757 /** 4758 Id of the most recent transaction. 4759 4760 @property _lastId 4761 @type Number 4762 @protected 4763 @static 4764 **/ 4765 Transaction._lastId = 0; 4766 4767 Transaction.prototype = { 4768 // -- Public Properties ---------------------------------------------------- 4769 4770 /** 4771 Current state of this transaction. One of "new", "executing", or "done". 4772 4773 @property _state 4774 @type String 4775 @protected 4776 **/ 4777 _state: 'new', // "new", "executing", or "done" 4778 4779 // -- Public Methods ------------------------------------------------------- 4780 4781 /** 4782 Aborts this transaction. 4783 4784 This will cause the transaction's `onFailure` callback to be called and 4785 will prevent any new script and link nodes from being added to the document, 4786 but any resources that have already been requested will continue loading 4787 (there's no safe way to prevent this, unfortunately). 4788 4789 @method abort 4790 @param {String} [msg="Aborted."] Optional message to use in the `errors` 4791 array describing why the transaction was aborted. 4792 **/ 4793 abort: function (msg) { 4794 this._pending = null; 4795 this._pendingCSS = null; 4796 this._pollTimer = clearTimeout(this._pollTimer); 4797 this._queue = []; 4798 this._reqsWaiting = 0; 4799 4800 this.errors.push({error: msg || 'Aborted'}); 4801 this._finish(); 4802 }, 4803 4804 /** 4805 Begins execting the transaction. 4806 4807 There's usually no reason to call this manually, since Get will call it 4808 automatically when other pending transactions have finished. If you really 4809 want to execute your transaction before Get does, you can, but be aware that 4810 this transaction's scripts may end up executing before the scripts in other 4811 pending transactions. 4812 4813 If the transaction is already executing, the specified callback (if any) 4814 will be queued and called after execution finishes. If the transaction has 4815 already finished, the callback will be called immediately (the transaction 4816 will not be executed again). 4817 4818 @method execute 4819 @param {Function} callback Callback function to execute after all requests 4820 in the transaction are complete, or after the transaction is aborted. 4821 **/ 4822 execute: function (callback) { 4823 var self = this, 4824 requests = self.requests, 4825 state = self._state, 4826 i, len, queue, req; 4827 4828 if (state === 'done') { 4829 callback && callback(self.errors.length ? self.errors : null, self); 4830 return; 4831 } else { 4832 callback && self._callbacks.push(callback); 4833 4834 if (state === 'executing') { 4835 return; 4836 } 4837 } 4838 4839 self._state = 'executing'; 4840 self._queue = queue = []; 4841 4842 if (self.options.timeout) { 4843 self._timeout = setTimeout(function () { 4844 self.abort('Timeout'); 4845 }, self.options.timeout); 4846 } 4847 4848 self._reqsWaiting = requests.length; 4849 4850 for (i = 0, len = requests.length; i < len; ++i) { 4851 req = requests[i]; 4852 4853 if (req.async || req.type === 'css') { 4854 // No need to queue CSS or fully async JS. 4855 self._insert(req); 4856 } else { 4857 queue.push(req); 4858 } 4859 } 4860 4861 self._next(); 4862 }, 4863 4864 /** 4865 Manually purges any `<script>` or `<link>` nodes this transaction has 4866 created. 4867 4868 Be careful when purging a transaction that contains CSS requests, since 4869 removing `<link>` nodes will also remove any styles they applied. 4870 4871 @method purge 4872 **/ 4873 purge: function () { 4874 Get._purge(this.nodes); 4875 }, 4876 4877 // -- Protected Methods ---------------------------------------------------- 4878 _createNode: function (name, attrs, doc) { 4879 var node = doc.createElement(name), 4880 attr, testEl; 4881 4882 if (!CUSTOM_ATTRS) { 4883 // IE6 and IE7 expect property names rather than attribute names for 4884 // certain attributes. Rather than sniffing, we do a quick feature 4885 // test the first time _createNode() runs to determine whether we 4886 // need to provide a workaround. 4887 testEl = doc.createElement('div'); 4888 testEl.setAttribute('class', 'a'); 4889 4890 CUSTOM_ATTRS = testEl.className === 'a' ? {} : { 4891 'for' : 'htmlFor', 4892 'class': 'className' 4893 }; 4894 } 4895 4896 for (attr in attrs) { 4897 if (attrs.hasOwnProperty(attr)) { 4898 node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]); 4899 } 4900 } 4901 4902 return node; 4903 }, 4904 4905 _finish: function () { 4906 var errors = this.errors.length ? this.errors : null, 4907 options = this.options, 4908 thisObj = options.context || this, 4909 data, i, len; 4910 4911 if (this._state === 'done') { 4912 return; 4913 } 4914 4915 this._state = 'done'; 4916 4917 for (i = 0, len = this._callbacks.length; i < len; ++i) { 4918 this._callbacks[i].call(thisObj, errors, this); 4919 } 4920 4921 data = this._getEventData(); 4922 4923 if (errors) { 4924 if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') { 4925 options.onTimeout.call(thisObj, data); 4926 } 4927 4928 if (options.onFailure) { 4929 options.onFailure.call(thisObj, data); 4930 } 4931 } else if (options.onSuccess) { 4932 options.onSuccess.call(thisObj, data); 4933 } 4934 4935 if (options.onEnd) { 4936 options.onEnd.call(thisObj, data); 4937 } 4938 4939 if (options._onFinish) { 4940 options._onFinish(); 4941 } 4942 }, 4943 4944 _getEventData: function (req) { 4945 if (req) { 4946 // This merge is necessary for backcompat. I hate it. 4947 return Y.merge(this, { 4948 abort : this.abort, // have to copy these because the prototype isn't preserved 4949 purge : this.purge, 4950 request: req, 4951 url : req.url, 4952 win : req.win 4953 }); 4954 } else { 4955 return this; 4956 } 4957 }, 4958 4959 _getInsertBefore: function (req) { 4960 var doc = req.doc, 4961 el = req.insertBefore, 4962 cache, docStamp; 4963 4964 if (el) { 4965 return typeof el === 'string' ? doc.getElementById(el) : el; 4966 } 4967 4968 cache = Get._insertCache; 4969 docStamp = Y.stamp(doc); 4970 4971 if ((el = cache[docStamp])) { // assignment 4972 return el; 4973 } 4974 4975 // Inserting before a <base> tag apparently works around an IE bug 4976 // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what 4977 // bug that is, exactly. Better safe than sorry? 4978 if ((el = doc.getElementsByTagName('base')[0])) { // assignment 4979 return (cache[docStamp] = el); 4980 } 4981 4982 // Look for a <head> element. 4983 el = doc.head || doc.getElementsByTagName('head')[0]; 4984 4985 if (el) { 4986 // Create a marker node at the end of <head> to use as an insertion 4987 // point. Inserting before this node will ensure that all our CSS 4988 // gets inserted in the correct order, to maintain style precedence. 4989 el.appendChild(doc.createTextNode('')); 4990 return (cache[docStamp] = el.lastChild); 4991 } 4992 4993 // If all else fails, just insert before the first script node on the 4994 // page, which is virtually guaranteed to exist. 4995 return (cache[docStamp] = doc.getElementsByTagName('script')[0]); 4996 }, 4997 4998 _insert: function (req) { 4999 var env = Get._env, 5000 insertBefore = this._getInsertBefore(req), 5001 isScript = req.type === 'js', 5002 node = req.node, 5003 self = this, 5004 ua = Y.UA, 5005 cssTimeout, nodeType; 5006 5007 if (!node) { 5008 if (isScript) { 5009 nodeType = 'script'; 5010 } else if (!env.cssLoad && ua.gecko) { 5011 nodeType = 'style'; 5012 } else { 5013 nodeType = 'link'; 5014 } 5015 5016 node = req.node = this._createNode(nodeType, req.attributes, 5017 req.doc); 5018 } 5019 5020 function onError() { 5021 self._progress('Failed to load ' + req.url, req); 5022 } 5023 5024 function onLoad() { 5025 if (cssTimeout) { 5026 clearTimeout(cssTimeout); 5027 } 5028 5029 self._progress(null, req); 5030 } 5031 5032 // Deal with script asynchronicity. 5033 if (isScript) { 5034 node.setAttribute('src', req.url); 5035 5036 if (req.async) { 5037 // Explicitly indicate that we want the browser to execute this 5038 // script asynchronously. This is necessary for older browsers 5039 // like Firefox <4. 5040 node.async = true; 5041 } else { 5042 if (env.async) { 5043 // This browser treats injected scripts as async by default 5044 // (standard HTML5 behavior) but asynchronous loading isn't 5045 // desired, so tell the browser not to mark this script as 5046 // async. 5047 node.async = false; 5048 } 5049 5050 // If this browser doesn't preserve script execution order based 5051 // on insertion order, we'll need to avoid inserting other 5052 // scripts until this one finishes loading. 5053 if (!env.preservesScriptOrder) { 5054 this._pending = req; 5055 } 5056 } 5057 } else { 5058 if (!env.cssLoad && ua.gecko) { 5059 // In Firefox <9, we can import the requested URL into a <style> 5060 // node and poll for the existence of node.sheet.cssRules. This 5061 // gives us a reliable way to determine CSS load completion that 5062 // also works for cross-domain stylesheets. 5063 // 5064 // Props to Zach Leatherman for calling my attention to this 5065 // technique. 5066 node.innerHTML = (req.attributes.charset ? 5067 '@charset "' + req.attributes.charset + '";' : '') + 5068 '@import "' + req.url + '";'; 5069 } else { 5070 node.setAttribute('href', req.url); 5071 } 5072 } 5073 5074 // Inject the node. 5075 if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) { 5076 // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode. 5077 node.onreadystatechange = function () { 5078 if (/loaded|complete/.test(node.readyState)) { 5079 node.onreadystatechange = null; 5080 onLoad(); 5081 } 5082 }; 5083 } else if (!isScript && !env.cssLoad) { 5084 // CSS on Firefox <9 or WebKit. 5085 this._poll(req); 5086 } else { 5087 // Script or CSS on everything else. Using DOM 0 events because that 5088 // evens the playing field with older IEs. 5089 5090 if (ua.ie >= 10) { 5091 5092 // We currently need to introduce a timeout for IE10, since it 5093 // calls onerror/onload synchronously for 304s - messing up existing 5094 // program flow. 5095 5096 // Remove this block if the following bug gets fixed by GA 5097 /*jshint maxlen: 1500 */ 5098 // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload 5099 node.onerror = function() { setTimeout(onError, 0); }; 5100 node.onload = function() { setTimeout(onLoad, 0); }; 5101 } else { 5102 node.onerror = onError; 5103 node.onload = onLoad; 5104 } 5105 5106 // If this browser doesn't fire an event when CSS fails to load, 5107 // fail after a timeout to avoid blocking the transaction queue. 5108 if (!env.cssFail && !isScript) { 5109 cssTimeout = setTimeout(onError, req.timeout || 3000); 5110 } 5111 } 5112 5113 this.nodes.push(node); 5114 insertBefore.parentNode.insertBefore(node, insertBefore); 5115 }, 5116 5117 _next: function () { 5118 if (this._pending) { 5119 return; 5120 } 5121 5122 // If there are requests in the queue, insert the next queued request. 5123 // Otherwise, if we're waiting on already-inserted requests to finish, 5124 // wait longer. If there are no queued requests and we're not waiting 5125 // for anything to load, then we're done! 5126 if (this._queue.length) { 5127 this._insert(this._queue.shift()); 5128 } else if (!this._reqsWaiting) { 5129 this._finish(); 5130 } 5131 }, 5132 5133 _poll: function (newReq) { 5134 var self = this, 5135 pendingCSS = self._pendingCSS, 5136 isWebKit = Y.UA.webkit, 5137 i, hasRules, j, nodeHref, req, sheets; 5138 5139 if (newReq) { 5140 pendingCSS || (pendingCSS = self._pendingCSS = []); 5141 pendingCSS.push(newReq); 5142 5143 if (self._pollTimer) { 5144 // A poll timeout is already pending, so no need to create a 5145 // new one. 5146 return; 5147 } 5148 } 5149 5150 self._pollTimer = null; 5151 5152 // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s 5153 // will still be treated as a success. There's no good workaround for 5154 // this. 5155 5156 for (i = 0; i < pendingCSS.length; ++i) { 5157 req = pendingCSS[i]; 5158 5159 if (isWebKit) { 5160 // Look for a stylesheet matching the pending URL. 5161 sheets = req.doc.styleSheets; 5162 j = sheets.length; 5163 nodeHref = req.node.href; 5164 5165 while (--j >= 0) { 5166 if (sheets[j].href === nodeHref) { 5167 pendingCSS.splice(i, 1); 5168 i -= 1; 5169 self._progress(null, req); 5170 break; 5171 } 5172 } 5173 } else { 5174 // Many thanks to Zach Leatherman for calling my attention to 5175 // the @import-based cross-domain technique used here, and to 5176 // Oleg Slobodskoi for an earlier same-domain implementation. 5177 // 5178 // See Zach's blog for more details: 5179 // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/ 5180 try { 5181 // We don't really need to store this value since we never 5182 // use it again, but if we don't store it, Closure Compiler 5183 // assumes the code is useless and removes it. 5184 hasRules = !!req.node.sheet.cssRules; 5185 5186 // If we get here, the stylesheet has loaded. 5187 pendingCSS.splice(i, 1); 5188 i -= 1; 5189 self._progress(null, req); 5190 } catch (ex) { 5191 // An exception means the stylesheet is still loading. 5192 } 5193 } 5194 } 5195 5196 if (pendingCSS.length) { 5197 self._pollTimer = setTimeout(function () { 5198 self._poll.call(self); 5199 }, self.options.pollInterval); 5200 } 5201 }, 5202 5203 _progress: function (err, req) { 5204 var options = this.options; 5205 5206 if (err) { 5207 req.error = err; 5208 5209 this.errors.push({ 5210 error : err, 5211 request: req 5212 }); 5213 5214 } 5215 5216 req.node._yuiget_finished = req.finished = true; 5217 5218 if (options.onProgress) { 5219 options.onProgress.call(options.context || this, 5220 this._getEventData(req)); 5221 } 5222 5223 if (req.autopurge) { 5224 // Pre-3.5.0 Get always excludes the most recent node from an 5225 // autopurge. I find this odd, but I'm keeping that behavior for 5226 // the sake of backcompat. 5227 Get._autoPurge(this.options.purgethreshold); 5228 Get._purgeNodes.push(req.node); 5229 } 5230 5231 if (this._pending === req) { 5232 this._pending = null; 5233 } 5234 5235 this._reqsWaiting -= 1; 5236 5237 this._next(); 5238 } 5239 }; 5240 5241 5242 }, '3.17.2', {"requires": ["yui-base"]}); 5243 YUI.add('features', function (Y, NAME) { 5244 5245 var feature_tests = {}; 5246 5247 /** 5248 Contains the core of YUI's feature test architecture. 5249 @module features 5250 */ 5251 5252 /** 5253 * Feature detection 5254 * @class Features 5255 * @static 5256 */ 5257 5258 Y.mix(Y.namespace('Features'), { 5259 5260 /** 5261 * Object hash of all registered feature tests 5262 * @property tests 5263 * @type Object 5264 */ 5265 tests: feature_tests, 5266 5267 /** 5268 * Add a test to the system 5269 * 5270 * ``` 5271 * Y.Features.add("load", "1", {}); 5272 * ``` 5273 * 5274 * @method add 5275 * @param {String} cat The category, right now only 'load' is supported 5276 * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3 5277 * @param {Object} o Object containing test properties 5278 * @param {String} o.name The name of the test 5279 * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance 5280 * @param {String} o.trigger The module that triggers this test. 5281 */ 5282 add: function(cat, name, o) { 5283 feature_tests[cat] = feature_tests[cat] || {}; 5284 feature_tests[cat][name] = o; 5285 }, 5286 /** 5287 * Execute all tests of a given category and return the serialized results 5288 * 5289 * ``` 5290 * caps=1:1;2:1;3:0 5291 * ``` 5292 * @method all 5293 * @param {String} cat The category to execute 5294 * @param {Array} args The arguments to pass to the test function 5295 * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0 5296 */ 5297 all: function(cat, args) { 5298 var cat_o = feature_tests[cat], 5299 // results = {}; 5300 result = []; 5301 if (cat_o) { 5302 Y.Object.each(cat_o, function(v, k) { 5303 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0)); 5304 }); 5305 } 5306 5307 return (result.length) ? result.join(';') : ''; 5308 }, 5309 /** 5310 * Run a specific test and return a Boolean response. 5311 * 5312 * ``` 5313 * Y.Features.test("load", "1"); 5314 * ``` 5315 * 5316 * @method test 5317 * @param {String} cat The category of the test to run 5318 * @param {String} name The name of the test to run 5319 * @param {Array} args The arguments to pass to the test function 5320 * @return {Boolean} True or false if the test passed/failed. 5321 */ 5322 test: function(cat, name, args) { 5323 args = args || []; 5324 var result, ua, test, 5325 cat_o = feature_tests[cat], 5326 feature = cat_o && cat_o[name]; 5327 5328 if (!feature) { 5329 } else { 5330 5331 result = feature.result; 5332 5333 if (Y.Lang.isUndefined(result)) { 5334 5335 ua = feature.ua; 5336 if (ua) { 5337 result = (Y.UA[ua]); 5338 } 5339 5340 test = feature.test; 5341 if (test && ((!ua) || result)) { 5342 result = test.apply(Y, args); 5343 } 5344 5345 feature.result = result; 5346 } 5347 } 5348 5349 return result; 5350 } 5351 }); 5352 5353 // Y.Features.add("load", "1", {}); 5354 // Y.Features.test("load", "1"); 5355 // caps=1:1;2:0;3:1; 5356 5357 /* This file is auto-generated by (yogi.js loader --mix --yes) */ 5358 /*jshint maxlen:900, eqeqeq: false */ 5359 var add = Y.Features.add; 5360 // app-transitions-native 5361 add('load', '0', { 5362 "name": "app-transitions-native", 5363 "test": function (Y) { 5364 var doc = Y.config.doc, 5365 node = doc ? doc.documentElement : null; 5366 5367 if (node && node.style) { 5368 return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 5369 } 5370 5371 return false; 5372 }, 5373 "trigger": "app-transitions" 5374 }); 5375 // autocomplete-list-keys 5376 add('load', '1', { 5377 "name": "autocomplete-list-keys", 5378 "test": function (Y) { 5379 // Only add keyboard support to autocomplete-list if this doesn't appear to 5380 // be an iOS or Android-based mobile device. 5381 // 5382 // There's currently no feasible way to actually detect whether a device has 5383 // a hardware keyboard, so this sniff will have to do. It can easily be 5384 // overridden by manually loading the autocomplete-list-keys module. 5385 // 5386 // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari 5387 // doesn't fire the keyboard events used by AutoCompleteList, so there's 5388 // no point loading the -keys module even when a bluetooth keyboard may be 5389 // available. 5390 return !(Y.UA.ios || Y.UA.android); 5391 }, 5392 "trigger": "autocomplete-list" 5393 }); 5394 // dd-gestures 5395 add('load', '2', { 5396 "name": "dd-gestures", 5397 "trigger": "dd-drag", 5398 "ua": "touchEnabled" 5399 }); 5400 // dom-style-ie 5401 add('load', '3', { 5402 "name": "dom-style-ie", 5403 "test": function (Y) { 5404 5405 var testFeature = Y.Features.test, 5406 addFeature = Y.Features.add, 5407 WINDOW = Y.config.win, 5408 DOCUMENT = Y.config.doc, 5409 DOCUMENT_ELEMENT = 'documentElement', 5410 ret = false; 5411 5412 addFeature('style', 'computedStyle', { 5413 test: function() { 5414 return WINDOW && 'getComputedStyle' in WINDOW; 5415 } 5416 }); 5417 5418 addFeature('style', 'opacity', { 5419 test: function() { 5420 return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style; 5421 } 5422 }); 5423 5424 ret = (!testFeature('style', 'opacity') && 5425 !testFeature('style', 'computedStyle')); 5426 5427 return ret; 5428 }, 5429 "trigger": "dom-style" 5430 }); 5431 // editor-para-ie 5432 add('load', '4', { 5433 "name": "editor-para-ie", 5434 "trigger": "editor-para", 5435 "ua": "ie", 5436 "when": "instead" 5437 }); 5438 // event-base-ie 5439 add('load', '5', { 5440 "name": "event-base-ie", 5441 "test": function(Y) { 5442 var imp = Y.config.doc && Y.config.doc.implementation; 5443 return (imp && (!imp.hasFeature('Events', '2.0'))); 5444 }, 5445 "trigger": "node-base" 5446 }); 5447 // graphics-canvas 5448 add('load', '6', { 5449 "name": "graphics-canvas", 5450 "test": function(Y) { 5451 var DOCUMENT = Y.config.doc, 5452 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 5453 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5454 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5455 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 5456 }, 5457 "trigger": "graphics" 5458 }); 5459 // graphics-canvas-default 5460 add('load', '7', { 5461 "name": "graphics-canvas-default", 5462 "test": function(Y) { 5463 var DOCUMENT = Y.config.doc, 5464 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 5465 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5466 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5467 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 5468 }, 5469 "trigger": "graphics" 5470 }); 5471 // graphics-svg 5472 add('load', '8', { 5473 "name": "graphics-svg", 5474 "test": function(Y) { 5475 var DOCUMENT = Y.config.doc, 5476 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 5477 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5478 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5479 5480 return svg && (useSVG || !canvas); 5481 }, 5482 "trigger": "graphics" 5483 }); 5484 // graphics-svg-default 5485 add('load', '9', { 5486 "name": "graphics-svg-default", 5487 "test": function(Y) { 5488 var DOCUMENT = Y.config.doc, 5489 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 5490 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5491 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5492 5493 return svg && (useSVG || !canvas); 5494 }, 5495 "trigger": "graphics" 5496 }); 5497 // graphics-vml 5498 add('load', '10', { 5499 "name": "graphics-vml", 5500 "test": function(Y) { 5501 var DOCUMENT = Y.config.doc, 5502 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 5503 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 5504 }, 5505 "trigger": "graphics" 5506 }); 5507 // graphics-vml-default 5508 add('load', '11', { 5509 "name": "graphics-vml-default", 5510 "test": function(Y) { 5511 var DOCUMENT = Y.config.doc, 5512 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 5513 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 5514 }, 5515 "trigger": "graphics" 5516 }); 5517 // history-hash-ie 5518 add('load', '12', { 5519 "name": "history-hash-ie", 5520 "test": function (Y) { 5521 var docMode = Y.config.doc && Y.config.doc.documentMode; 5522 5523 return Y.UA.ie && (!('onhashchange' in Y.config.win) || 5524 !docMode || docMode < 8); 5525 }, 5526 "trigger": "history-hash" 5527 }); 5528 // io-nodejs 5529 add('load', '13', { 5530 "name": "io-nodejs", 5531 "trigger": "io-base", 5532 "ua": "nodejs" 5533 }); 5534 // json-parse-shim 5535 add('load', '14', { 5536 "name": "json-parse-shim", 5537 "test": function (Y) { 5538 var _JSON = Y.config.global.JSON, 5539 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 5540 nativeSupport = Y.config.useNativeJSONParse !== false && !!Native; 5541 5542 function workingNative( k, v ) { 5543 return k === "ok" ? true : v; 5544 } 5545 5546 // Double check basic functionality. This is mainly to catch early broken 5547 // implementations of the JSON API in Firefox 3.1 beta1 and beta2 5548 if ( nativeSupport ) { 5549 try { 5550 nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok; 5551 } 5552 catch ( e ) { 5553 nativeSupport = false; 5554 } 5555 } 5556 5557 return !nativeSupport; 5558 }, 5559 "trigger": "json-parse" 5560 }); 5561 // json-stringify-shim 5562 add('load', '15', { 5563 "name": "json-stringify-shim", 5564 "test": function (Y) { 5565 var _JSON = Y.config.global.JSON, 5566 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 5567 nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native; 5568 5569 // Double check basic native functionality. This is primarily to catch broken 5570 // early JSON API implementations in Firefox 3.1 beta1 and beta2. 5571 if ( nativeSupport ) { 5572 try { 5573 nativeSupport = ( '0' === Native.stringify(0) ); 5574 } catch ( e ) { 5575 nativeSupport = false; 5576 } 5577 } 5578 5579 5580 return !nativeSupport; 5581 }, 5582 "trigger": "json-stringify" 5583 }); 5584 // scrollview-base-ie 5585 add('load', '16', { 5586 "name": "scrollview-base-ie", 5587 "trigger": "scrollview-base", 5588 "ua": "ie" 5589 }); 5590 // selector-css2 5591 add('load', '17', { 5592 "name": "selector-css2", 5593 "test": function (Y) { 5594 var DOCUMENT = Y.config.doc, 5595 ret = DOCUMENT && !('querySelectorAll' in DOCUMENT); 5596 5597 return ret; 5598 }, 5599 "trigger": "selector" 5600 }); 5601 // transition-timer 5602 add('load', '18', { 5603 "name": "transition-timer", 5604 "test": function (Y) { 5605 var DOCUMENT = Y.config.doc, 5606 node = (DOCUMENT) ? DOCUMENT.documentElement: null, 5607 ret = true; 5608 5609 if (node && node.style) { 5610 ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 5611 } 5612 5613 return ret; 5614 }, 5615 "trigger": "transition" 5616 }); 5617 // widget-base-ie 5618 add('load', '19', { 5619 "name": "widget-base-ie", 5620 "trigger": "widget-base", 5621 "ua": "ie" 5622 }); 5623 // yql-jsonp 5624 add('load', '20', { 5625 "name": "yql-jsonp", 5626 "test": function (Y) { 5627 /* Only load the JSONP module when not in nodejs or winjs 5628 TODO Make the winjs module a CORS module 5629 */ 5630 return (!Y.UA.nodejs && !Y.UA.winjs); 5631 }, 5632 "trigger": "yql" 5633 }); 5634 // yql-nodejs 5635 add('load', '21', { 5636 "name": "yql-nodejs", 5637 "trigger": "yql", 5638 "ua": "nodejs" 5639 }); 5640 // yql-winjs 5641 add('load', '22', { 5642 "name": "yql-winjs", 5643 "trigger": "yql", 5644 "ua": "winjs" 5645 }); 5646 5647 }, '3.17.2', {"requires": ["yui-base"]}); 5648 YUI.add('intl-base', function (Y, NAME) { 5649 5650 /** 5651 * The Intl utility provides a central location for managing sets of 5652 * localized resources (strings and formatting patterns). 5653 * 5654 * @class Intl 5655 * @uses EventTarget 5656 * @static 5657 */ 5658 5659 var SPLIT_REGEX = /[, ]/; 5660 5661 Y.mix(Y.namespace('Intl'), { 5662 5663 /** 5664 * Returns the language among those available that 5665 * best matches the preferred language list, using the Lookup 5666 * algorithm of BCP 47. 5667 * If none of the available languages meets the user's preferences, 5668 * then "" is returned. 5669 * Extended language ranges are not supported. 5670 * 5671 * @method lookupBestLang 5672 * @param {String[] | String} preferredLanguages The list of preferred 5673 * languages in descending preference order, represented as BCP 47 5674 * language tags. A string array or a comma-separated list. 5675 * @param {String[]} availableLanguages The list of languages 5676 * that the application supports, represented as BCP 47 language 5677 * tags. 5678 * 5679 * @return {String} The available language that best matches the 5680 * preferred language list, or "". 5681 * @since 3.1.0 5682 */ 5683 lookupBestLang: function(preferredLanguages, availableLanguages) { 5684 5685 var i, language, result, index; 5686 5687 // check whether the list of available languages contains language; 5688 // if so return it 5689 function scan(language) { 5690 var i; 5691 for (i = 0; i < availableLanguages.length; i += 1) { 5692 if (language.toLowerCase() === 5693 availableLanguages[i].toLowerCase()) { 5694 return availableLanguages[i]; 5695 } 5696 } 5697 } 5698 5699 if (Y.Lang.isString(preferredLanguages)) { 5700 preferredLanguages = preferredLanguages.split(SPLIT_REGEX); 5701 } 5702 5703 for (i = 0; i < preferredLanguages.length; i += 1) { 5704 language = preferredLanguages[i]; 5705 if (!language || language === '*') { 5706 continue; 5707 } 5708 // check the fallback sequence for one language 5709 while (language.length > 0) { 5710 result = scan(language); 5711 if (result) { 5712 return result; 5713 } else { 5714 index = language.lastIndexOf('-'); 5715 if (index >= 0) { 5716 language = language.substring(0, index); 5717 // one-character subtags get cut along with the 5718 // following subtag 5719 if (index >= 2 && language.charAt(index - 2) === '-') { 5720 language = language.substring(0, index - 2); 5721 } 5722 } else { 5723 // nothing available for this language 5724 break; 5725 } 5726 } 5727 } 5728 } 5729 5730 return ''; 5731 } 5732 }); 5733 5734 5735 }, '3.17.2', {"requires": ["yui-base"]}); 5736 YUI.add('yui-log', function (Y, NAME) { 5737 5738 /** 5739 * Provides console log capability and exposes a custom event for 5740 * console implementations. This module is a `core` YUI module, 5741 * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>. 5742 * 5743 * @module yui 5744 * @submodule yui-log 5745 */ 5746 5747 var INSTANCE = Y, 5748 LOGEVENT = 'yui:log', 5749 UNDEFINED = 'undefined', 5750 LEVELS = { debug: 1, 5751 info: 2, 5752 warn: 4, 5753 error: 8 }; 5754 5755 /** 5756 * If the 'debug' config is true, a 'yui:log' event will be 5757 * dispatched, which the Console widget and anything else 5758 * can consume. If the 'useBrowserConsole' config is true, it will 5759 * write to the browser console if available. YUI-specific log 5760 * messages will only be present in the -debug versions of the 5761 * JS files. The build system is supposed to remove log statements 5762 * from the raw and minified versions of the files. 5763 * 5764 * @method log 5765 * @for YUI 5766 * @param {String} msg The message to log. 5767 * @param {String} cat The log category for the message. Default 5768 * categories are "info", "warn", "error", "debug". 5769 * Custom categories can be used as well. (opt). 5770 * @param {String} src The source of the the message (opt). 5771 * @param {boolean} silent If true, the log event won't fire. 5772 * @return {YUI} YUI instance. 5773 */ 5774 INSTANCE.log = function(msg, cat, src, silent) { 5775 var bail, excl, incl, m, f, minlevel, 5776 Y = INSTANCE, 5777 c = Y.config, 5778 publisher = (Y.fire) ? Y : YUI.Env.globalEvents; 5779 // suppress log message if the config is off or the event stack 5780 // or the event call stack contains a consumer of the yui:log event 5781 if (c.debug) { 5782 // apply source filters 5783 src = src || ""; 5784 if (typeof src !== "undefined") { 5785 excl = c.logExclude; 5786 incl = c.logInclude; 5787 if (incl && !(src in incl)) { 5788 bail = 1; 5789 } else if (incl && (src in incl)) { 5790 bail = !incl[src]; 5791 } else if (excl && (src in excl)) { 5792 bail = excl[src]; 5793 } 5794 5795 // Set a default category of info if the category was not defined. 5796 if ((typeof cat === 'undefined')) { 5797 cat = 'info'; 5798 } 5799 5800 // Determine the current minlevel as defined in configuration 5801 Y.config.logLevel = Y.config.logLevel || 'debug'; 5802 minlevel = LEVELS[Y.config.logLevel.toLowerCase()]; 5803 5804 if (cat in LEVELS && LEVELS[cat] < minlevel) { 5805 // Skip this message if the we don't meet the defined minlevel 5806 bail = 1; 5807 } 5808 } 5809 if (!bail) { 5810 if (c.useBrowserConsole) { 5811 m = (src) ? src + ': ' + msg : msg; 5812 if (Y.Lang.isFunction(c.logFn)) { 5813 c.logFn.call(Y, msg, cat, src); 5814 } else if (typeof console !== UNDEFINED && console.log) { 5815 f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log'; 5816 console[f](m); 5817 } else if (typeof opera !== UNDEFINED) { 5818 opera.postError(m); 5819 } 5820 } 5821 5822 if (publisher && !silent) { 5823 5824 if (publisher === Y && (!publisher.getEvent(LOGEVENT))) { 5825 publisher.publish(LOGEVENT, { 5826 broadcast: 2 5827 }); 5828 } 5829 5830 publisher.fire(LOGEVENT, { 5831 msg: msg, 5832 cat: cat, 5833 src: src 5834 }); 5835 } 5836 } 5837 } 5838 5839 return Y; 5840 }; 5841 5842 /** 5843 * Write a system message. This message will be preserved in the 5844 * minified and raw versions of the YUI files, unlike log statements. 5845 * @method message 5846 * @for YUI 5847 * @param {String} msg The message to log. 5848 * @param {String} cat The log category for the message. Default 5849 * categories are "info", "warn", "error", "debug". 5850 * Custom categories can be used as well. (opt). 5851 * @param {String} src The source of the the message (opt). 5852 * @param {boolean} silent If true, the log event won't fire. 5853 * @return {YUI} YUI instance. 5854 */ 5855 INSTANCE.message = function() { 5856 return INSTANCE.log.apply(INSTANCE, arguments); 5857 }; 5858 5859 5860 }, '3.17.2', {"requires": ["yui-base"]}); 5861 YUI.add('yui-later', function (Y, NAME) { 5862 5863 /** 5864 * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module, 5865 * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>. 5866 * 5867 * @module yui 5868 * @submodule yui-later 5869 */ 5870 5871 var NO_ARGS = []; 5872 5873 /** 5874 * Executes the supplied function in the context of the supplied 5875 * object 'when' milliseconds later. Executes the function a 5876 * single time unless periodic is set to true. 5877 * @for YUI 5878 * @method later 5879 * @param when {Number} the number of milliseconds to wait until the fn 5880 * is executed. 5881 * @param o the context object. 5882 * @param fn {Function|String} the function to execute or the name of 5883 * the method in the 'o' object to execute. 5884 * @param data [Array] data that is provided to the function. This 5885 * accepts either a single item or an array. If an array is provided, 5886 * the function is executed with one parameter for each array item. 5887 * If you need to pass a single array parameter, it needs to be wrapped 5888 * in an array [myarray]. 5889 * 5890 * Note: native methods in IE may not have the call and apply methods. 5891 * In this case, it will work, but you are limited to four arguments. 5892 * 5893 * @param periodic {boolean} if true, executes continuously at supplied 5894 * interval until canceled. 5895 * @return {object} a timer object. Call the cancel() method on this 5896 * object to stop the timer. 5897 */ 5898 Y.later = function(when, o, fn, data, periodic) { 5899 when = when || 0; 5900 data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS; 5901 o = o || Y.config.win || Y; 5902 5903 var cancelled = false, 5904 method = (o && Y.Lang.isString(fn)) ? o[fn] : fn, 5905 wrapper = function() { 5906 // IE 8- may execute a setInterval callback one last time 5907 // after clearInterval was called, so in order to preserve 5908 // the cancel() === no more runny-run, we have to jump through 5909 // an extra hoop. 5910 if (!cancelled) { 5911 if (!method.apply) { 5912 method(data[0], data[1], data[2], data[3]); 5913 } else { 5914 method.apply(o, data || NO_ARGS); 5915 } 5916 } 5917 }, 5918 id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when); 5919 5920 return { 5921 id: id, 5922 interval: periodic, 5923 cancel: function() { 5924 cancelled = true; 5925 if (this.interval) { 5926 clearInterval(id); 5927 } else { 5928 clearTimeout(id); 5929 } 5930 } 5931 }; 5932 }; 5933 5934 Y.Lang.later = Y.later; 5935 5936 5937 5938 }, '3.17.2', {"requires": ["yui-base"]}); 5939 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 |