[ 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', 'loader-base', 'loader-rollup', 'loader-yui3'], 355 loaderExtras: ['loader-rollup', 'loader-yui3'], 356 mods: {}, // flat module map 357 versions: {}, // version module map 358 base: BASE, 359 cdn: BASE + VERSION + '/build/', 360 // bootstrapped: false, 361 _idx: 0, 362 _used: {}, 363 _attached: {}, 364 _exported: {}, 365 _missed: [], 366 _yidx: 0, 367 _uidx: 0, 368 _guidp: 'y', 369 _loaded: {}, 370 // serviced: {}, 371 // Regex in English: 372 // I'll start at the \b(yui). 373 // 1. Look in the test string for "yui" or 374 // "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it 375 // can't match "foyui" or "i_heart_yui". This can be anywhere in the string. 376 // 2. After #1 must come a forward slash followed by the string matched in #1, so 377 // "yui-base/yui-base" or "yui-pants/yui-pants". 378 // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min", 379 // so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt". 380 // 4. This is followed by ".js", so "yui/yui.js". 381 // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string, 382 // then capture the junk between the LAST "&" and the string in 1-4. So 383 // "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js" 384 // will capture "3.3.0/build/" 385 // 386 // Regex Exploded: 387 // (?:\? Find a ? 388 // (?:[^&]*&) followed by 0..n characters followed by an & 389 // * in fact, find as many sets of characters followed by a & as you can 390 // ([^&]*) capture the stuff after the last & in \1 391 // )? but it's ok if all this ?junk&more_junk stuff isn't even there 392 // \b( after a word break find either the string 393 // yui(?:-\w+)? "yui" optionally followed by a -, then more characters 394 // ) and store the yui-* string in \2 395 // \/\2 then comes a / followed by the yui-* string in \2 396 // (?:-(min|debug))? optionally followed by "-min" or "-debug" 397 // .js and ending in ".js" 398 _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/, 399 parseBasePath: function(src, pattern) { 400 var match = src.match(pattern), 401 path, filter; 402 403 if (match) { 404 path = RegExp.leftContext || src.slice(0, src.indexOf(match[0])); 405 406 // this is to set up the path to the loader. The file 407 // filter for loader should match the yui include. 408 filter = match[3]; 409 410 // extract correct path for mixed combo urls 411 // http://yuilibrary.com/projects/yui3/ticket/2528423 412 if (match[1]) { 413 path += '?' + match[1]; 414 } 415 path = { 416 filter: filter, 417 path: path 418 }; 419 } 420 return path; 421 }, 422 getBase: G_ENV && G_ENV.getBase || 423 function(pattern) { 424 var nodes = (doc && doc.getElementsByTagName('script')) || [], 425 path = Env.cdn, parsed, 426 i, len, src; 427 428 for (i = 0, len = nodes.length; i < len; ++i) { 429 src = nodes[i].src; 430 if (src) { 431 parsed = Y.Env.parseBasePath(src, pattern); 432 if (parsed) { 433 filter = parsed.filter; 434 path = parsed.path; 435 break; 436 } 437 } 438 } 439 440 // use CDN default 441 return path; 442 } 443 444 }; 445 446 Env = Y.Env; 447 448 Env._loaded[VERSION] = {}; 449 450 if (G_ENV && Y !== YUI) { 451 Env._yidx = ++G_ENV._yidx; 452 Env._guidp = ('yui_' + VERSION + '_' + 453 Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_'); 454 } else if (YUI._YUI) { 455 456 G_ENV = YUI._YUI.Env; 457 Env._yidx += G_ENV._yidx; 458 Env._uidx += G_ENV._uidx; 459 460 for (prop in G_ENV) { 461 if (!(prop in Env)) { 462 Env[prop] = G_ENV[prop]; 463 } 464 } 465 466 delete YUI._YUI; 467 } 468 469 Y.id = Y.stamp(Y); 470 instances[Y.id] = Y; 471 472 } 473 474 Y.constructor = YUI; 475 476 // configuration defaults 477 Y.config = Y.config || { 478 bootstrap: true, 479 cacheUse: true, 480 debug: true, 481 doc: doc, 482 fetchCSS: true, 483 throwFail: true, 484 useBrowserConsole: true, 485 useNativeES5: true, 486 win: win, 487 global: Function('return this')() 488 }; 489 490 //Register the CSS stamp element 491 if (doc && !doc.getElementById(CSS_STAMP_EL)) { 492 el = doc.createElement('div'); 493 el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>'; 494 YUI.Env.cssStampEl = el.firstChild; 495 if (doc.body) { 496 doc.body.appendChild(YUI.Env.cssStampEl); 497 } else { 498 docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild); 499 } 500 } else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) { 501 YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL); 502 } 503 504 Y.config.lang = Y.config.lang || 'en-US'; 505 506 Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE); 507 508 if (!filter || (!('mindebug').indexOf(filter))) { 509 filter = 'min'; 510 } 511 filter = (filter) ? '-' + filter : filter; 512 Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js'; 513 514 }, 515 516 /** 517 Finishes the instance setup. Attaches whatever YUI modules were defined 518 at the time that this instance was created. 519 520 @method _setup 521 @private 522 **/ 523 _setup: function() { 524 var i, Y = this, 525 core = [], 526 mods = YUI.Env.mods, 527 extras = Y.config.core || [].concat(YUI.Env.core); //Clone it.. 528 529 for (i = 0; i < extras.length; i++) { 530 if (mods[extras[i]]) { 531 core.push(extras[i]); 532 } 533 } 534 535 Y._attach(['yui-base']); 536 Y._attach(core); 537 538 if (Y.Loader) { 539 getLoader(Y); 540 } 541 542 // Y.log(Y.id + ' initialized', 'info', 'yui'); 543 }, 544 545 /** 546 Executes the named method on the specified YUI instance if that method is 547 whitelisted. 548 549 @method applyTo 550 @param {String} id YUI instance id. 551 @param {String} method Name of the method to execute. For example: 552 'Object.keys'. 553 @param {Array} args Arguments to apply to the method. 554 @return {Mixed} Return value from the applied method, or `null` if the 555 specified instance was not found or the method was not whitelisted. 556 **/ 557 applyTo: function(id, method, args) { 558 if (!(method in APPLY_TO_AUTH)) { 559 this.log(method + ': applyTo not allowed', 'warn', 'yui'); 560 return null; 561 } 562 563 var instance = instances[id], nest, m, i; 564 if (instance) { 565 nest = method.split('.'); 566 m = instance; 567 for (i = 0; i < nest.length; i = i + 1) { 568 m = m[nest[i]]; 569 if (!m) { 570 this.log('applyTo not found: ' + method, 'warn', 'yui'); 571 } 572 } 573 return m && m.apply(instance, args); 574 } 575 576 return null; 577 }, 578 579 /** 580 Registers a YUI module and makes it available for use in a `YUI().use()` call or 581 as a dependency for other modules. 582 583 The easiest way to create a first-class YUI module is to use 584 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build 585 tool. 586 587 Shifter will automatically wrap your module code in a `YUI.add()` call along 588 with any configuration info required for the module. 589 590 @example 591 592 YUI.add('davglass', function (Y) { 593 Y.davglass = function () { 594 Y.log('Dav was here!'); 595 }; 596 }, '3.4.0', { 597 requires: ['harley-davidson', 'mt-dew'] 598 }); 599 600 @method add 601 @param {String} name Module name. 602 @param {Function} fn Function containing module code. This function will be 603 executed whenever the module is attached to a specific YUI instance. 604 605 @param {YUI} fn.Y The YUI instance to which this module is attached. 606 @param {String} fn.name Name of the module 607 608 @param {String} version Module version number. This is currently used only for 609 informational purposes, and is not used internally by YUI. 610 611 @param {Object} [details] Module config. 612 @param {Array} [details.requires] Array of other module names that must be 613 attached before this module can be attached. 614 @param {Array} [details.optional] Array of optional module names that should 615 be attached before this module is attached if they've already been 616 loaded. If the `loadOptional` YUI option is `true`, optional modules 617 that have not yet been loaded will be loaded just as if they were hard 618 requirements. 619 @param {Array} [details.use] Array of module names that are included within 620 or otherwise provided by this module, and which should be attached 621 automatically when this module is attached. This makes it possible to 622 create "virtual rollup" modules that simply attach a collection of other 623 modules or submodules. 624 625 @return {YUI} This YUI instance. 626 **/ 627 add: function(name, fn, version, details) { 628 details = details || {}; 629 var env = YUI.Env, 630 mod = { 631 name: name, 632 fn: fn, 633 version: version, 634 details: details 635 }, 636 //Instance hash so we don't apply it to the same instance twice 637 applied = {}, 638 loader, inst, modInfo, 639 i, versions = env.versions; 640 641 env.mods[name] = mod; 642 versions[version] = versions[version] || {}; 643 versions[version][name] = mod; 644 645 for (i in instances) { 646 if (instances.hasOwnProperty(i)) { 647 inst = instances[i]; 648 if (!applied[inst.id]) { 649 applied[inst.id] = true; 650 loader = inst.Env._loader; 651 if (loader) { 652 modInfo = loader.getModuleInfo(name); 653 if (!modInfo || modInfo.temp) { 654 loader.addModule(details, name); 655 } 656 } 657 } 658 } 659 } 660 661 return this; 662 }, 663 664 /** 665 Executes the callback function associated with each required module, 666 attaching the module to this YUI instance. 667 668 @method _attach 669 @param {Array} r The array of modules to attach 670 @param {Boolean} [moot=false] If `true`, don't throw a warning if the module 671 is not attached. 672 @private 673 **/ 674 _attach: function(r, moot) { 675 var i, name, mod, details, req, use, after, 676 mods = YUI.Env.mods, 677 aliases = YUI.Env.aliases, 678 Y = this, j, 679 cache = YUI.Env._renderedMods, 680 loader = Y.Env._loader, 681 done = Y.Env._attached, 682 exported = Y.Env._exported, 683 len = r.length, loader, def, go, 684 c = [], 685 modArgs, esCompat, reqlen, modInfo, 686 condition, 687 __exports__, __imports__; 688 689 //Check for conditional modules (in a second+ instance) and add their requirements 690 //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass 691 for (i = 0; i < len; i++) { 692 name = r[i]; 693 mod = mods[name]; 694 c.push(name); 695 if (loader && loader.conditions[name]) { 696 for (j in loader.conditions[name]) { 697 if (loader.conditions[name].hasOwnProperty(j)) { 698 def = loader.conditions[name][j]; 699 go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y))); 700 if (go) { 701 c.push(def.name); 702 } 703 } 704 } 705 } 706 } 707 r = c; 708 len = r.length; 709 710 for (i = 0; i < len; i++) { 711 if (!done[r[i]]) { 712 name = r[i]; 713 mod = mods[name]; 714 715 if (aliases && aliases[name] && !mod) { 716 Y._attach(aliases[name]); 717 continue; 718 } 719 if (!mod) { 720 modInfo = loader && loader.getModuleInfo(name); 721 if (modInfo) { 722 mod = modInfo; 723 moot = true; 724 } 725 726 // Y.log('no js def for: ' + name, 'info', 'yui'); 727 728 //if (!loader || !loader.moduleInfo[name]) { 729 //if ((!loader || !loader.moduleInfo[name]) && !moot) { 730 if (!moot && name) { 731 if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) { 732 Y.Env._missed.push(name); 733 Y.Env._missed = Y.Array.dedupe(Y.Env._missed); 734 Y.message('NOT loaded: ' + name, 'warn', 'yui'); 735 } 736 } 737 } else { 738 done[name] = true; 739 //Don't like this, but in case a mod was asked for once, then we fetch it 740 //We need to remove it from the missed list ^davglass 741 for (j = 0; j < Y.Env._missed.length; j++) { 742 if (Y.Env._missed[j] === name) { 743 Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui'); 744 Y.Env._missed.splice(j, 1); 745 } 746 } 747 748 // Optional dependencies normally work by modifying the 749 // dependency list of a module. If the dependency's test 750 // passes it is added to the list. If not, it's not loaded. 751 // This following check ensures that optional dependencies 752 // are not attached when they were already loaded into the 753 // page (when bundling for example) 754 if (loader && !loader._canBeAttached(name)) { 755 Y.log('Failed to attach module ' + name, 'warn', 'yui'); 756 return true; 757 } 758 759 /* 760 If it's a temp module, we need to redo it's requirements if it's already loaded 761 since it may have been loaded by another instance and it's dependencies might 762 have been redefined inside the fetched file. 763 */ 764 if (loader && cache && cache[name] && cache[name].temp) { 765 loader.getRequires(cache[name]); 766 req = []; 767 modInfo = loader.getModuleInfo(name); 768 for (j in modInfo.expanded_map) { 769 if (modInfo.expanded_map.hasOwnProperty(j)) { 770 req.push(j); 771 } 772 } 773 Y._attach(req); 774 } 775 776 details = mod.details; 777 req = details.requires; 778 esCompat = details.es; 779 use = details.use; 780 after = details.after; 781 //Force Intl load if there is a language (Loader logic) @todo fix this shit 782 if (details.lang) { 783 req = req || []; 784 req.unshift('intl'); 785 } 786 787 if (req) { 788 reqlen = req.length; 789 for (j = 0; j < reqlen; j++) { 790 if (!done[req[j]]) { 791 if (!Y._attach(req)) { 792 return false; 793 } 794 break; 795 } 796 } 797 } 798 799 if (after) { 800 for (j = 0; j < after.length; j++) { 801 if (!done[after[j]]) { 802 if (!Y._attach(after, true)) { 803 return false; 804 } 805 break; 806 } 807 } 808 } 809 810 if (mod.fn) { 811 modArgs = [Y, name]; 812 if (esCompat) { 813 __imports__ = {}; 814 __exports__ = {}; 815 // passing `exports` and `imports` onto the module function 816 modArgs.push(__imports__, __exports__); 817 if (req) { 818 reqlen = req.length; 819 for (j = 0; j < reqlen; j++) { 820 __imports__[req[j]] = exported.hasOwnProperty(req[j]) ? exported[req[j]] : Y; 821 } 822 } 823 } 824 if (Y.config.throwFail) { 825 __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); 826 } else { 827 try { 828 __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); 829 } catch (e) { 830 Y.error('Attach error: ' + name, e, name); 831 return false; 832 } 833 } 834 if (esCompat) { 835 // store the `exports` in case others `es` modules requires it 836 exported[name] = __exports__; 837 838 // If an ES module is conditionally loaded and set 839 // to be used "instead" another module, replace the 840 // trigger module's content with the conditionally 841 // loaded one so the values returned by require() 842 // still makes sense 843 condition = mod.details.condition; 844 if (condition && condition.when === 'instead') { 845 exported[condition.trigger] = __exports__; 846 } 847 } 848 } 849 850 if (use) { 851 for (j = 0; j < use.length; j++) { 852 if (!done[use[j]]) { 853 if (!Y._attach(use)) { 854 return false; 855 } 856 break; 857 } 858 } 859 } 860 861 862 863 } 864 } 865 } 866 867 return true; 868 }, 869 870 /** 871 Delays the `use` callback until another event has taken place such as 872 `window.onload`, `domready`, `contentready`, or `available`. 873 874 @private 875 @method _delayCallback 876 @param {Function} cb The original `use` callback. 877 @param {String|Object} until Either an event name ('load', 'domready', etc.) 878 or an object containing event/args keys for contentready/available. 879 @return {Function} 880 **/ 881 _delayCallback: function(cb, until) { 882 883 var Y = this, 884 mod = ['event-base']; 885 886 until = (Y.Lang.isObject(until) ? until : { event: until }); 887 888 if (until.event === 'load') { 889 mod.push('event-synthetic'); 890 } 891 892 Y.log('Delaying use callback until: ' + until.event, 'info', 'yui'); 893 return function() { 894 Y.log('Use callback fired, waiting on delay', 'info', 'yui'); 895 var args = arguments; 896 Y._use(mod, function() { 897 Y.log('Delayed use wrapper callback after dependencies', 'info', 'yui'); 898 Y.on(until.event, function() { 899 args[1].delayUntil = until.event; 900 Y.log('Delayed use callback done after ' + until.event, 'info', 'yui'); 901 cb.apply(Y, args); 902 }, until.args); 903 }); 904 }; 905 }, 906 907 /** 908 Attaches one or more modules to this YUI instance. When this is executed, 909 the requirements of the desired modules are analyzed, and one of several 910 things can happen: 911 912 913 * All required modules have already been loaded, and just need to be 914 attached to this YUI instance. In this case, the `use()` callback will 915 be executed synchronously after the modules are attached. 916 917 * One or more modules have not yet been loaded, or the Get utility is not 918 available, or the `bootstrap` config option is `false`. In this case, 919 a warning is issued indicating that modules are missing, but all 920 available modules will still be attached and the `use()` callback will 921 be executed synchronously. 922 923 * One or more modules are missing and the Loader is not available but the 924 Get utility is, and `bootstrap` is not `false`. In this case, the Get 925 utility will be used to load the Loader, and we will then proceed to 926 the following state: 927 928 * One or more modules are missing and the Loader is available. In this 929 case, the Loader will be used to resolve the dependency tree for the 930 missing modules and load them and their dependencies. When the Loader is 931 finished loading modules, the `use()` callback will be executed 932 asynchronously. 933 934 @example 935 936 // Loads and attaches dd and its dependencies. 937 YUI().use('dd', function (Y) { 938 // ... 939 }); 940 941 // Loads and attaches dd and node as well as all of their dependencies. 942 YUI().use(['dd', 'node'], function (Y) { 943 // ... 944 }); 945 946 // Attaches all modules that have already been loaded. 947 YUI().use('*', function (Y) { 948 // ... 949 }); 950 951 // Attaches a gallery module. 952 YUI().use('gallery-yql', function (Y) { 953 // ... 954 }); 955 956 // Attaches a YUI 2in3 module. 957 YUI().use('yui2-datatable', function (Y) { 958 // ... 959 }); 960 961 @method use 962 @param {String|Array} modules* One or more module names to attach. 963 @param {Function} [callback] Callback function to be executed once all 964 specified modules and their dependencies have been attached. 965 @param {YUI} callback.Y The YUI instance created for this sandbox. 966 @param {Object} callback.status Object containing `success`, `msg` and 967 `data` properties. 968 @chainable 969 **/ 970 use: function() { 971 var args = SLICE.call(arguments, 0), 972 callback = args[args.length - 1], 973 Y = this, 974 i = 0, 975 name, 976 Env = Y.Env, 977 provisioned = true; 978 979 // The last argument supplied to use can be a load complete callback 980 if (Y.Lang.isFunction(callback)) { 981 args.pop(); 982 if (Y.config.delayUntil) { 983 callback = Y._delayCallback(callback, Y.config.delayUntil); 984 } 985 } else { 986 callback = null; 987 } 988 if (Y.Lang.isArray(args[0])) { 989 args = args[0]; 990 } 991 992 if (Y.config.cacheUse) { 993 while ((name = args[i++])) { 994 if (!Env._attached[name]) { 995 provisioned = false; 996 break; 997 } 998 } 999 1000 if (provisioned) { 1001 if (args.length) { 1002 Y.log('already provisioned: ' + args, 'info', 'yui'); 1003 } 1004 Y._notify(callback, ALREADY_DONE, args); 1005 return Y; 1006 } 1007 } 1008 1009 if (Y._loading) { 1010 Y._useQueue = Y._useQueue || new Y.Queue(); 1011 Y._useQueue.add([args, callback]); 1012 } else { 1013 Y._use(args, function(Y, response) { 1014 Y._notify(callback, response, args); 1015 }); 1016 } 1017 1018 return Y; 1019 }, 1020 1021 /** 1022 Sugar for loading both legacy and ES6-based YUI modules. 1023 1024 @method require 1025 @param {String} [modules*] List of module names to import or a single 1026 module name. 1027 @param {Function} callback Callback that gets called once all the modules 1028 were loaded. Each parameter of the callback is the export value of the 1029 corresponding module in the list. If the module is a legacy YUI module, 1030 the YUI instance is used instead of the module exports. 1031 @example 1032 ``` 1033 YUI().require(['es6-set'], function (Y, imports) { 1034 var Set = imports.Set, 1035 set = new Set(); 1036 }); 1037 ``` 1038 **/ 1039 require: function () { 1040 var args = SLICE.call(arguments), 1041 callback; 1042 1043 if (typeof args[args.length - 1] === 'function') { 1044 callback = args.pop(); 1045 1046 // only add the callback if one was provided 1047 // YUI().require('foo'); is valid 1048 args.push(function (Y) { 1049 var i, length = args.length, 1050 exported = Y.Env._exported, 1051 __imports__ = {}; 1052 1053 // Get only the imports requested as arguments 1054 for (i = 0; i < length; i++) { 1055 if (exported.hasOwnProperty(args[i])) { 1056 __imports__[args[i]] = exported[args[i]]; 1057 } 1058 } 1059 1060 // Using `undefined` because: 1061 // - Using `Y.config.global` would force the value of `this` to be 1062 // the global object even in strict mode 1063 // - Using `Y` goes against the goal of moving away from a shared 1064 // object and start thinking in terms of imported and exported 1065 // objects 1066 callback.call(undefined, Y, __imports__); 1067 }); 1068 } 1069 // Do not return the Y object. This makes it hard to follow this 1070 // traditional pattern: 1071 // var Y = YUI().use(...); 1072 // This is a good idea in the light of ES6 modules, to avoid working 1073 // in the global scope. 1074 // This also leaves the door open for returning a promise, once the 1075 // YUI loader is based on the ES6 loader which uses 1076 // loader.import(...).then(...) 1077 this.use.apply(this, args); 1078 }, 1079 1080 /** 1081 Handles Loader notifications about attachment/load errors. 1082 1083 @method _notify 1084 @param {Function} callback Callback to pass to `Y.config.loadErrorFn`. 1085 @param {Object} response Response returned from Loader. 1086 @param {Array} args Arguments passed from Loader. 1087 @private 1088 **/ 1089 _notify: function(callback, response, args) { 1090 if (!response.success && this.config.loadErrorFn) { 1091 this.config.loadErrorFn.call(this, this, callback, response, args); 1092 } else if (callback) { 1093 if (this.Env._missed && this.Env._missed.length) { 1094 response.msg = 'Missing modules: ' + this.Env._missed.join(); 1095 response.success = false; 1096 } 1097 if (this.config.throwFail) { 1098 callback(this, response); 1099 } else { 1100 try { 1101 callback(this, response); 1102 } catch (e) { 1103 this.error('use callback error', e, args); 1104 } 1105 } 1106 } 1107 }, 1108 1109 /** 1110 Called from the `use` method queue to ensure that only one set of loading 1111 logic is performed at a time. 1112 1113 @method _use 1114 @param {String} args* One or more modules to attach. 1115 @param {Function} [callback] Function to call once all required modules have 1116 been attached. 1117 @private 1118 **/ 1119 _use: function(args, callback) { 1120 1121 if (!this.Array) { 1122 this._attach(['yui-base']); 1123 } 1124 1125 var len, loader, handleBoot, 1126 Y = this, 1127 G_ENV = YUI.Env, 1128 mods = G_ENV.mods, 1129 Env = Y.Env, 1130 used = Env._used, 1131 aliases = G_ENV.aliases, 1132 queue = G_ENV._loaderQueue, 1133 firstArg = args[0], 1134 YArray = Y.Array, 1135 config = Y.config, 1136 boot = config.bootstrap, 1137 missing = [], 1138 i, 1139 r = [], 1140 ret = true, 1141 fetchCSS = config.fetchCSS, 1142 process = function(names, skip) { 1143 1144 var i = 0, a = [], name, len, m, req, use; 1145 1146 if (!names.length) { 1147 return; 1148 } 1149 1150 if (aliases) { 1151 len = names.length; 1152 for (i = 0; i < len; i++) { 1153 if (aliases[names[i]] && !mods[names[i]]) { 1154 a = [].concat(a, aliases[names[i]]); 1155 } else { 1156 a.push(names[i]); 1157 } 1158 } 1159 names = a; 1160 } 1161 1162 len = names.length; 1163 1164 for (i = 0; i < len; i++) { 1165 name = names[i]; 1166 if (!skip) { 1167 r.push(name); 1168 } 1169 1170 // only attach a module once 1171 if (used[name]) { 1172 continue; 1173 } 1174 1175 m = mods[name]; 1176 req = null; 1177 use = null; 1178 1179 if (m) { 1180 used[name] = true; 1181 req = m.details.requires; 1182 use = m.details.use; 1183 } else { 1184 // CSS files don't register themselves, see if it has 1185 // been loaded 1186 if (!G_ENV._loaded[VERSION][name]) { 1187 missing.push(name); 1188 } else { 1189 used[name] = true; // probably css 1190 } 1191 } 1192 1193 // make sure requirements are attached 1194 if (req && req.length) { 1195 process(req); 1196 } 1197 1198 // make sure we grab the submodule dependencies too 1199 if (use && use.length) { 1200 process(use, 1); 1201 } 1202 } 1203 1204 }, 1205 1206 handleLoader = function(fromLoader) { 1207 var response = fromLoader || { 1208 success: true, 1209 msg: 'not dynamic' 1210 }, 1211 redo, origMissing, 1212 ret = true, 1213 data = response.data; 1214 1215 Y._loading = false; 1216 1217 if (data) { 1218 origMissing = missing; 1219 missing = []; 1220 r = []; 1221 process(data); 1222 redo = missing.length; 1223 if (redo) { 1224 if ([].concat(missing).sort().join() == 1225 origMissing.sort().join()) { 1226 redo = false; 1227 } 1228 } 1229 } 1230 1231 if (redo && data) { 1232 Y._loading = true; 1233 Y._use(missing, function() { 1234 Y.log('Nested use callback: ' + data, 'info', 'yui'); 1235 if (Y._attach(data)) { 1236 Y._notify(callback, response, data); 1237 } 1238 }); 1239 } else { 1240 if (data) { 1241 // Y.log('attaching from loader: ' + data, 'info', 'yui'); 1242 ret = Y._attach(data); 1243 } 1244 if (ret) { 1245 Y._notify(callback, response, args); 1246 } 1247 } 1248 1249 if (Y._useQueue && Y._useQueue.size() && !Y._loading) { 1250 Y._use.apply(Y, Y._useQueue.next()); 1251 } 1252 1253 }; 1254 1255 // Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui'); 1256 1257 // YUI().use('*'); // bind everything available 1258 if (firstArg === '*') { 1259 args = []; 1260 for (i in mods) { 1261 if (mods.hasOwnProperty(i)) { 1262 args.push(i); 1263 } 1264 } 1265 ret = Y._attach(args); 1266 if (ret) { 1267 handleLoader(); 1268 } 1269 return Y; 1270 } 1271 1272 if ((mods.loader || mods['loader-base']) && !Y.Loader) { 1273 Y.log('Loader was found in meta, but it is not attached. Attaching..', 'info', 'yui'); 1274 Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]); 1275 } 1276 1277 // Y.log('before loader requirements: ' + args, 'info', 'yui'); 1278 1279 // use loader to expand dependencies and sort the 1280 // requirements if it is available. 1281 if (boot && Y.Loader && args.length) { 1282 Y.log('Using loader to expand dependencies', 'info', 'yui'); 1283 loader = getLoader(Y); 1284 loader.require(args); 1285 loader.ignoreRegistered = true; 1286 loader._boot = true; 1287 loader.calculate(null, (fetchCSS) ? null : 'js'); 1288 args = loader.sorted; 1289 loader._boot = false; 1290 } 1291 1292 process(args); 1293 1294 len = missing.length; 1295 1296 1297 if (len) { 1298 missing = YArray.dedupe(missing); 1299 len = missing.length; 1300 Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui'); 1301 } 1302 1303 1304 // dynamic load 1305 if (boot && len && Y.Loader) { 1306 // Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui'); 1307 Y.log('Using Loader', 'info', 'yui'); 1308 Y._loading = true; 1309 loader = getLoader(Y); 1310 loader.onEnd = handleLoader; 1311 loader.context = Y; 1312 loader.data = args; 1313 loader.ignoreRegistered = false; 1314 loader.require(missing); 1315 loader.insert(null, (fetchCSS) ? null : 'js'); 1316 1317 } else if (boot && len && Y.Get && !Env.bootstrapped) { 1318 1319 Y._loading = true; 1320 1321 handleBoot = function() { 1322 Y._loading = false; 1323 queue.running = false; 1324 Env.bootstrapped = true; 1325 G_ENV._bootstrapping = false; 1326 if (Y._attach(['loader'])) { 1327 Y._use(args, callback); 1328 } 1329 }; 1330 1331 if (G_ENV._bootstrapping) { 1332 Y.log('Waiting for loader', 'info', 'yui'); 1333 queue.add(handleBoot); 1334 } else { 1335 G_ENV._bootstrapping = true; 1336 Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui'); 1337 Y.Get.script(config.base + config.loaderPath, { 1338 onEnd: handleBoot 1339 }); 1340 } 1341 1342 } else { 1343 Y.log('Attaching available dependencies: ' + args, 'info', 'yui'); 1344 ret = Y._attach(args); 1345 if (ret) { 1346 handleLoader(); 1347 } 1348 } 1349 1350 return Y; 1351 }, 1352 1353 1354 /** 1355 Utility method for safely creating namespaces if they don't already exist. 1356 May be called statically on the YUI global object or as a method on a YUI 1357 instance. 1358 1359 When called statically, a namespace will be created on the YUI global 1360 object: 1361 1362 // Create `YUI.your.namespace.here` as nested objects, preserving any 1363 // objects that already exist instead of overwriting them. 1364 YUI.namespace('your.namespace.here'); 1365 1366 When called as a method on a YUI instance, a namespace will be created on 1367 that instance: 1368 1369 // Creates `Y.property.package`. 1370 Y.namespace('property.package'); 1371 1372 Dots in the input string cause `namespace` to create nested objects for each 1373 token. If any part of the requested namespace already exists, the current 1374 object will be left in place and will not be overwritten. This allows 1375 multiple calls to `namespace` to preserve existing namespaced properties. 1376 1377 If the first token in the namespace string is "YAHOO", that token is 1378 discarded. This is legacy behavior for backwards compatibility with YUI 2. 1379 1380 Be careful with namespace tokens. Reserved words may work in some browsers 1381 and not others. For instance, the following will fail in some browsers 1382 because the supported version of JavaScript reserves the word "long": 1383 1384 Y.namespace('really.long.nested.namespace'); 1385 1386 Note: If you pass multiple arguments to create multiple namespaces, only the 1387 last one created is returned from this function. 1388 1389 @method namespace 1390 @param {String} namespace* One or more namespaces to create. 1391 @return {Object} Reference to the last namespace object created. 1392 **/ 1393 namespace: function() { 1394 var a = arguments, o, i = 0, j, d, arg; 1395 1396 for (; i < a.length; i++) { 1397 o = this; //Reset base object per argument or it will get reused from the last 1398 arg = a[i]; 1399 if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present 1400 d = arg.split(PERIOD); 1401 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) { 1402 o[d[j]] = o[d[j]] || {}; 1403 o = o[d[j]]; 1404 } 1405 } else { 1406 o[arg] = o[arg] || {}; 1407 o = o[arg]; //Reset base object to the new object so it's returned 1408 } 1409 } 1410 return o; 1411 }, 1412 1413 // this is replaced if the log module is included 1414 log: NOOP, 1415 message: NOOP, 1416 // this is replaced if the dump module is included 1417 dump: function (o) { return ''+o; }, 1418 1419 /** 1420 Reports an error. 1421 1422 The reporting mechanism is controlled by the `throwFail` configuration 1423 attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is 1424 truthy, a JS exception is thrown. 1425 1426 If an `errorFn` is specified in the config it must return `true` to indicate 1427 that the exception was handled and keep it from being thrown. 1428 1429 @method error 1430 @param {String} msg Error message. 1431 @param {Error|String} [e] JavaScript error object or an error string. 1432 @param {String} [src] Source of the error (such as the name of the module in 1433 which the error occurred). 1434 @chainable 1435 **/ 1436 error: function(msg, e, src) { 1437 //TODO Add check for window.onerror here 1438 1439 var Y = this, ret; 1440 1441 if (Y.config.errorFn) { 1442 ret = Y.config.errorFn.apply(Y, arguments); 1443 } 1444 1445 if (!ret) { 1446 throw (e || new Error(msg)); 1447 } else { 1448 Y.message(msg, 'error', ''+src); // don't scrub this one 1449 } 1450 1451 return Y; 1452 }, 1453 1454 /** 1455 Generates an id string that is unique among all YUI instances in this 1456 execution context. 1457 1458 @method guid 1459 @param {String} [pre] Prefix. 1460 @return {String} Unique id. 1461 **/ 1462 guid: function(pre) { 1463 var id = this.Env._guidp + '_' + (++this.Env._uidx); 1464 return (pre) ? (pre + id) : id; 1465 }, 1466 1467 /** 1468 Returns a unique id associated with the given object and (if *readOnly* is 1469 falsy) stamps the object with that id so it can be identified in the future. 1470 1471 Stamping an object involves adding a `_yuid` property to it that contains 1472 the object's id. One exception to this is that in Internet Explorer, DOM 1473 nodes have a `uniqueID` property that contains a browser-generated unique 1474 id, which will be used instead of a YUI-generated id when available. 1475 1476 @method stamp 1477 @param {Object} o Object to stamp. 1478 @param {Boolean} readOnly If truthy and the given object has not already 1479 been stamped, the object will not be modified and `null` will be 1480 returned. 1481 @return {String} Object's unique id, or `null` if *readOnly* was truthy and 1482 the given object was not already stamped. 1483 **/ 1484 stamp: function(o, readOnly) { 1485 var uid; 1486 if (!o) { 1487 return o; 1488 } 1489 1490 // IE generates its own unique ID for dom nodes 1491 // The uniqueID property of a document node returns a new ID 1492 if (o.uniqueID && o.nodeType && o.nodeType !== 9) { 1493 uid = o.uniqueID; 1494 } else { 1495 uid = (typeof o === 'string') ? o : o._yuid; 1496 } 1497 1498 if (!uid) { 1499 uid = this.guid(); 1500 if (!readOnly) { 1501 try { 1502 o._yuid = uid; 1503 } catch (e) { 1504 uid = null; 1505 } 1506 } 1507 } 1508 return uid; 1509 }, 1510 1511 /** 1512 Destroys this YUI instance. 1513 1514 @method destroy 1515 @since 3.3.0 1516 **/ 1517 destroy: function() { 1518 var Y = this; 1519 if (Y.Event) { 1520 Y.Event._unload(); 1521 } 1522 delete instances[Y.id]; 1523 delete Y.Env; 1524 delete Y.config; 1525 } 1526 1527 /** 1528 Safe `instanceof` wrapper that works around a memory leak in IE when the 1529 object being tested is `window` or `document`. 1530 1531 Unless you are testing objects that may be `window` or `document`, you 1532 should use the native `instanceof` operator instead of this method. 1533 1534 @method instanceOf 1535 @param {Object} o Object to check. 1536 @param {Object} type Class to check against. 1537 @since 3.3.0 1538 **/ 1539 }; 1540 1541 YUI.prototype = proto; 1542 1543 // inheritance utilities are not available yet 1544 for (prop in proto) { 1545 if (proto.hasOwnProperty(prop)) { 1546 YUI[prop] = proto[prop]; 1547 } 1548 } 1549 1550 /** 1551 Applies a configuration to all YUI instances in this execution context. 1552 1553 The main use case for this method is in "mashups" where several third-party 1554 scripts need to write to a global YUI config, but cannot share a single 1555 centrally-managed config object. This way they can all call 1556 `YUI.applyConfig({})` instead of overwriting the single global config. 1557 1558 @example 1559 1560 YUI.applyConfig({ 1561 modules: { 1562 davglass: { 1563 fullpath: './davglass.js' 1564 } 1565 } 1566 }); 1567 1568 YUI.applyConfig({ 1569 modules: { 1570 foo: { 1571 fullpath: './foo.js' 1572 } 1573 } 1574 }); 1575 1576 YUI().use('davglass', function (Y) { 1577 // Module davglass will be available here. 1578 }); 1579 1580 @method applyConfig 1581 @param {Object} o Configuration object to apply. 1582 @static 1583 @since 3.5.0 1584 **/ 1585 YUI.applyConfig = function(o) { 1586 if (!o) { 1587 return; 1588 } 1589 //If there is a GlobalConfig, apply it first to set the defaults 1590 if (YUI.GlobalConfig) { 1591 this.prototype.applyConfig.call(this, YUI.GlobalConfig); 1592 } 1593 //Apply this config to it 1594 this.prototype.applyConfig.call(this, o); 1595 //Reset GlobalConfig to the combined config 1596 YUI.GlobalConfig = this.config; 1597 }; 1598 1599 // set up the environment 1600 YUI._init(); 1601 1602 if (hasWin) { 1603 add(doc, 'DOMContentLoaded', handleReady); 1604 1605 // add a window load event at load time so we can capture 1606 // the case where it fires before dynamic loading is 1607 // complete. 1608 add(window, 'load', handleLoad); 1609 } else { 1610 handleReady(); 1611 handleLoad(); 1612 } 1613 1614 YUI.Env.add = add; 1615 YUI.Env.remove = remove; 1616 1617 /*global exports*/ 1618 // Support the CommonJS method for exporting our single global 1619 if (typeof exports == 'object') { 1620 exports.YUI = YUI; 1621 /** 1622 * Set a method to be called when `Get.script` is called in Node.js 1623 * `Get` will open the file, then pass it's content and it's path 1624 * to this method before attaching it. Commonly used for code coverage 1625 * instrumentation. <strong>Calling this multiple times will only 1626 * attach the last hook method</strong>. This method is only 1627 * available in Node.js. 1628 * @method setLoadHook 1629 * @static 1630 * @param {Function} fn The function to set 1631 * @param {String} fn.data The content of the file 1632 * @param {String} fn.path The file path of the file 1633 */ 1634 YUI.setLoadHook = function(fn) { 1635 YUI._getLoadHook = fn; 1636 }; 1637 /** 1638 * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook` 1639 * @method _getLoadHook 1640 * @private 1641 * @param {String} data The content of the file 1642 * @param {String} path The file path of the file 1643 */ 1644 YUI._getLoadHook = null; 1645 } 1646 1647 YUI.Env[VERSION] = {}; 1648 }()); 1649 1650 1651 /** 1652 Config object that contains all of the configuration options for 1653 this `YUI` instance. 1654 1655 This object is supplied by the implementer when instantiating YUI. Some 1656 properties have default values if they are not supplied by the implementer. 1657 1658 This object should not be updated directly because some values are cached. Use 1659 `applyConfig()` to update the config object on a YUI instance that has already 1660 been configured. 1661 1662 @class config 1663 @static 1664 **/ 1665 1666 /** 1667 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata 1668 if they're needed to load additional dependencies and aren't already available. 1669 1670 Setting this to `false` will prevent YUI from automatically loading the Loader 1671 and module metadata, so you will need to manually ensure that they're available 1672 or handle dependency resolution yourself. 1673 1674 @property {Boolean} bootstrap 1675 @default true 1676 **/ 1677 1678 /** 1679 If `true`, `Y.log()` messages will be written to the browser's debug console 1680 when available and when `useBrowserConsole` is also `true`. 1681 1682 @property {Boolean} debug 1683 @default true 1684 **/ 1685 1686 /** 1687 Log messages to the browser console if `debug` is `true` and the browser has a 1688 supported console. 1689 1690 @property {Boolean} useBrowserConsole 1691 @default true 1692 **/ 1693 1694 /** 1695 A hash of log sources that should be logged. If specified, only messages from 1696 these sources will be logged. Others will be discarded. 1697 1698 @property {Object} logInclude 1699 @type object 1700 **/ 1701 1702 /** 1703 A hash of log sources that should be not be logged. If specified, all sources 1704 will be logged *except* those on this list. 1705 1706 @property {Object} logExclude 1707 **/ 1708 1709 /** 1710 When the YUI seed file is dynamically loaded after the `window.onload` event has 1711 fired, set this to `true` to tell YUI that it shouldn't wait for `window.onload` 1712 to occur. 1713 1714 This ensures that components that rely on `window.onload` and the `domready` 1715 custom event will work as expected even when YUI is dynamically injected. 1716 1717 @property {Boolean} injected 1718 @default false 1719 **/ 1720 1721 /** 1722 If `true`, `Y.error()` will generate or re-throw a JavaScript error. Otherwise, 1723 errors are merely logged silently. 1724 1725 @property {Boolean} throwFail 1726 @default true 1727 **/ 1728 1729 /** 1730 Reference to the global object for this execution context. 1731 1732 In a browser, this is the current `window` object. In Node.js, this is the 1733 Node.js `global` object. 1734 1735 @property {Object} global 1736 **/ 1737 1738 /** 1739 The browser window or frame that this YUI instance should operate in. 1740 1741 When running in Node.js, this property is `undefined`, since there is no 1742 `window` object. Use `global` to get a reference to the global object that will 1743 work in both browsers and Node.js. 1744 1745 @property {Window} win 1746 **/ 1747 1748 /** 1749 The browser `document` object associated with this YUI instance's `win` object. 1750 1751 When running in Node.js, this property is `undefined`, since there is no 1752 `document` object. 1753 1754 @property {Document} doc 1755 **/ 1756 1757 /** 1758 A list of modules that defines the YUI core (overrides the default list). 1759 1760 @property {Array} core 1761 @type Array 1762 @default ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3'] 1763 **/ 1764 1765 /** 1766 A list of languages to use in order of preference. 1767 1768 This list is matched against the list of available languages in modules that the 1769 YUI instance uses to determine the best possible localization of language 1770 sensitive modules. 1771 1772 Languages are represented using BCP 47 language tags, such as "en-GB" for 1773 English as used in the United Kingdom, or "zh-Hans-CN" for simplified Chinese as 1774 used in China. The list may be provided as a comma-separated string or as an 1775 array. 1776 1777 @property {String|String[]} lang 1778 **/ 1779 1780 /** 1781 Default date format. 1782 1783 @property {String} dateFormat 1784 @deprecated Use configuration in `DataType.Date.format()` instead. 1785 **/ 1786 1787 /** 1788 Default locale. 1789 1790 @property {String} locale 1791 @deprecated Use `config.lang` instead. 1792 **/ 1793 1794 /** 1795 Default generic polling interval in milliseconds. 1796 1797 @property {Number} pollInterval 1798 @default 20 1799 **/ 1800 1801 /** 1802 The number of dynamic `<script>` nodes to insert by default before automatically 1803 removing them when loading scripts. 1804 1805 This applies only to script nodes because removing the node will not make the 1806 evaluated script unavailable. Dynamic CSS nodes are not auto purged, because 1807 removing a linked style sheet will also remove the style definitions. 1808 1809 @property {Number} purgethreshold 1810 @default 20 1811 **/ 1812 1813 /** 1814 Delay in milliseconds to wait after a window `resize` event before firing the 1815 event. If another `resize` event occurs before this delay has elapsed, the 1816 delay will start over to ensure that `resize` events are throttled. 1817 1818 @property {Number} windowResizeDelay 1819 @default 40 1820 **/ 1821 1822 /** 1823 Base directory for dynamic loading. 1824 1825 @property {String} base 1826 **/ 1827 1828 /** 1829 Base URL for a dynamic combo handler. This will be used to make combo-handled 1830 module requests if `combine` is set to `true. 1831 1832 @property {String} comboBase 1833 @default "http://yui.yahooapis.com/combo?" 1834 **/ 1835 1836 /** 1837 Root path to prepend to each module path when creating a combo-handled request. 1838 1839 This is updated for each YUI release to point to a specific version of the 1840 library; for example: "3.8.0/build/". 1841 1842 @property {String} root 1843 **/ 1844 1845 /** 1846 Filter to apply to module urls. This filter will modify the default path for all 1847 modules. 1848 1849 The default path for the YUI library is the minified version of the files (e.g., 1850 event-min.js). The filter property can be a predefined filter or a custom 1851 filter. The valid predefined filters are: 1852 1853 - **debug**: Loads debug versions of modules (e.g., event-debug.js). 1854 - **raw**: Loads raw, non-minified versions of modules without debug logging 1855 (e.g., event.js). 1856 1857 You can also define a custom filter, which must be an object literal containing 1858 a search regular expression and a replacement string: 1859 1860 myFilter: { 1861 searchExp : "-min\\.js", 1862 replaceStr: "-debug.js" 1863 } 1864 1865 @property {Object|String} filter 1866 **/ 1867 1868 /** 1869 Skin configuration and customizations. 1870 1871 @property {Object} skin 1872 @param {String} [skin.defaultSkin='sam'] Default skin name. This skin will be 1873 applied automatically to skinnable components if not overridden by a 1874 component-specific skin name. 1875 @param {String} [skin.base='assets/skins/'] Default base path for a skin, 1876 relative to Loader's `base` path. 1877 @param {Object} [skin.overrides] Component-specific skin name overrides. Specify 1878 a component name as the key and, as the value, a string or array of strings 1879 for a skin or skins that should be loaded for that component instead of the 1880 `defaultSkin`. 1881 **/ 1882 1883 /** 1884 Hash of per-component filter specifications. If specified for a given component, 1885 this overrides the global `filter` config. 1886 1887 @example 1888 YUI({ 1889 modules: { 1890 'foo': './foo.js', 1891 'bar': './bar.js', 1892 'baz': './baz.js' 1893 }, 1894 filters: { 1895 'foo': { 1896 searchExp: '.js', 1897 replaceStr: '-coverage.js' 1898 } 1899 } 1900 }).use('foo', 'bar', 'baz', function (Y) { 1901 // foo-coverage.js is loaded 1902 // bar.js is loaded 1903 // baz.js is loaded 1904 }); 1905 1906 @property {Object} filters 1907 **/ 1908 1909 /** 1910 If `true`, YUI will use a combo handler to load multiple modules in as few 1911 requests as possible. 1912 1913 The YUI CDN (which YUI uses by default) supports combo handling, but other 1914 servers may not. If the server from which you're loading YUI does not support 1915 combo handling, set this to `false`. 1916 1917 Providing a value for the `base` config property will cause `combine` to default 1918 to `false` instead of `true`. 1919 1920 @property {Boolean} combine 1921 @default true 1922 */ 1923 1924 /** 1925 Array of module names that should never be dynamically loaded. 1926 1927 @property {String[]} ignore 1928 **/ 1929 1930 /** 1931 Array of module names that should always be loaded when required, even if 1932 already present on the page. 1933 1934 @property {String[]} force 1935 **/ 1936 1937 /** 1938 DOM element or id that should be used as the insertion point for dynamically 1939 added `<script>` and `<link>` nodes. 1940 1941 @property {HTMLElement|String} insertBefore 1942 **/ 1943 1944 /** 1945 Object hash containing attributes to add to dynamically added `<script>` nodes. 1946 1947 @property {Object} jsAttributes 1948 **/ 1949 1950 /** 1951 Object hash containing attributes to add to dynamically added `<link>` nodes. 1952 1953 @property {Object} cssAttributes 1954 **/ 1955 1956 /** 1957 Timeout in milliseconds before a dynamic JS or CSS request will be considered a 1958 failure. If not set, no timeout will be enforced. 1959 1960 @property {Number} timeout 1961 **/ 1962 1963 /** 1964 A hash of module definitions to add to the list of available YUI modules. These 1965 modules can then be dynamically loaded via the `use()` method. 1966 1967 This is a hash in which keys are module names and values are objects containing 1968 module metadata. 1969 1970 See `Loader.addModule()` for the supported module metadata fields. Also see 1971 `groups`, which provides a way to configure the base and combo spec for a set of 1972 modules. 1973 1974 @example 1975 1976 modules: { 1977 mymod1: { 1978 requires: ['node'], 1979 fullpath: '/mymod1/mymod1.js' 1980 }, 1981 1982 mymod2: { 1983 requires: ['mymod1'], 1984 fullpath: '/mymod2/mymod2.js' 1985 }, 1986 1987 mymod3: '/js/mymod3.js', 1988 mycssmod: '/css/mycssmod.css' 1989 } 1990 1991 @property {Object} modules 1992 **/ 1993 1994 /** 1995 Aliases are dynamic groups of modules that can be used as shortcuts. 1996 1997 @example 1998 1999 YUI({ 2000 aliases: { 2001 davglass: [ 'node', 'yql', 'dd' ], 2002 mine: [ 'davglass', 'autocomplete'] 2003 } 2004 }).use('mine', function (Y) { 2005 // Node, YQL, DD & AutoComplete available here. 2006 }); 2007 2008 @property {Object} aliases 2009 **/ 2010 2011 /** 2012 A hash of module group definitions. 2013 2014 For each group you can specify a list of modules and the base path and 2015 combo spec to use when dynamically loading the modules. 2016 2017 @example 2018 2019 groups: { 2020 yui2: { 2021 // specify whether or not this group has a combo service 2022 combine: true, 2023 2024 // The comboSeperator to use with this group's combo handler 2025 comboSep: ';', 2026 2027 // The maxURLLength for this server 2028 maxURLLength: 500, 2029 2030 // the base path for non-combo paths 2031 base: 'http://yui.yahooapis.com/2.8.0r4/build/', 2032 2033 // the path to the combo service 2034 comboBase: 'http://yui.yahooapis.com/combo?', 2035 2036 // a fragment to prepend to the path attribute when 2037 // when building combo urls 2038 root: '2.8.0r4/build/', 2039 2040 // the module definitions 2041 modules: { 2042 yui2_yde: { 2043 path: "yahoo-dom-event/yahoo-dom-event.js" 2044 }, 2045 yui2_anim: { 2046 path: "animation/animation.js", 2047 requires: ['yui2_yde'] 2048 } 2049 } 2050 } 2051 } 2052 2053 @property {Object} groups 2054 **/ 2055 2056 /** 2057 Path to the Loader JS file, relative to the `base` path. 2058 2059 This is used to dynamically bootstrap the Loader when it's needed and isn't yet 2060 available. 2061 2062 @property {String} loaderPath 2063 @default "loader/loader-min.js" 2064 **/ 2065 2066 /** 2067 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to 2068 `false` to prevent YUI from loading any CSS, or set it to the string `"force"` 2069 to force CSS dependencies to be loaded even if their associated JS modules are 2070 already loaded. 2071 2072 @property {Boolean|String} fetchCSS 2073 @default true 2074 **/ 2075 2076 /** 2077 Default gallery version used to build gallery module urls. 2078 2079 @property {String} gallery 2080 @since 3.1.0 2081 **/ 2082 2083 /** 2084 Default YUI 2 version used to build YUI 2 module urls. 2085 2086 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the 2087 `2in3` config for pulling different revisions of the wrapped YUI 2 modules. 2088 2089 @property {String} yui2 2090 @default "2.9.0" 2091 @since 3.1.0 2092 **/ 2093 2094 /** 2095 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3. 2096 2097 @property {String} 2in3 2098 @default "4" 2099 @since 3.1.0 2100 **/ 2101 2102 /** 2103 Alternate console log function that should be used in environments without a 2104 supported native console. This function is executed with the YUI instance as its 2105 `this` object. 2106 2107 @property {Function} logFn 2108 @since 3.1.0 2109 **/ 2110 2111 /** 2112 The minimum log level to log messages for. Log levels are defined 2113 incrementally. Messages greater than or equal to the level specified will 2114 be shown. All others will be discarded. The order of log levels in 2115 increasing priority is: 2116 2117 debug 2118 info 2119 warn 2120 error 2121 2122 @property {String} logLevel 2123 @default 'debug' 2124 @since 3.10.0 2125 **/ 2126 2127 /** 2128 Callback to execute when `Y.error()` is called. It receives the error message 2129 and a JavaScript error object if one was provided. 2130 2131 This function is executed with the YUI instance as its `this` object. 2132 2133 Returning `true` from this function will prevent an exception from being thrown. 2134 2135 @property {Function} errorFn 2136 @param {String} errorFn.msg Error message 2137 @param {Object} [errorFn.err] Error object (if one was provided). 2138 @since 3.2.0 2139 **/ 2140 2141 /** 2142 A callback to execute when Loader fails to load one or more resources. 2143 2144 This could be because of a script load failure. It could also be because a 2145 module fails to register itself when the `requireRegistration` config is `true`. 2146 2147 If this function is defined, the `use()` callback will only be called when the 2148 loader succeeds. Otherwise, `use()` will always executes unless there was a 2149 JavaScript error when attaching a module. 2150 2151 @property {Function} loadErrorFn 2152 @since 3.3.0 2153 **/ 2154 2155 /** 2156 If `true`, Loader will expect all loaded scripts to be first-class YUI modules 2157 that register themselves with the YUI global, and will trigger a failure if a 2158 loaded script does not register a YUI module. 2159 2160 @property {Boolean} requireRegistration 2161 @default false 2162 @since 3.3.0 2163 **/ 2164 2165 /** 2166 Cache serviced use() requests. 2167 2168 @property {Boolean} cacheUse 2169 @default true 2170 @since 3.3.0 2171 @deprecated No longer used. 2172 **/ 2173 2174 /** 2175 Whether or not YUI should use native ES5 functionality when available for 2176 features like `Y.Array.each()`, `Y.Object()`, etc. 2177 2178 When `false`, YUI will always use its own fallback implementations instead of 2179 relying on ES5 functionality, even when ES5 functionality is available. 2180 2181 @property {Boolean} useNativeES5 2182 @default true 2183 @since 3.5.0 2184 **/ 2185 2186 /** 2187 * Leverage native JSON stringify if the browser has a native 2188 * implementation. In general, this is a good idea. See the Known Issues 2189 * section in the JSON user guide for caveats. The default value is true 2190 * for browsers with native JSON support. 2191 * 2192 * @property useNativeJSONStringify 2193 * @type Boolean 2194 * @default true 2195 * @since 3.8.0 2196 */ 2197 2198 /** 2199 * Leverage native JSON parse if the browser has a native implementation. 2200 * In general, this is a good idea. See the Known Issues section in the 2201 * JSON user guide for caveats. The default value is true for browsers with 2202 * native JSON support. 2203 * 2204 * @property useNativeJSONParse 2205 * @type Boolean 2206 * @default true 2207 * @since 3.8.0 2208 */ 2209 2210 /** 2211 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`) 2212 2213 @property {Object|String} delayUntil 2214 @since 3.6.0 2215 @example 2216 2217 You can use `load` or `domready` strings by default: 2218 2219 YUI({ 2220 delayUntil: 'domready' 2221 }, function (Y) { 2222 // This will not execute until 'domeready' occurs. 2223 }); 2224 2225 Or you can delay until a node is available (with `available` or `contentready`): 2226 2227 YUI({ 2228 delayUntil: { 2229 event: 'available', 2230 args : '#foo' 2231 } 2232 }, function (Y) { 2233 // This will not execute until a node matching the selector "#foo" is 2234 // available in the DOM. 2235 }); 2236 2237 **/ 2238 YUI.add('yui-base', function (Y, NAME) { 2239 2240 /* 2241 * YUI stub 2242 * @module yui 2243 * @submodule yui-base 2244 */ 2245 /** 2246 * The YUI module contains the components required for building the YUI 2247 * seed file. This includes the script loading mechanism, a simple queue, 2248 * and the core utilities for the library. 2249 * @module yui 2250 * @submodule yui-base 2251 */ 2252 2253 /** 2254 * Provides core language utilites and extensions used throughout YUI. 2255 * 2256 * @class Lang 2257 * @static 2258 */ 2259 2260 var L = Y.Lang || (Y.Lang = {}), 2261 2262 STRING_PROTO = String.prototype, 2263 TOSTRING = Object.prototype.toString, 2264 2265 TYPES = { 2266 'undefined' : 'undefined', 2267 'number' : 'number', 2268 'boolean' : 'boolean', 2269 'string' : 'string', 2270 '[object Function]': 'function', 2271 '[object RegExp]' : 'regexp', 2272 '[object Array]' : 'array', 2273 '[object Date]' : 'date', 2274 '[object Error]' : 'error' 2275 }, 2276 2277 SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g, 2278 2279 WHITESPACE = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF", 2280 WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+", 2281 TRIM_LEFT_REGEX = new RegExp("^" + WHITESPACE_CLASS), 2282 TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"), 2283 TRIMREGEX = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"), 2284 2285 NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i; 2286 2287 // -- Protected Methods -------------------------------------------------------- 2288 2289 /** 2290 Returns `true` if the given function appears to be implemented in native code, 2291 `false` otherwise. Will always return `false` -- even in ES5-capable browsers -- 2292 if the `useNativeES5` YUI config option is set to `false`. 2293 2294 This isn't guaranteed to be 100% accurate and won't work for anything other than 2295 functions, but it can be useful for determining whether a function like 2296 `Array.prototype.forEach` is native or a JS shim provided by another library. 2297 2298 There's a great article by @kangax discussing certain flaws with this technique: 2299 <http://perfectionkills.com/detecting-built-in-host-methods/> 2300 2301 While his points are valid, it's still possible to benefit from this function 2302 as long as it's used carefully and sparingly, and in such a way that false 2303 negatives have minimal consequences. It's used internally to avoid using 2304 potentially broken non-native ES5 shims that have been added to the page by 2305 other libraries. 2306 2307 @method _isNative 2308 @param {Function} fn Function to test. 2309 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise. 2310 @static 2311 @protected 2312 @since 3.5.0 2313 **/ 2314 L._isNative = function (fn) { 2315 return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn)); 2316 }; 2317 2318 // -- Public Methods ----------------------------------------------------------- 2319 2320 /** 2321 * Determines whether or not the provided item is an array. 2322 * 2323 * Returns `false` for array-like collections such as the function `arguments` 2324 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to 2325 * test for an array-like collection. 2326 * 2327 * @method isArray 2328 * @param o The object to test. 2329 * @return {boolean} true if o is an array. 2330 * @static 2331 */ 2332 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) { 2333 return L.type(o) === 'array'; 2334 }; 2335 2336 /** 2337 * Determines whether or not the provided item is a boolean. 2338 * @method isBoolean 2339 * @static 2340 * @param o The object to test. 2341 * @return {boolean} true if o is a boolean. 2342 */ 2343 L.isBoolean = function(o) { 2344 return typeof o === 'boolean'; 2345 }; 2346 2347 /** 2348 * Determines whether or not the supplied item is a date instance. 2349 * @method isDate 2350 * @static 2351 * @param o The object to test. 2352 * @return {boolean} true if o is a date. 2353 */ 2354 L.isDate = function(o) { 2355 return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o); 2356 }; 2357 2358 /** 2359 * <p> 2360 * Determines whether or not the provided item is a function. 2361 * Note: Internet Explorer thinks certain functions are objects: 2362 * </p> 2363 * 2364 * <pre> 2365 * var obj = document.createElement("object"); 2366 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE 2367 * 2368 * var input = document.createElement("input"); // append to body 2369 * Y.Lang.isFunction(input.focus) // reports false in IE 2370 * </pre> 2371 * 2372 * <p> 2373 * You will have to implement additional tests if these functions 2374 * matter to you. 2375 * </p> 2376 * 2377 * @method isFunction 2378 * @static 2379 * @param o The object to test. 2380 * @return {boolean} true if o is a function. 2381 */ 2382 L.isFunction = function(o) { 2383 return L.type(o) === 'function'; 2384 }; 2385 2386 /** 2387 * Determines whether or not the provided item is null. 2388 * @method isNull 2389 * @static 2390 * @param o The object to test. 2391 * @return {boolean} true if o is null. 2392 */ 2393 L.isNull = function(o) { 2394 return o === null; 2395 }; 2396 2397 /** 2398 * Determines whether or not the provided item is a legal number. 2399 * @method isNumber 2400 * @static 2401 * @param o The object to test. 2402 * @return {boolean} true if o is a number. 2403 */ 2404 L.isNumber = function(o) { 2405 return typeof o === 'number' && isFinite(o); 2406 }; 2407 2408 /** 2409 * Determines whether or not the provided item is of type object 2410 * or function. Note that arrays are also objects, so 2411 * <code>Y.Lang.isObject([]) === true</code>. 2412 * @method isObject 2413 * @static 2414 * @param o The object to test. 2415 * @param failfn {boolean} fail if the input is a function. 2416 * @return {boolean} true if o is an object. 2417 * @see isPlainObject 2418 */ 2419 L.isObject = function(o, failfn) { 2420 var t = typeof o; 2421 return (o && (t === 'object' || 2422 (!failfn && (t === 'function' || L.isFunction(o))))) || false; 2423 }; 2424 2425 /** 2426 * Determines whether or not the provided value is a regexp. 2427 * @method isRegExp 2428 * @static 2429 * @param value The value or object to test. 2430 * @return {boolean} true if value is a regexp. 2431 */ 2432 L.isRegExp = function(value) { 2433 return L.type(value) === 'regexp'; 2434 }; 2435 2436 /** 2437 * Determines whether or not the provided item is a string. 2438 * @method isString 2439 * @static 2440 * @param o The object to test. 2441 * @return {boolean} true if o is a string. 2442 */ 2443 L.isString = function(o) { 2444 return typeof o === 'string'; 2445 }; 2446 2447 /** 2448 * Determines whether or not the provided item is undefined. 2449 * @method isUndefined 2450 * @static 2451 * @param o The object to test. 2452 * @return {boolean} true if o is undefined. 2453 */ 2454 L.isUndefined = function(o) { 2455 return typeof o === 'undefined'; 2456 }; 2457 2458 /** 2459 * A convenience method for detecting a legitimate non-null value. 2460 * Returns false for null/undefined/NaN, true for other values, 2461 * including 0/false/'' 2462 * @method isValue 2463 * @static 2464 * @param o The item to test. 2465 * @return {boolean} true if it is not null/undefined/NaN || false. 2466 */ 2467 L.isValue = function(o) { 2468 var t = L.type(o); 2469 2470 switch (t) { 2471 case 'number': 2472 return isFinite(o); 2473 2474 case 'null': // fallthru 2475 case 'undefined': 2476 return false; 2477 2478 default: 2479 return !!t; 2480 } 2481 }; 2482 2483 /** 2484 * Returns the current time in milliseconds. 2485 * 2486 * @method now 2487 * @return {Number} Current time in milliseconds. 2488 * @static 2489 * @since 3.3.0 2490 */ 2491 L.now = Date.now || function () { 2492 return new Date().getTime(); 2493 }; 2494 2495 /** 2496 * Performs `{placeholder}` substitution on a string. The object passed as the 2497 * second parameter provides values to replace the `{placeholder}`s. 2498 * `{placeholder}` token names must match property names of the object. For example, 2499 * 2500 *`var greeting = Y.Lang.sub("Hello, {who}!", { who: "World" });` 2501 * 2502 * `{placeholder}` tokens that are undefined on the object map will be left 2503 * in tact (leaving unsightly `{placeholder}`'s in the output string). 2504 * 2505 * @method sub 2506 * @param {string} s String to be modified. 2507 * @param {object} o Object containing replacement values. 2508 * @return {string} the substitute result. 2509 * @static 2510 * @since 3.2.0 2511 */ 2512 L.sub = function(s, o) { 2513 return s.replace ? s.replace(SUBREGEX, function (match, key) { 2514 return L.isUndefined(o[key]) ? match : o[key]; 2515 }) : s; 2516 }; 2517 2518 /** 2519 * Returns a string without any leading or trailing whitespace. If 2520 * the input is not a string, the input will be returned untouched. 2521 * @method trim 2522 * @static 2523 * @param s {string} the string to trim. 2524 * @return {string} the trimmed string. 2525 */ 2526 L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) { 2527 return s && s.trim ? s.trim() : s; 2528 } : function (s) { 2529 try { 2530 return s.replace(TRIMREGEX, ''); 2531 } catch (e) { 2532 return s; 2533 } 2534 }; 2535 2536 /** 2537 * Returns a string without any leading whitespace. 2538 * @method trimLeft 2539 * @static 2540 * @param s {string} the string to trim. 2541 * @return {string} the trimmed string. 2542 */ 2543 L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) { 2544 return s.trimLeft(); 2545 } : function (s) { 2546 return s.replace(TRIM_LEFT_REGEX, ''); 2547 }; 2548 2549 /** 2550 * Returns a string without any trailing whitespace. 2551 * @method trimRight 2552 * @static 2553 * @param s {string} the string to trim. 2554 * @return {string} the trimmed string. 2555 */ 2556 L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) { 2557 return s.trimRight(); 2558 } : function (s) { 2559 return s.replace(TRIM_RIGHT_REGEX, ''); 2560 }; 2561 2562 /** 2563 Returns one of the following strings, representing the type of the item passed 2564 in: 2565 2566 * "array" 2567 * "boolean" 2568 * "date" 2569 * "error" 2570 * "function" 2571 * "null" 2572 * "number" 2573 * "object" 2574 * "regexp" 2575 * "string" 2576 * "undefined" 2577 2578 Known issues: 2579 2580 * `typeof HTMLElementCollection` returns function in Safari, but 2581 `Y.Lang.type()` reports "object", which could be a good thing -- 2582 but it actually caused the logic in <code>Y.Lang.isObject</code> to fail. 2583 2584 @method type 2585 @param o the item to test. 2586 @return {string} the detected type. 2587 @static 2588 **/ 2589 L.type = function(o) { 2590 return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null'); 2591 }; 2592 /** 2593 @module yui 2594 @submodule yui-base 2595 */ 2596 2597 var Lang = Y.Lang, 2598 Native = Array.prototype, 2599 2600 hasOwn = Object.prototype.hasOwnProperty; 2601 2602 /** 2603 Provides utility methods for working with arrays. Additional array helpers can 2604 be found in the `collection` and `array-extras` modules. 2605 2606 `Y.Array(thing)` returns a native array created from _thing_. Depending on 2607 _thing_'s type, one of the following will happen: 2608 2609 * Arrays are returned unmodified unless a non-zero _startIndex_ is 2610 specified. 2611 * Array-like collections (see `Array.test()`) are converted to arrays. 2612 * For everything else, a new array is created with _thing_ as the sole 2613 item. 2614 2615 Note: elements that are also collections, such as `<form>` and `<select>` 2616 elements, are not automatically converted to arrays. To force a conversion, 2617 pass `true` as the value of the _force_ parameter. 2618 2619 @class Array 2620 @constructor 2621 @param {Any} thing The thing to arrayify. 2622 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like 2623 collection, a subset of items starting at the specified index will be 2624 returned. 2625 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an 2626 array-like collection no matter what. 2627 @return {Array} A native array created from _thing_, according to the rules 2628 described above. 2629 **/ 2630 function YArray(thing, startIndex, force) { 2631 var len, result; 2632 2633 /*jshint expr: true*/ 2634 startIndex || (startIndex = 0); 2635 2636 if (force || YArray.test(thing)) { 2637 // IE throws when trying to slice HTMLElement collections. 2638 try { 2639 return Native.slice.call(thing, startIndex); 2640 } catch (ex) { 2641 result = []; 2642 2643 for (len = thing.length; startIndex < len; ++startIndex) { 2644 result.push(thing[startIndex]); 2645 } 2646 2647 return result; 2648 } 2649 } 2650 2651 return [thing]; 2652 } 2653 2654 Y.Array = YArray; 2655 2656 /** 2657 Dedupes an array of strings, returning an array that's guaranteed to contain 2658 only one copy of a given string. 2659 2660 This method differs from `Array.unique()` in that it's optimized for use only 2661 with arrays consisting entirely of strings or entirely of numbers, whereas 2662 `unique` may be used with other value types (but is slower). 2663 2664 Using `dedupe()` with values other than strings or numbers, or with arrays 2665 containing a mix of strings and numbers, may result in unexpected behavior. 2666 2667 @method dedupe 2668 @param {String[]|Number[]} array Array of strings or numbers to dedupe. 2669 @return {Array} Copy of _array_ containing no duplicate values. 2670 @static 2671 @since 3.4.0 2672 **/ 2673 YArray.dedupe = Lang._isNative(Object.create) ? function (array) { 2674 var hash = Object.create(null), 2675 results = [], 2676 i, item, len; 2677 2678 for (i = 0, len = array.length; i < len; ++i) { 2679 item = array[i]; 2680 2681 if (!hash[item]) { 2682 hash[item] = 1; 2683 results.push(item); 2684 } 2685 } 2686 2687 return results; 2688 } : function (array) { 2689 var hash = {}, 2690 results = [], 2691 i, item, len; 2692 2693 for (i = 0, len = array.length; i < len; ++i) { 2694 item = array[i]; 2695 2696 if (!hasOwn.call(hash, item)) { 2697 hash[item] = 1; 2698 results.push(item); 2699 } 2700 } 2701 2702 return results; 2703 }; 2704 2705 /** 2706 Executes the supplied function on each item in the array. This method wraps 2707 the native ES5 `Array.forEach()` method if available. 2708 2709 @method each 2710 @param {Array} array Array to iterate. 2711 @param {Function} fn Function to execute on each item in the array. The function 2712 will receive the following arguments: 2713 @param {Any} fn.item Current array item. 2714 @param {Number} fn.index Current array index. 2715 @param {Array} fn.array Array being iterated. 2716 @param {Object} [thisObj] `this` object to use when calling _fn_. 2717 @return {YUI} The YUI instance. 2718 @static 2719 **/ 2720 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) { 2721 Native.forEach.call(array || [], fn, thisObj || Y); 2722 return Y; 2723 } : function (array, fn, thisObj) { 2724 for (var i = 0, len = (array && array.length) || 0; i < len; ++i) { 2725 if (i in array) { 2726 fn.call(thisObj || Y, array[i], i, array); 2727 } 2728 } 2729 2730 return Y; 2731 }; 2732 2733 /** 2734 Alias for `each()`. 2735 2736 @method forEach 2737 @static 2738 **/ 2739 2740 /** 2741 Returns an object using the first array as keys and the second as values. If 2742 the second array is not provided, or if it doesn't contain the same number of 2743 values as the first array, then `true` will be used in place of the missing 2744 values. 2745 2746 @example 2747 2748 Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']); 2749 // => {a: 'foo', b: 'bar', c: true} 2750 2751 @method hash 2752 @param {String[]} keys Array of strings to use as keys. 2753 @param {Array} [values] Array to use as values. 2754 @return {Object} Hash using the first array as keys and the second as values. 2755 @static 2756 **/ 2757 YArray.hash = function (keys, values) { 2758 var hash = {}, 2759 vlen = (values && values.length) || 0, 2760 i, len; 2761 2762 for (i = 0, len = keys.length; i < len; ++i) { 2763 if (i in keys) { 2764 hash[keys[i]] = vlen > i && i in values ? values[i] : true; 2765 } 2766 } 2767 2768 return hash; 2769 }; 2770 2771 /** 2772 Returns the index of the first item in the array that's equal (using a strict 2773 equality check) to the specified _value_, or `-1` if the value isn't found. 2774 2775 This method wraps the native ES5 `Array.indexOf()` method if available. 2776 2777 @method indexOf 2778 @param {Array} array Array to search. 2779 @param {Any} value Value to search for. 2780 @param {Number} [from=0] The index at which to begin the search. 2781 @return {Number} Index of the item strictly equal to _value_, or `-1` if not 2782 found. 2783 @static 2784 **/ 2785 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) { 2786 return Native.indexOf.call(array, value, from); 2787 } : function (array, value, from) { 2788 // http://es5.github.com/#x15.4.4.14 2789 var len = array.length; 2790 2791 from = +from || 0; 2792 from = (from > 0 || -1) * Math.floor(Math.abs(from)); 2793 2794 if (from < 0) { 2795 from += len; 2796 2797 if (from < 0) { 2798 from = 0; 2799 } 2800 } 2801 2802 for (; from < len; ++from) { 2803 if (from in array && array[from] === value) { 2804 return from; 2805 } 2806 } 2807 2808 return -1; 2809 }; 2810 2811 /** 2812 Numeric sort convenience function. 2813 2814 The native `Array.prototype.sort()` function converts values to strings and 2815 sorts them in lexicographic order, which is unsuitable for sorting numeric 2816 values. Provide `Array.numericSort` as a custom sort function when you want 2817 to sort values in numeric order. 2818 2819 @example 2820 2821 [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort); 2822 // => [4, 8, 15, 16, 23, 42] 2823 2824 @method numericSort 2825 @param {Number} a First value to compare. 2826 @param {Number} b Second value to compare. 2827 @return {Number} Difference between _a_ and _b_. 2828 @static 2829 **/ 2830 YArray.numericSort = function (a, b) { 2831 return a - b; 2832 }; 2833 2834 /** 2835 Executes the supplied function on each item in the array. Returning a truthy 2836 value from the function will stop the processing of remaining items. 2837 2838 @method some 2839 @param {Array} array Array to iterate over. 2840 @param {Function} fn Function to execute on each item. The function will receive 2841 the following arguments: 2842 @param {Any} fn.value Current array item. 2843 @param {Number} fn.index Current array index. 2844 @param {Array} fn.array Array being iterated over. 2845 @param {Object} [thisObj] `this` object to use when calling _fn_. 2846 @return {Boolean} `true` if the function returns a truthy value on any of the 2847 items in the array; `false` otherwise. 2848 @static 2849 **/ 2850 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) { 2851 return Native.some.call(array, fn, thisObj); 2852 } : function (array, fn, thisObj) { 2853 for (var i = 0, len = array.length; i < len; ++i) { 2854 if (i in array && fn.call(thisObj, array[i], i, array)) { 2855 return true; 2856 } 2857 } 2858 2859 return false; 2860 }; 2861 2862 /** 2863 Evaluates _obj_ to determine if it's an array, an array-like collection, or 2864 something else. This is useful when working with the function `arguments` 2865 collection and `HTMLElement` collections. 2866 2867 Note: This implementation doesn't consider elements that are also 2868 collections, such as `<form>` and `<select>`, to be array-like. 2869 2870 @method test 2871 @param {Object} obj Object to test. 2872 @return {Number} A number indicating the results of the test: 2873 2874 * 0: Neither an array nor an array-like collection. 2875 * 1: Real array. 2876 * 2: Array-like collection. 2877 2878 @static 2879 **/ 2880 YArray.test = function (obj) { 2881 var result = 0; 2882 2883 if (Lang.isArray(obj)) { 2884 result = 1; 2885 } else if (Lang.isObject(obj)) { 2886 try { 2887 // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here), 2888 // or functions without apply/call (Safari 2889 // HTMLElementCollection bug). 2890 if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) { 2891 result = 2; 2892 } 2893 } catch (ex) {} 2894 } 2895 2896 return result; 2897 }; 2898 /** 2899 * The YUI module contains the components required for building the YUI 2900 * seed file. This includes the script loading mechanism, a simple queue, 2901 * and the core utilities for the library. 2902 * @module yui 2903 * @submodule yui-base 2904 */ 2905 2906 /** 2907 * A simple FIFO queue. Items are added to the Queue with add(1..n items) and 2908 * removed using next(). 2909 * 2910 * @class Queue 2911 * @constructor 2912 * @param {MIXED} item* 0..n items to seed the queue. 2913 */ 2914 function Queue() { 2915 this._init(); 2916 this.add.apply(this, arguments); 2917 } 2918 2919 Queue.prototype = { 2920 /** 2921 * Initialize the queue 2922 * 2923 * @method _init 2924 * @protected 2925 */ 2926 _init: function() { 2927 /** 2928 * The collection of enqueued items 2929 * 2930 * @property _q 2931 * @type Array 2932 * @protected 2933 */ 2934 this._q = []; 2935 }, 2936 2937 /** 2938 * Get the next item in the queue. FIFO support 2939 * 2940 * @method next 2941 * @return {MIXED} the next item in the queue. 2942 */ 2943 next: function() { 2944 return this._q.shift(); 2945 }, 2946 2947 /** 2948 * Get the last in the queue. LIFO support. 2949 * 2950 * @method last 2951 * @return {MIXED} the last item in the queue. 2952 */ 2953 last: function() { 2954 return this._q.pop(); 2955 }, 2956 2957 /** 2958 * Add 0..n items to the end of the queue. 2959 * 2960 * @method add 2961 * @param {MIXED} item* 0..n items. 2962 * @return {object} this queue. 2963 */ 2964 add: function() { 2965 this._q.push.apply(this._q, arguments); 2966 2967 return this; 2968 }, 2969 2970 /** 2971 * Returns the current number of queued items. 2972 * 2973 * @method size 2974 * @return {Number} The size. 2975 */ 2976 size: function() { 2977 return this._q.length; 2978 } 2979 }; 2980 2981 Y.Queue = Queue; 2982 2983 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue(); 2984 2985 /** 2986 The YUI module contains the components required for building the YUI seed file. 2987 This includes the script loading mechanism, a simple queue, and the core 2988 utilities for the library. 2989 2990 @module yui 2991 @submodule yui-base 2992 **/ 2993 2994 var CACHED_DELIMITER = '__', 2995 2996 hasOwn = Object.prototype.hasOwnProperty, 2997 isObject = Y.Lang.isObject; 2998 2999 /** 3000 Returns a wrapper for a function which caches the return value of that function, 3001 keyed off of the combined string representation of the argument values provided 3002 when the wrapper is called. 3003 3004 Calling this function again with the same arguments will return the cached value 3005 rather than executing the wrapped function. 3006 3007 Note that since the cache is keyed off of the string representation of arguments 3008 passed to the wrapper function, arguments that aren't strings and don't provide 3009 a meaningful `toString()` method may result in unexpected caching behavior. For 3010 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the 3011 string `[object Object]` when used as a cache key. 3012 3013 @method cached 3014 @param {Function} source The function to memoize. 3015 @param {Object} [cache={}] Object in which to store cached values. You may seed 3016 this object with pre-existing cached values if desired. 3017 @param {any} [refetch] If supplied, this value is compared with the cached value 3018 using a `==` comparison. If the values are equal, the wrapped function is 3019 executed again even though a cached value exists. 3020 @return {Function} Wrapped function. 3021 @for YUI 3022 **/ 3023 Y.cached = function (source, cache, refetch) { 3024 /*jshint expr: true*/ 3025 cache || (cache = {}); 3026 3027 return function (arg) { 3028 var key = arguments.length > 1 ? 3029 Array.prototype.join.call(arguments, CACHED_DELIMITER) : 3030 String(arg); 3031 3032 /*jshint eqeqeq: false*/ 3033 if (!(key in cache) || (refetch && cache[key] == refetch)) { 3034 cache[key] = source.apply(source, arguments); 3035 } 3036 3037 return cache[key]; 3038 }; 3039 }; 3040 3041 /** 3042 Returns the `location` object from the window/frame in which this YUI instance 3043 operates, or `undefined` when executing in a non-browser environment 3044 (e.g. Node.js). 3045 3046 It is _not_ recommended to hold references to the `window.location` object 3047 outside of the scope of a function in which its properties are being accessed or 3048 its methods are being called. This is because of a nasty bug/issue that exists 3049 in both Safari and MobileSafari browsers: 3050 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679). 3051 3052 @method getLocation 3053 @return {location} The `location` object from the window/frame in which this YUI 3054 instance operates. 3055 @since 3.5.0 3056 **/ 3057 Y.getLocation = function () { 3058 // It is safer to look this up every time because yui-base is attached to a 3059 // YUI instance before a user's config is applied; i.e. `Y.config.win` does 3060 // not point the correct window object when this file is loaded. 3061 var win = Y.config.win; 3062 3063 // It is not safe to hold a reference to the `location` object outside the 3064 // scope in which it is being used. The WebKit engine used in Safari and 3065 // MobileSafari will "disconnect" the `location` object from the `window` 3066 // when a page is restored from back/forward history cache. 3067 return win && win.location; 3068 }; 3069 3070 /** 3071 Returns a new object containing all of the properties of all the supplied 3072 objects. The properties from later objects will overwrite those in earlier 3073 objects. 3074 3075 Passing in a single object will create a shallow copy of it. For a deep copy, 3076 use `clone()`. 3077 3078 @method merge 3079 @param {Object} objects* One or more objects to merge. 3080 @return {Object} A new merged object. 3081 **/ 3082 Y.merge = function () { 3083 var i = 0, 3084 len = arguments.length, 3085 result = {}, 3086 key, 3087 obj; 3088 3089 for (; i < len; ++i) { 3090 obj = arguments[i]; 3091 3092 for (key in obj) { 3093 if (hasOwn.call(obj, key)) { 3094 result[key] = obj[key]; 3095 } 3096 } 3097 } 3098 3099 return result; 3100 }; 3101 3102 /** 3103 Mixes _supplier_'s properties into _receiver_. 3104 3105 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or 3106 shadowed unless the _overwrite_ parameter is `true`, and will not be merged 3107 unless the _merge_ parameter is `true`. 3108 3109 In the default mode (0), only properties the supplier owns are copied (prototype 3110 properties are not copied). The following copying modes are available: 3111 3112 * `0`: _Default_. Object to object. 3113 * `1`: Prototype to prototype. 3114 * `2`: Prototype to prototype and object to object. 3115 * `3`: Prototype to object. 3116 * `4`: Object to prototype. 3117 3118 @method mix 3119 @param {Function|Object} receiver The object or function to receive the mixed 3120 properties. 3121 @param {Function|Object} supplier The object or function supplying the 3122 properties to be mixed. 3123 @param {Boolean} [overwrite=false] If `true`, properties that already exist 3124 on the receiver will be overwritten with properties from the supplier. 3125 @param {String[]} [whitelist] An array of property names to copy. If 3126 specified, only the whitelisted properties will be copied, and all others 3127 will be ignored. 3128 @param {Number} [mode=0] Mix mode to use. See above for available modes. 3129 @param {Boolean} [merge=false] If `true`, objects and arrays that already 3130 exist on the receiver will have the corresponding object/array from the 3131 supplier merged into them, rather than being skipped or overwritten. When 3132 both _overwrite_ and _merge_ are `true`, _merge_ takes precedence. 3133 @return {Function|Object|YUI} The receiver, or the YUI instance if the 3134 specified receiver is falsy. 3135 **/ 3136 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) { 3137 var alwaysOverwrite, exists, from, i, key, len, to; 3138 3139 // If no supplier is given, we return the receiver. If no receiver is given, 3140 // we return Y. Returning Y doesn't make much sense to me, but it's 3141 // grandfathered in for backcompat reasons. 3142 if (!receiver || !supplier) { 3143 return receiver || Y; 3144 } 3145 3146 if (mode) { 3147 // In mode 2 (prototype to prototype and object to object), we recurse 3148 // once to do the proto to proto mix. The object to object mix will be 3149 // handled later on. 3150 if (mode === 2) { 3151 Y.mix(receiver.prototype, supplier.prototype, overwrite, 3152 whitelist, 0, merge); 3153 } 3154 3155 // Depending on which mode is specified, we may be copying from or to 3156 // the prototypes of the supplier and receiver. 3157 from = mode === 1 || mode === 3 ? supplier.prototype : supplier; 3158 to = mode === 1 || mode === 4 ? receiver.prototype : receiver; 3159 3160 // If either the supplier or receiver doesn't actually have a 3161 // prototype property, then we could end up with an undefined `from` 3162 // or `to`. If that happens, we abort and return the receiver. 3163 if (!from || !to) { 3164 return receiver; 3165 } 3166 } else { 3167 from = supplier; 3168 to = receiver; 3169 } 3170 3171 // If `overwrite` is truthy and `merge` is falsy, then we can skip a 3172 // property existence check on each iteration and save some time. 3173 alwaysOverwrite = overwrite && !merge; 3174 3175 if (whitelist) { 3176 for (i = 0, len = whitelist.length; i < len; ++i) { 3177 key = whitelist[i]; 3178 3179 // We call `Object.prototype.hasOwnProperty` instead of calling 3180 // `hasOwnProperty` on the object itself, since the object's 3181 // `hasOwnProperty` method may have been overridden or removed. 3182 // Also, some native objects don't implement a `hasOwnProperty` 3183 // method. 3184 if (!hasOwn.call(from, key)) { 3185 continue; 3186 } 3187 3188 // The `key in to` check here is (sadly) intentional for backwards 3189 // compatibility reasons. It prevents undesired shadowing of 3190 // prototype members on `to`. 3191 exists = alwaysOverwrite ? false : key in to; 3192 3193 if (merge && exists && isObject(to[key], true) 3194 && isObject(from[key], true)) { 3195 // If we're in merge mode, and the key is present on both 3196 // objects, and the value on both objects is either an object or 3197 // an array (but not a function), then we recurse to merge the 3198 // `from` value into the `to` value instead of overwriting it. 3199 // 3200 // Note: It's intentional that the whitelist isn't passed to the 3201 // recursive call here. This is legacy behavior that lots of 3202 // code still depends on. 3203 Y.mix(to[key], from[key], overwrite, null, 0, merge); 3204 } else if (overwrite || !exists) { 3205 // We're not in merge mode, so we'll only copy the `from` value 3206 // to the `to` value if we're in overwrite mode or if the 3207 // current key doesn't exist on the `to` object. 3208 to[key] = from[key]; 3209 } 3210 } 3211 } else { 3212 for (key in from) { 3213 // The code duplication here is for runtime performance reasons. 3214 // Combining whitelist and non-whitelist operations into a single 3215 // loop or breaking the shared logic out into a function both result 3216 // in worse performance, and Y.mix is critical enough that the byte 3217 // tradeoff is worth it. 3218 if (!hasOwn.call(from, key)) { 3219 continue; 3220 } 3221 3222 // The `key in to` check here is (sadly) intentional for backwards 3223 // compatibility reasons. It prevents undesired shadowing of 3224 // prototype members on `to`. 3225 exists = alwaysOverwrite ? false : key in to; 3226 3227 if (merge && exists && isObject(to[key], true) 3228 && isObject(from[key], true)) { 3229 Y.mix(to[key], from[key], overwrite, null, 0, merge); 3230 } else if (overwrite || !exists) { 3231 to[key] = from[key]; 3232 } 3233 } 3234 3235 // If this is an IE browser with the JScript enumeration bug, force 3236 // enumeration of the buggy properties by making a recursive call with 3237 // the buggy properties as the whitelist. 3238 if (Y.Object._hasEnumBug) { 3239 Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge); 3240 } 3241 } 3242 3243 return receiver; 3244 }; 3245 /** 3246 * The YUI module contains the components required for building the YUI 3247 * seed file. This includes the script loading mechanism, a simple queue, 3248 * and the core utilities for the library. 3249 * @module yui 3250 * @submodule yui-base 3251 */ 3252 3253 /** 3254 * Adds utilities to the YUI instance for working with objects. 3255 * 3256 * @class Object 3257 */ 3258 3259 var Lang = Y.Lang, 3260 hasOwn = Object.prototype.hasOwnProperty, 3261 3262 UNDEFINED, // <-- Note the comma. We're still declaring vars. 3263 3264 /** 3265 * Returns a new object that uses _obj_ as its prototype. This method wraps the 3266 * native ES5 `Object.create()` method if available, but doesn't currently 3267 * pass through `Object.create()`'s second argument (properties) in order to 3268 * ensure compatibility with older browsers. 3269 * 3270 * @method () 3271 * @param {Object} obj Prototype object. 3272 * @return {Object} New object using _obj_ as its prototype. 3273 * @static 3274 */ 3275 O = Y.Object = Lang._isNative(Object.create) ? function (obj) { 3276 // We currently wrap the native Object.create instead of simply aliasing it 3277 // to ensure consistency with our fallback shim, which currently doesn't 3278 // support Object.create()'s second argument (properties). Once we have a 3279 // safe fallback for the properties arg, we can stop wrapping 3280 // Object.create(). 3281 return Object.create(obj); 3282 } : (function () { 3283 // Reusable constructor function for the Object.create() shim. 3284 function F() {} 3285 3286 // The actual shim. 3287 return function (obj) { 3288 F.prototype = obj; 3289 return new F(); 3290 }; 3291 }()), 3292 3293 /** 3294 * Property names that IE doesn't enumerate in for..in loops, even when they 3295 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to 3296 * manually enumerate these properties. 3297 * 3298 * @property _forceEnum 3299 * @type String[] 3300 * @protected 3301 * @static 3302 */ 3303 forceEnum = O._forceEnum = [ 3304 'hasOwnProperty', 3305 'isPrototypeOf', 3306 'propertyIsEnumerable', 3307 'toString', 3308 'toLocaleString', 3309 'valueOf' 3310 ], 3311 3312 /** 3313 * `true` if this browser has the JScript enumeration bug that prevents 3314 * enumeration of the properties named in the `_forceEnum` array, `false` 3315 * otherwise. 3316 * 3317 * See: 3318 * - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug> 3319 * - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation> 3320 * 3321 * @property _hasEnumBug 3322 * @type Boolean 3323 * @protected 3324 * @static 3325 */ 3326 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'), 3327 3328 /** 3329 * `true` if this browser incorrectly considers the `prototype` property of 3330 * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x. 3331 * 3332 * @property _hasProtoEnumBug 3333 * @type Boolean 3334 * @protected 3335 * @static 3336 */ 3337 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'), 3338 3339 /** 3340 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or 3341 * exists only on _obj_'s prototype. This is essentially a safer version of 3342 * `obj.hasOwnProperty()`. 3343 * 3344 * @method owns 3345 * @param {Object} obj Object to test. 3346 * @param {String} key Property name to look for. 3347 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise. 3348 * @static 3349 */ 3350 owns = O.owns = function (obj, key) { 3351 return !!obj && hasOwn.call(obj, key); 3352 }; // <-- End of var declarations. 3353 3354 /** 3355 * Alias for `owns()`. 3356 * 3357 * @method hasKey 3358 * @param {Object} obj Object to test. 3359 * @param {String} key Property name to look for. 3360 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise. 3361 * @static 3362 */ 3363 O.hasKey = owns; 3364 3365 /** 3366 * Returns an array containing the object's enumerable keys. Does not include 3367 * prototype keys or non-enumerable keys. 3368 * 3369 * Note that keys are returned in enumeration order (that is, in the same order 3370 * that they would be enumerated by a `for-in` loop), which may not be the same 3371 * as the order in which they were defined. 3372 * 3373 * This method is an alias for the native ES5 `Object.keys()` method if 3374 * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of 3375 * `Object.keys()` have an inconsistency as they consider `prototype` to be 3376 * enumerable, so a non-native shim is used to rectify the difference. 3377 * 3378 * @example 3379 * 3380 * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'}); 3381 * // => ['a', 'b', 'c'] 3382 * 3383 * @method keys 3384 * @param {Object} obj An object. 3385 * @return {String[]} Array of keys. 3386 * @static 3387 */ 3388 O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) { 3389 if (!Lang.isObject(obj)) { 3390 throw new TypeError('Object.keys called on a non-object'); 3391 } 3392 3393 var keys = [], 3394 i, key, len; 3395 3396 if (hasProtoEnumBug && typeof obj === 'function') { 3397 for (key in obj) { 3398 if (owns(obj, key) && key !== 'prototype') { 3399 keys.push(key); 3400 } 3401 } 3402 } else { 3403 for (key in obj) { 3404 if (owns(obj, key)) { 3405 keys.push(key); 3406 } 3407 } 3408 } 3409 3410 if (hasEnumBug) { 3411 for (i = 0, len = forceEnum.length; i < len; ++i) { 3412 key = forceEnum[i]; 3413 3414 if (owns(obj, key)) { 3415 keys.push(key); 3416 } 3417 } 3418 } 3419 3420 return keys; 3421 }; 3422 3423 /** 3424 * Returns an array containing the values of the object's enumerable keys. 3425 * 3426 * Note that values are returned in enumeration order (that is, in the same 3427 * order that they would be enumerated by a `for-in` loop), which may not be the 3428 * same as the order in which they were defined. 3429 * 3430 * @example 3431 * 3432 * Y.Object.values({a: 'foo', b: 'bar', c: 'baz'}); 3433 * // => ['foo', 'bar', 'baz'] 3434 * 3435 * @method values 3436 * @param {Object} obj An object. 3437 * @return {Array} Array of values. 3438 * @static 3439 */ 3440 O.values = function (obj) { 3441 var keys = O.keys(obj), 3442 i = 0, 3443 len = keys.length, 3444 values = []; 3445 3446 for (; i < len; ++i) { 3447 values.push(obj[keys[i]]); 3448 } 3449 3450 return values; 3451 }; 3452 3453 /** 3454 * Returns the number of enumerable keys owned by an object. 3455 * 3456 * @method size 3457 * @param {Object} obj An object. 3458 * @return {Number} The object's size. 3459 * @static 3460 */ 3461 O.size = function (obj) { 3462 try { 3463 return O.keys(obj).length; 3464 } catch (ex) { 3465 return 0; // Legacy behavior for non-objects. 3466 } 3467 }; 3468 3469 /** 3470 * Returns `true` if the object owns an enumerable property with the specified 3471 * value. 3472 * 3473 * @method hasValue 3474 * @param {Object} obj An object. 3475 * @param {any} value The value to search for. 3476 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise. 3477 * @static 3478 */ 3479 O.hasValue = function (obj, value) { 3480 return Y.Array.indexOf(O.values(obj), value) > -1; 3481 }; 3482 3483 /** 3484 * Executes a function on each enumerable property in _obj_. The function 3485 * receives the value, the key, and the object itself as parameters (in that 3486 * order). 3487 * 3488 * By default, only properties owned by _obj_ are enumerated. To include 3489 * prototype properties, set the _proto_ parameter to `true`. 3490 * 3491 * @method each 3492 * @param {Object} obj Object to enumerate. 3493 * @param {Function} fn Function to execute on each enumerable property. 3494 * @param {mixed} fn.value Value of the current property. 3495 * @param {String} fn.key Key of the current property. 3496 * @param {Object} fn.obj Object being enumerated. 3497 * @param {Object} [thisObj] `this` object to use when calling _fn_. 3498 * @param {Boolean} [proto=false] Include prototype properties. 3499 * @return {YUI} the YUI instance. 3500 * @chainable 3501 * @static 3502 */ 3503 O.each = function (obj, fn, thisObj, proto) { 3504 var key; 3505 3506 for (key in obj) { 3507 if (proto || owns(obj, key)) { 3508 fn.call(thisObj || Y, obj[key], key, obj); 3509 } 3510 } 3511 3512 return Y; 3513 }; 3514 3515 /** 3516 * Executes a function on each enumerable property in _obj_, but halts if the 3517 * function returns a truthy value. The function receives the value, the key, 3518 * and the object itself as paramters (in that order). 3519 * 3520 * By default, only properties owned by _obj_ are enumerated. To include 3521 * prototype properties, set the _proto_ parameter to `true`. 3522 * 3523 * @method some 3524 * @param {Object} obj Object to enumerate. 3525 * @param {Function} fn Function to execute on each enumerable property. 3526 * @param {mixed} fn.value Value of the current property. 3527 * @param {String} fn.key Key of the current property. 3528 * @param {Object} fn.obj Object being enumerated. 3529 * @param {Object} [thisObj] `this` object to use when calling _fn_. 3530 * @param {Boolean} [proto=false] Include prototype properties. 3531 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value, 3532 * `false` otherwise. 3533 * @static 3534 */ 3535 O.some = function (obj, fn, thisObj, proto) { 3536 var key; 3537 3538 for (key in obj) { 3539 if (proto || owns(obj, key)) { 3540 if (fn.call(thisObj || Y, obj[key], key, obj)) { 3541 return true; 3542 } 3543 } 3544 } 3545 3546 return false; 3547 }; 3548 3549 /** 3550 * Retrieves the sub value at the provided path, 3551 * from the value object provided. 3552 * 3553 * @method getValue 3554 * @static 3555 * @param o The object from which to extract the property value. 3556 * @param path {Array} A path array, specifying the object traversal path 3557 * from which to obtain the sub value. 3558 * @return {Any} The value stored in the path, undefined if not found, 3559 * undefined if the source is not an object. Returns the source object 3560 * if an empty path is provided. 3561 */ 3562 O.getValue = function(o, path) { 3563 if (!Lang.isObject(o)) { 3564 return UNDEFINED; 3565 } 3566 3567 var i, 3568 p = Y.Array(path), 3569 l = p.length; 3570 3571 for (i = 0; o !== UNDEFINED && i < l; i++) { 3572 o = o[p[i]]; 3573 } 3574 3575 return o; 3576 }; 3577 3578 /** 3579 * Sets the sub-attribute value at the provided path on the 3580 * value object. Returns the modified value object, or 3581 * undefined if the path is invalid. 3582 * 3583 * @method setValue 3584 * @static 3585 * @param o The object on which to set the sub value. 3586 * @param path {Array} A path array, specifying the object traversal path 3587 * at which to set the sub value. 3588 * @param val {Any} The new value for the sub-attribute. 3589 * @return {Object} The modified object, with the new sub value set, or 3590 * undefined, if the path was invalid. 3591 */ 3592 O.setValue = function(o, path, val) { 3593 var i, 3594 p = Y.Array(path), 3595 leafIdx = p.length - 1, 3596 ref = o; 3597 3598 if (leafIdx >= 0) { 3599 for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) { 3600 ref = ref[p[i]]; 3601 } 3602 3603 if (ref !== UNDEFINED) { 3604 ref[p[i]] = val; 3605 } else { 3606 return UNDEFINED; 3607 } 3608 } 3609 3610 return o; 3611 }; 3612 3613 /** 3614 * Returns `true` if the object has no enumerable properties of its own. 3615 * 3616 * @method isEmpty 3617 * @param {Object} obj An object. 3618 * @return {Boolean} `true` if the object is empty. 3619 * @static 3620 * @since 3.2.0 3621 */ 3622 O.isEmpty = function (obj) { 3623 return !O.keys(Object(obj)).length; 3624 }; 3625 /** 3626 * The YUI module contains the components required for building the YUI seed 3627 * file. This includes the script loading mechanism, a simple queue, and the 3628 * core utilities for the library. 3629 * @module yui 3630 * @submodule yui-base 3631 */ 3632 3633 /** 3634 * YUI user agent detection. 3635 * Do not fork for a browser if it can be avoided. Use feature detection when 3636 * you can. Use the user agent as a last resort. For all fields listed 3637 * as @type float, UA stores a version number for the browser engine, 3638 * 0 otherwise. This value may or may not map to the version number of 3639 * the browser using the engine. The value is presented as a float so 3640 * that it can easily be used for boolean evaluation as well as for 3641 * looking for a particular range of versions. Because of this, 3642 * some of the granularity of the version info may be lost. The fields that 3643 * are @type string default to null. The API docs list the values that 3644 * these fields can have. 3645 * @class UA 3646 * @static 3647 */ 3648 3649 /** 3650 * Static method on `YUI.Env` for parsing a UA string. Called at instantiation 3651 * to populate `Y.UA`. 3652 * 3653 * @static 3654 * @method parseUA 3655 * @param {String} [subUA=navigator.userAgent] UA string to parse 3656 * @return {Object} The Y.UA object 3657 */ 3658 YUI.Env.parseUA = function(subUA) { 3659 3660 var numberify = function(s) { 3661 var c = 0; 3662 return parseFloat(s.replace(/\./g, function() { 3663 return (c++ === 1) ? '' : '.'; 3664 })); 3665 }, 3666 3667 win = Y.config.win, 3668 3669 nav = win && win.navigator, 3670 3671 o = { 3672 3673 /** 3674 * Internet Explorer version number or 0. Example: 6 3675 * @property ie 3676 * @type float 3677 * @static 3678 */ 3679 ie: 0, 3680 3681 /** 3682 * Opera version number or 0. Example: 9.2 3683 * @property opera 3684 * @type float 3685 * @static 3686 */ 3687 opera: 0, 3688 3689 /** 3690 * Gecko engine revision number. Will evaluate to 1 if Gecko 3691 * is detected but the revision could not be found. Other browsers 3692 * will be 0. Example: 1.8 3693 * <pre> 3694 * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7 3695 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8 3696 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81 3697 * Firefox 3.0 <-- 1.9 3698 * Firefox 3.5 <-- 1.91 3699 * </pre> 3700 * @property gecko 3701 * @type float 3702 * @static 3703 */ 3704 gecko: 0, 3705 3706 /** 3707 * AppleWebKit version. KHTML browsers that are not WebKit browsers 3708 * will evaluate to 1, other browsers 0. Example: 418.9 3709 * <pre> 3710 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the 3711 * latest available for Mac OSX 10.3. 3712 * Safari 2.0.2: 416 <-- hasOwnProperty introduced 3713 * Safari 2.0.4: 418 <-- preventDefault fixed 3714 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run 3715 * different versions of webkit 3716 * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been 3717 * updated, but not updated 3718 * to the latest patch. 3719 * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native 3720 * SVG and many major issues fixed). 3721 * Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic 3722 * update from 2.x via the 10.4.11 OS patch. 3723 * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event. 3724 * yahoo.com user agent hack removed. 3725 * </pre> 3726 * http://en.wikipedia.org/wiki/Safari_version_history 3727 * @property webkit 3728 * @type float 3729 * @static 3730 */ 3731 webkit: 0, 3732 3733 /** 3734 * Safari will be detected as webkit, but this property will also 3735 * be populated with the Safari version number 3736 * @property safari 3737 * @type float 3738 * @static 3739 */ 3740 safari: 0, 3741 3742 /** 3743 * Chrome will be detected as webkit, but this property will also 3744 * be populated with the Chrome version number 3745 * @property chrome 3746 * @type float 3747 * @static 3748 */ 3749 chrome: 0, 3750 3751 /** 3752 * The mobile property will be set to a string containing any relevant 3753 * user agent information when a modern mobile browser is detected. 3754 * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series 3755 * devices with the WebKit-based browser, and Opera Mini. 3756 * @property mobile 3757 * @type string 3758 * @default null 3759 * @static 3760 */ 3761 mobile: null, 3762 3763 /** 3764 * Adobe AIR version number or 0. Only populated if webkit is detected. 3765 * Example: 1.0 3766 * @property air 3767 * @type float 3768 */ 3769 air: 0, 3770 /** 3771 * PhantomJS version number or 0. Only populated if webkit is detected. 3772 * Example: 1.0 3773 * @property phantomjs 3774 * @type float 3775 */ 3776 phantomjs: 0, 3777 /** 3778 * Detects Apple iPad's OS version 3779 * @property ipad 3780 * @type float 3781 * @static 3782 */ 3783 ipad: 0, 3784 /** 3785 * Detects Apple iPhone's OS version 3786 * @property iphone 3787 * @type float 3788 * @static 3789 */ 3790 iphone: 0, 3791 /** 3792 * Detects Apples iPod's OS version 3793 * @property ipod 3794 * @type float 3795 * @static 3796 */ 3797 ipod: 0, 3798 /** 3799 * General truthy check for iPad, iPhone or iPod 3800 * @property ios 3801 * @type Boolean 3802 * @default null 3803 * @static 3804 */ 3805 ios: null, 3806 /** 3807 * Detects Googles Android OS version 3808 * @property android 3809 * @type float 3810 * @static 3811 */ 3812 android: 0, 3813 /** 3814 * Detects Kindle Silk 3815 * @property silk 3816 * @type float 3817 * @static 3818 */ 3819 silk: 0, 3820 /** 3821 * Detects Ubuntu version 3822 * @property ubuntu 3823 * @type float 3824 * @static 3825 */ 3826 ubuntu: 0, 3827 /** 3828 * Detects Kindle Silk Acceleration 3829 * @property accel 3830 * @type Boolean 3831 * @static 3832 */ 3833 accel: false, 3834 /** 3835 * Detects Palms WebOS version 3836 * @property webos 3837 * @type float 3838 * @static 3839 */ 3840 webos: 0, 3841 3842 /** 3843 * Google Caja version number or 0. 3844 * @property caja 3845 * @type float 3846 */ 3847 caja: nav && nav.cajaVersion, 3848 3849 /** 3850 * Set to true if the page appears to be in SSL 3851 * @property secure 3852 * @type boolean 3853 * @static 3854 */ 3855 secure: false, 3856 3857 /** 3858 * The operating system. Currently only detecting windows or macintosh 3859 * @property os 3860 * @type string 3861 * @default null 3862 * @static 3863 */ 3864 os: null, 3865 3866 /** 3867 * The Nodejs Version 3868 * @property nodejs 3869 * @type float 3870 * @default 0 3871 * @static 3872 */ 3873 nodejs: 0, 3874 /** 3875 * Window8/IE10 Application host environment 3876 * @property winjs 3877 * @type Boolean 3878 * @static 3879 */ 3880 winjs: !!((typeof Windows !== "undefined") && Windows.System), 3881 /** 3882 * Are touch/msPointer events available on this device 3883 * @property touchEnabled 3884 * @type Boolean 3885 * @static 3886 */ 3887 touchEnabled: false 3888 }, 3889 3890 ua = subUA || nav && nav.userAgent, 3891 3892 loc = win && win.location, 3893 3894 href = loc && loc.href, 3895 3896 m; 3897 3898 /** 3899 * The User Agent string that was parsed 3900 * @property userAgent 3901 * @type String 3902 * @static 3903 */ 3904 o.userAgent = ua; 3905 3906 3907 o.secure = href && (href.toLowerCase().indexOf('https') === 0); 3908 3909 if (ua) { 3910 3911 if ((/windows|win32/i).test(ua)) { 3912 o.os = 'windows'; 3913 } else if ((/macintosh|mac_powerpc/i).test(ua)) { 3914 o.os = 'macintosh'; 3915 } else if ((/android/i).test(ua)) { 3916 o.os = 'android'; 3917 } else if ((/symbos/i).test(ua)) { 3918 o.os = 'symbos'; 3919 } else if ((/linux/i).test(ua)) { 3920 o.os = 'linux'; 3921 } else if ((/rhino/i).test(ua)) { 3922 o.os = 'rhino'; 3923 } 3924 3925 // Modern KHTML browsers should qualify as Safari X-Grade 3926 if ((/KHTML/).test(ua)) { 3927 o.webkit = 1; 3928 } 3929 if ((/IEMobile|XBLWP7/).test(ua)) { 3930 o.mobile = 'windows'; 3931 } 3932 if ((/Fennec/).test(ua)) { 3933 o.mobile = 'gecko'; 3934 } 3935 // Modern WebKit browsers are at least X-Grade 3936 m = ua.match(/AppleWebKit\/([^\s]*)/); 3937 if (m && m[1]) { 3938 o.webkit = numberify(m[1]); 3939 o.safari = o.webkit; 3940 3941 if (/PhantomJS/.test(ua)) { 3942 m = ua.match(/PhantomJS\/([^\s]*)/); 3943 if (m && m[1]) { 3944 o.phantomjs = numberify(m[1]); 3945 } 3946 } 3947 3948 // Mobile browser check 3949 if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) { 3950 o.mobile = 'Apple'; // iPhone or iPod Touch 3951 3952 m = ua.match(/OS ([^\s]*)/); 3953 if (m && m[1]) { 3954 m = numberify(m[1].replace('_', '.')); 3955 } 3956 o.ios = m; 3957 o.os = 'ios'; 3958 o.ipad = o.ipod = o.iphone = 0; 3959 3960 m = ua.match(/iPad|iPod|iPhone/); 3961 if (m && m[0]) { 3962 o[m[0].toLowerCase()] = o.ios; 3963 } 3964 } else { 3965 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/); 3966 if (m) { 3967 // Nokia N-series, webOS, ex: NokiaN95 3968 o.mobile = m[0]; 3969 } 3970 if (/webOS/.test(ua)) { 3971 o.mobile = 'WebOS'; 3972 m = ua.match(/webOS\/([^\s]*);/); 3973 if (m && m[1]) { 3974 o.webos = numberify(m[1]); 3975 } 3976 } 3977 if (/ Android/.test(ua)) { 3978 if (/Mobile/.test(ua)) { 3979 o.mobile = 'Android'; 3980 } 3981 m = ua.match(/Android ([^\s]*);/); 3982 if (m && m[1]) { 3983 o.android = numberify(m[1]); 3984 } 3985 3986 } 3987 if (/Silk/.test(ua)) { 3988 m = ua.match(/Silk\/([^\s]*)/); 3989 if (m && m[1]) { 3990 o.silk = numberify(m[1]); 3991 } 3992 if (!o.android) { 3993 o.android = 2.34; //Hack for desktop mode in Kindle 3994 o.os = 'Android'; 3995 } 3996 if (/Accelerated=true/.test(ua)) { 3997 o.accel = true; 3998 } 3999 } 4000 } 4001 4002 m = ua.match(/OPR\/(\d+\.\d+)/); 4003 4004 if (m && m[1]) { 4005 // Opera 15+ with Blink (pretends to be both Chrome and Safari) 4006 o.opera = numberify(m[1]); 4007 } else { 4008 m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/); 4009 4010 if (m && m[1] && m[2]) { 4011 o.chrome = numberify(m[2]); // Chrome 4012 o.safari = 0; //Reset safari back to 0 4013 if (m[1] === 'CrMo') { 4014 o.mobile = 'chrome'; 4015 } 4016 } else { 4017 m = ua.match(/AdobeAIR\/([^\s]*)/); 4018 if (m) { 4019 o.air = m[0]; // Adobe AIR 1.0 or better 4020 } 4021 } 4022 } 4023 } 4024 4025 m = ua.match(/Ubuntu\ (\d+\.\d+)/); 4026 if (m && m[1]) { 4027 4028 o.os = 'linux'; 4029 o.ubuntu = numberify(m[1]); 4030 4031 m = ua.match(/\ WebKit\/([^\s]*)/); 4032 if (m && m[1]) { 4033 o.webkit = numberify(m[1]); 4034 } 4035 m = ua.match(/\ Chromium\/([^\s]*)/); 4036 if (m && m[1]) { 4037 o.chrome = numberify(m[1]); 4038 } 4039 if (/ Mobile$/.test(ua)) { 4040 o.mobile = 'Ubuntu'; 4041 } 4042 } 4043 4044 if (!o.webkit) { // not webkit 4045 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) 4046 if (/Opera/.test(ua)) { 4047 m = ua.match(/Opera[\s\/]([^\s]*)/); 4048 if (m && m[1]) { 4049 o.opera = numberify(m[1]); 4050 } 4051 m = ua.match(/Version\/([^\s]*)/); 4052 if (m && m[1]) { 4053 o.opera = numberify(m[1]); // opera 10+ 4054 } 4055 4056 if (/Opera Mobi/.test(ua)) { 4057 o.mobile = 'opera'; 4058 m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/); 4059 if (m && m[1]) { 4060 o.opera = numberify(m[1]); 4061 } 4062 } 4063 m = ua.match(/Opera Mini[^;]*/); 4064 4065 if (m) { 4066 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 4067 } 4068 } else { // not opera or webkit 4069 m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/); 4070 4071 if (m && (m[1] || m[2])) { 4072 o.ie = numberify(m[1] || m[2]); 4073 } else { // not opera, webkit, or ie 4074 m = ua.match(/Gecko\/([^\s]*)/); 4075 4076 if (m) { 4077 o.gecko = 1; // Gecko detected, look for revision 4078 m = ua.match(/rv:([^\s\)]*)/); 4079 if (m && m[1]) { 4080 o.gecko = numberify(m[1]); 4081 if (/Mobile|Tablet/.test(ua)) { 4082 o.mobile = "ffos"; 4083 } 4084 } 4085 } 4086 } 4087 } 4088 } 4089 } 4090 4091 //Check for known properties to tell if touch events are enabled on this device or if 4092 //the number of MSPointer touchpoints on this device is greater than 0. 4093 if (win && nav && !(o.chrome && o.chrome < 6)) { 4094 o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0))); 4095 } 4096 4097 //It was a parsed UA, do not assign the global value. 4098 if (!subUA) { 4099 4100 if (typeof process === 'object') { 4101 4102 if (process.versions && process.versions.node) { 4103 //NodeJS 4104 o.os = process.platform; 4105 o.nodejs = numberify(process.versions.node); 4106 } 4107 } 4108 4109 YUI.Env.UA = o; 4110 4111 } 4112 4113 return o; 4114 }; 4115 4116 4117 Y.UA = YUI.Env.UA || YUI.Env.parseUA(); 4118 4119 /** 4120 Performs a simple comparison between two version numbers, accounting for 4121 standard versioning logic such as the fact that "535.8" is a lower version than 4122 "535.24", even though a simple numerical comparison would indicate that it's 4123 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are 4124 considered equivalent. 4125 4126 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent, 4127 1 if _a_ is higher than _b_. 4128 4129 Versions may be numbers or strings containing numbers and dots. For example, 4130 both `535` and `"535.8.10"` are acceptable. A version string containing 4131 non-numeric characters, like `"535.8.beta"`, may produce unexpected results. 4132 4133 @method compareVersions 4134 @param {Number|String} a First version number to compare. 4135 @param {Number|String} b Second version number to compare. 4136 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is 4137 higher than _b_. 4138 **/ 4139 Y.UA.compareVersions = function (a, b) { 4140 var aPart, aParts, bPart, bParts, i, len; 4141 4142 if (a === b) { 4143 return 0; 4144 } 4145 4146 aParts = (a + '').split('.'); 4147 bParts = (b + '').split('.'); 4148 4149 for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) { 4150 aPart = parseInt(aParts[i], 10); 4151 bPart = parseInt(bParts[i], 10); 4152 4153 /*jshint expr: true*/ 4154 isNaN(aPart) && (aPart = 0); 4155 isNaN(bPart) && (bPart = 0); 4156 4157 if (aPart < bPart) { 4158 return -1; 4159 } 4160 4161 if (aPart > bPart) { 4162 return 1; 4163 } 4164 } 4165 4166 return 0; 4167 }; 4168 YUI.Env.aliases = { 4169 "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"], 4170 "anim-shape-transform": ["anim-shape"], 4171 "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"], 4172 "attribute": ["attribute-base","attribute-complex"], 4173 "attribute-events": ["attribute-observable"], 4174 "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"], 4175 "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"], 4176 "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"], 4177 "base": ["base-base","base-pluginhost","base-build"], 4178 "cache": ["cache-base","cache-offline","cache-plugin"], 4179 "charts": ["charts-base"], 4180 "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"], 4181 "color": ["color-base","color-hsl","color-harmony"], 4182 "controller": ["router"], 4183 "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"], 4184 "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"], 4185 "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"], 4186 "datatype": ["datatype-date","datatype-number","datatype-xml"], 4187 "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"], 4188 "datatype-number": ["datatype-number-parse","datatype-number-format"], 4189 "datatype-xml": ["datatype-xml-parse","datatype-xml-format"], 4190 "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"], 4191 "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"], 4192 "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"], 4193 "event": ["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"], 4194 "event-custom": ["event-custom-base","event-custom-complex"], 4195 "event-gestures": ["event-flick","event-move"], 4196 "handlebars": ["handlebars-compiler"], 4197 "highlight": ["highlight-base","highlight-accentfold"], 4198 "history": ["history-base","history-hash","history-html5"], 4199 "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"], 4200 "json": ["json-parse","json-stringify"], 4201 "loader": ["loader-base","loader-rollup","loader-yui3"], 4202 "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"], 4203 "pluginhost": ["pluginhost-base","pluginhost-config"], 4204 "querystring": ["querystring-parse","querystring-stringify"], 4205 "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"], 4206 "resize": ["resize-base","resize-proxy","resize-constrain"], 4207 "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"], 4208 "template": ["template-base","template-micro"], 4209 "text": ["text-accentfold","text-wordbreak"], 4210 "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"] 4211 }; 4212 4213 4214 }, '3.17.2', { 4215 "use": [ 4216 "yui-base", 4217 "get", 4218 "features", 4219 "intl-base", 4220 "yui-log", 4221 "yui-later", 4222 "loader-base", 4223 "loader-rollup", 4224 "loader-yui3" 4225 ] 4226 }); 4227 YUI.add('get', function (Y, NAME) { 4228 4229 /*jslint boss:true, expr:true, laxbreak: true */ 4230 4231 /** 4232 Provides dynamic loading of remote JavaScript and CSS resources. 4233 4234 @module get 4235 @class Get 4236 @static 4237 **/ 4238 4239 var Lang = Y.Lang, 4240 4241 CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode() 4242 4243 Get, Transaction; 4244 4245 Y.Get = Get = { 4246 // -- Public Properties ---------------------------------------------------- 4247 4248 /** 4249 Default options for CSS requests. Options specified here will override 4250 global defaults for CSS requests. 4251 4252 See the `options` property for all available options. 4253 4254 @property cssOptions 4255 @type Object 4256 @static 4257 @since 3.5.0 4258 **/ 4259 cssOptions: { 4260 attributes: { 4261 rel: 'stylesheet' 4262 }, 4263 4264 doc : Y.config.linkDoc || Y.config.doc, 4265 pollInterval: 50 4266 }, 4267 4268 /** 4269 Default options for JS requests. Options specified here will override global 4270 defaults for JS requests. 4271 4272 See the `options` property for all available options. 4273 4274 @property jsOptions 4275 @type Object 4276 @static 4277 @since 3.5.0 4278 **/ 4279 jsOptions: { 4280 autopurge: true, 4281 doc : Y.config.scriptDoc || Y.config.doc 4282 }, 4283 4284 /** 4285 Default options to use for all requests. 4286 4287 Note that while all available options are documented here for ease of 4288 discovery, some options (like callback functions) only make sense at the 4289 transaction level. 4290 4291 Callback functions specified via the options object or the `options` 4292 parameter of the `css()`, `js()`, or `load()` methods will receive the 4293 transaction object as a parameter. See `Y.Get.Transaction` for details on 4294 the properties and methods available on transactions. 4295 4296 @static 4297 @since 3.5.0 4298 @property {Object} options 4299 4300 @property {Boolean} [options.async=false] Whether or not to load scripts 4301 asynchronously, meaning they're requested in parallel and execution 4302 order is not guaranteed. Has no effect on CSS, since CSS is always 4303 loaded asynchronously. 4304 4305 @property {Object} [options.attributes] HTML attribute name/value pairs that 4306 should be added to inserted nodes. By default, the `charset` attribute 4307 will be set to "utf-8" and nodes will be given an auto-generated `id` 4308 attribute, but you can override these with your own values if desired. 4309 4310 @property {Boolean} [options.autopurge] Whether or not to automatically 4311 purge inserted nodes after the purge threshold is reached. This is 4312 `true` by default for JavaScript, but `false` for CSS since purging a 4313 CSS node will also remove any styling applied by the referenced file. 4314 4315 @property {Object} [options.context] `this` object to use when calling 4316 callback functions. Defaults to the transaction object. 4317 4318 @property {Mixed} [options.data] Arbitrary data object to pass to "on*" 4319 callbacks. 4320 4321 @property {Document} [options.doc] Document into which nodes should be 4322 inserted. By default, the current document is used. 4323 4324 @property {HTMLElement|String} [options.insertBefore] HTML element or id 4325 string of an element before which all generated nodes should be 4326 inserted. If not specified, Get will automatically determine the best 4327 place to insert nodes for maximum compatibility. 4328 4329 @property {Function} [options.onEnd] Callback to execute after a transaction 4330 is complete, regardless of whether it succeeded or failed. 4331 4332 @property {Function} [options.onFailure] Callback to execute after a 4333 transaction fails, times out, or is aborted. 4334 4335 @property {Function} [options.onProgress] Callback to execute after each 4336 individual request in a transaction either succeeds or fails. 4337 4338 @property {Function} [options.onSuccess] Callback to execute after a 4339 transaction completes successfully with no errors. Note that in browsers 4340 that don't support the `error` event on CSS `<link>` nodes, a failed CSS 4341 request may still be reported as a success because in these browsers 4342 it can be difficult or impossible to distinguish between success and 4343 failure for CSS resources. 4344 4345 @property {Function} [options.onTimeout] Callback to execute after a 4346 transaction times out. 4347 4348 @property {Number} [options.pollInterval=50] Polling interval (in 4349 milliseconds) for detecting CSS load completion in browsers that don't 4350 support the `load` event on `<link>` nodes. This isn't used for 4351 JavaScript. 4352 4353 @property {Number} [options.purgethreshold=20] Number of nodes to insert 4354 before triggering an automatic purge when `autopurge` is `true`. 4355 4356 @property {Number} [options.timeout] Number of milliseconds to wait before 4357 aborting a transaction. When a timeout occurs, the `onTimeout` callback 4358 is called, followed by `onFailure` and finally `onEnd`. By default, 4359 there is no timeout. 4360 4361 @property {String} [options.type] Resource type ("css" or "js"). This option 4362 is set automatically by the `css()` and `js()` functions and will be 4363 ignored there, but may be useful when using the `load()` function. If 4364 not specified, the type will be inferred from the URL, defaulting to 4365 "js" if the URL doesn't contain a recognizable file extension. 4366 **/ 4367 options: { 4368 attributes: { 4369 charset: 'utf-8' 4370 }, 4371 4372 purgethreshold: 20 4373 }, 4374 4375 // -- Protected Properties ------------------------------------------------- 4376 4377 /** 4378 Regex that matches a CSS URL. Used to guess the file type when it's not 4379 specified. 4380 4381 @property REGEX_CSS 4382 @type RegExp 4383 @final 4384 @protected 4385 @static 4386 @since 3.5.0 4387 **/ 4388 REGEX_CSS: /\.css(?:[?;].*)?$/i, 4389 4390 /** 4391 Regex that matches a JS URL. Used to guess the file type when it's not 4392 specified. 4393 4394 @property REGEX_JS 4395 @type RegExp 4396 @final 4397 @protected 4398 @static 4399 @since 3.5.0 4400 **/ 4401 REGEX_JS : /\.js(?:[?;].*)?$/i, 4402 4403 /** 4404 Contains information about the current environment, such as what script and 4405 link injection features it supports. 4406 4407 This object is created and populated the first time the `_getEnv()` method 4408 is called. 4409 4410 @property _env 4411 @type Object 4412 @protected 4413 @static 4414 @since 3.5.0 4415 **/ 4416 4417 /** 4418 Mapping of document _yuid strings to <head> or <base> node references so we 4419 don't have to look the node up each time we want to insert a request node. 4420 4421 @property _insertCache 4422 @type Object 4423 @protected 4424 @static 4425 @since 3.5.0 4426 **/ 4427 _insertCache: {}, 4428 4429 /** 4430 Information about the currently pending transaction, if any. 4431 4432 This is actually an object with two properties: `callback`, containing the 4433 optional callback passed to `css()`, `load()`, or `js()`; and `transaction`, 4434 containing the actual transaction instance. 4435 4436 @property _pending 4437 @type Object 4438 @protected 4439 @static 4440 @since 3.5.0 4441 **/ 4442 _pending: null, 4443 4444 /** 4445 HTML nodes eligible to be purged next time autopurge is triggered. 4446 4447 @property _purgeNodes 4448 @type HTMLElement[] 4449 @protected 4450 @static 4451 @since 3.5.0 4452 **/ 4453 _purgeNodes: [], 4454 4455 /** 4456 Queued transactions and associated callbacks. 4457 4458 @property _queue 4459 @type Object[] 4460 @protected 4461 @static 4462 @since 3.5.0 4463 **/ 4464 _queue: [], 4465 4466 // -- Public Methods ------------------------------------------------------- 4467 4468 /** 4469 Aborts the specified transaction. 4470 4471 This will cause the transaction's `onFailure` callback to be called and 4472 will prevent any new script and link nodes from being added to the document, 4473 but any resources that have already been requested will continue loading 4474 (there's no safe way to prevent this, unfortunately). 4475 4476 *Note:* This method is deprecated as of 3.5.0, and will be removed in a 4477 future version of YUI. Use the transaction-level `abort()` method instead. 4478 4479 @method abort 4480 @param {Get.Transaction} transaction Transaction to abort. 4481 @deprecated Use the `abort()` method on the transaction instead. 4482 @static 4483 **/ 4484 abort: function (transaction) { 4485 var i, id, item, len, pending; 4486 4487 Y.log('`Y.Get.abort()` is deprecated as of 3.5.0. Use the `abort()` method on the transaction instead.', 'warn', 'get'); 4488 4489 if (!transaction.abort) { 4490 id = transaction; 4491 pending = this._pending; 4492 transaction = null; 4493 4494 if (pending && pending.transaction.id === id) { 4495 transaction = pending.transaction; 4496 this._pending = null; 4497 } else { 4498 for (i = 0, len = this._queue.length; i < len; ++i) { 4499 item = this._queue[i].transaction; 4500 4501 if (item.id === id) { 4502 transaction = item; 4503 this._queue.splice(i, 1); 4504 break; 4505 } 4506 } 4507 } 4508 } 4509 4510 transaction && transaction.abort(); 4511 }, 4512 4513 /** 4514 Loads one or more CSS files. 4515 4516 The _urls_ parameter may be provided as a URL string, a request object, 4517 or an array of URL strings and/or request objects. 4518 4519 A request object is just an object that contains a `url` property and zero 4520 or more options that should apply specifically to that request. 4521 Request-specific options take priority over transaction-level options and 4522 default options. 4523 4524 URLs may be relative or absolute, and do not have to have the same origin 4525 as the current page. 4526 4527 The `options` parameter may be omitted completely and a callback passed in 4528 its place, if desired. 4529 4530 @example 4531 4532 // Load a single CSS file and log a message on completion. 4533 Y.Get.css('foo.css', function (err) { 4534 if (err) { 4535 Y.log('foo.css failed to load!'); 4536 } else { 4537 Y.log('foo.css was loaded successfully'); 4538 } 4539 }); 4540 4541 // Load multiple CSS files and log a message when all have finished 4542 // loading. 4543 var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css']; 4544 4545 Y.Get.css(urls, function (err) { 4546 if (err) { 4547 Y.log('one or more files failed to load!'); 4548 } else { 4549 Y.log('all files loaded successfully'); 4550 } 4551 }); 4552 4553 // Specify transaction-level options, which will apply to all requests 4554 // within the transaction. 4555 Y.Get.css(urls, { 4556 attributes: {'class': 'my-css'}, 4557 timeout : 5000 4558 }); 4559 4560 // Specify per-request options, which override transaction-level and 4561 // default options. 4562 Y.Get.css([ 4563 {url: 'foo.css', attributes: {id: 'foo'}}, 4564 {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}} 4565 ]); 4566 4567 @method css 4568 @param {String|Object|Array} urls URL string, request object, or array 4569 of URLs and/or request objects to load. 4570 @param {Object} [options] Options for this transaction. See the 4571 `Y.Get.options` property for a complete list of available options. 4572 @param {Function} [callback] Callback function to be called on completion. 4573 This is a general callback and will be called before any more granular 4574 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4575 object. 4576 4577 @param {Array|null} callback.err Array of errors that occurred during 4578 the transaction, or `null` on success. 4579 @param {Get.Transaction} callback.transaction Transaction object. 4580 4581 @return {Get.Transaction} Transaction object. 4582 @static 4583 **/ 4584 css: function (urls, options, callback) { 4585 return this._load('css', urls, options, callback); 4586 }, 4587 4588 /** 4589 Loads one or more JavaScript resources. 4590 4591 The _urls_ parameter may be provided as a URL string, a request object, 4592 or an array of URL strings and/or request objects. 4593 4594 A request object is just an object that contains a `url` property and zero 4595 or more options that should apply specifically to that request. 4596 Request-specific options take priority over transaction-level options and 4597 default options. 4598 4599 URLs may be relative or absolute, and do not have to have the same origin 4600 as the current page. 4601 4602 The `options` parameter may be omitted completely and a callback passed in 4603 its place, if desired. 4604 4605 Scripts will be executed in the order they're specified unless the `async` 4606 option is `true`, in which case they'll be loaded in parallel and executed 4607 in whatever order they finish loading. 4608 4609 @example 4610 4611 // Load a single JS file and log a message on completion. 4612 Y.Get.js('foo.js', function (err) { 4613 if (err) { 4614 Y.log('foo.js failed to load!'); 4615 } else { 4616 Y.log('foo.js was loaded successfully'); 4617 } 4618 }); 4619 4620 // Load multiple JS files, execute them in order, and log a message when 4621 // all have finished loading. 4622 var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js']; 4623 4624 Y.Get.js(urls, function (err) { 4625 if (err) { 4626 Y.log('one or more files failed to load!'); 4627 } else { 4628 Y.log('all files loaded successfully'); 4629 } 4630 }); 4631 4632 // Specify transaction-level options, which will apply to all requests 4633 // within the transaction. 4634 Y.Get.js(urls, { 4635 attributes: {'class': 'my-js'}, 4636 timeout : 5000 4637 }); 4638 4639 // Specify per-request options, which override transaction-level and 4640 // default options. 4641 Y.Get.js([ 4642 {url: 'foo.js', attributes: {id: 'foo'}}, 4643 {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}} 4644 ]); 4645 4646 @method js 4647 @param {String|Object|Array} urls URL string, request object, or array 4648 of URLs and/or request objects to load. 4649 @param {Object} [options] Options for this transaction. See the 4650 `Y.Get.options` property for a complete list of available options. 4651 @param {Function} [callback] Callback function to be called on completion. 4652 This is a general callback and will be called before any more granular 4653 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4654 object. 4655 4656 @param {Array|null} callback.err Array of errors that occurred during 4657 the transaction, or `null` on success. 4658 @param {Get.Transaction} callback.transaction Transaction object. 4659 4660 @return {Get.Transaction} Transaction object. 4661 @since 3.5.0 4662 @static 4663 **/ 4664 js: function (urls, options, callback) { 4665 return this._load('js', urls, options, callback); 4666 }, 4667 4668 /** 4669 Loads one or more CSS and/or JavaScript resources in the same transaction. 4670 4671 Use this method when you want to load both CSS and JavaScript in a single 4672 transaction and be notified when all requested URLs have finished loading, 4673 regardless of type. 4674 4675 Behavior and options are the same as for the `css()` and `js()` methods. If 4676 a resource type isn't specified in per-request options or transaction-level 4677 options, Get will guess the file type based on the URL's extension (`.css` 4678 or `.js`, with or without a following query string). If the file type can't 4679 be guessed from the URL, a warning will be logged and Get will assume the 4680 URL is a JavaScript resource. 4681 4682 @example 4683 4684 // Load both CSS and JS files in a single transaction, and log a message 4685 // when all files have finished loading. 4686 Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) { 4687 if (err) { 4688 Y.log('one or more files failed to load!'); 4689 } else { 4690 Y.log('all files loaded successfully'); 4691 } 4692 }); 4693 4694 @method load 4695 @param {String|Object|Array} urls URL string, request object, or array 4696 of URLs and/or request objects to load. 4697 @param {Object} [options] Options for this transaction. See the 4698 `Y.Get.options` property for a complete list of available options. 4699 @param {Function} [callback] Callback function to be called on completion. 4700 This is a general callback and will be called before any more granular 4701 callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options` 4702 object. 4703 4704 @param {Array|null} err Array of errors that occurred during the 4705 transaction, or `null` on success. 4706 @param {Get.Transaction} Transaction object. 4707 4708 @return {Get.Transaction} Transaction object. 4709 @since 3.5.0 4710 @static 4711 **/ 4712 load: function (urls, options, callback) { 4713 return this._load(null, urls, options, callback); 4714 }, 4715 4716 // -- Protected Methods ---------------------------------------------------- 4717 4718 /** 4719 Triggers an automatic purge if the purge threshold has been reached. 4720 4721 @method _autoPurge 4722 @param {Number} threshold Purge threshold to use, in milliseconds. 4723 @protected 4724 @since 3.5.0 4725 @static 4726 **/ 4727 _autoPurge: function (threshold) { 4728 if (threshold && this._purgeNodes.length >= threshold) { 4729 Y.log('autopurge triggered after ' + this._purgeNodes.length + ' nodes', 'info', 'get'); 4730 this._purge(this._purgeNodes); 4731 } 4732 }, 4733 4734 /** 4735 Populates the `_env` property with information about the current 4736 environment. 4737 4738 @method _getEnv 4739 @return {Object} Environment information. 4740 @protected 4741 @since 3.5.0 4742 @static 4743 **/ 4744 _getEnv: function () { 4745 var doc = Y.config.doc, 4746 ua = Y.UA; 4747 4748 // Note: some of these checks require browser sniffs since it's not 4749 // feasible to load test files on every pageview just to perform a 4750 // feature test. I'm sorry if this makes you sad. 4751 return (this._env = { 4752 4753 // True if this is a browser that supports disabling async mode on 4754 // dynamically created script nodes. See 4755 // https://developer.mozilla.org/En/HTML/Element/Script#Attributes 4756 4757 // IE10 doesn't return true for the MDN feature test, so setting it explicitly, 4758 // because it is async by default, and allows you to disable async by setting it to false 4759 async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10), 4760 4761 // True if this browser fires an event when a dynamically injected 4762 // link node fails to load. This is currently true for Firefox 9+ 4763 // and WebKit 535.24+ 4764 cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0, 4765 4766 // True if this browser fires an event when a dynamically injected 4767 // link node finishes loading. This is currently true for IE, Opera, 4768 // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the 4769 // DOM 0 "onload" event, but not "load". All versions of IE fire 4770 // "onload". 4771 // davglass: Seems that Chrome on Android needs this to be false. 4772 cssLoad: ( 4773 (!ua.gecko && !ua.webkit) || ua.gecko >= 9 || 4774 ua.compareVersions(ua.webkit, 535.24) >= 0 4775 ) && !(ua.chrome && ua.chrome <= 18), 4776 4777 // True if this browser preserves script execution order while 4778 // loading scripts in parallel as long as the script node's `async` 4779 // attribute is set to false to explicitly disable async execution. 4780 preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10)) 4781 }); 4782 }, 4783 4784 _getTransaction: function (urls, options) { 4785 var requests = [], 4786 i, len, req, url; 4787 4788 if (!Lang.isArray(urls)) { 4789 urls = [urls]; 4790 } 4791 4792 options = Y.merge(this.options, options); 4793 4794 // Clone the attributes object so we don't end up modifying it by ref. 4795 options.attributes = Y.merge(this.options.attributes, 4796 options.attributes); 4797 4798 for (i = 0, len = urls.length; i < len; ++i) { 4799 url = urls[i]; 4800 req = {attributes: {}}; 4801 4802 // If `url` is a string, we create a URL object for it, then mix in 4803 // global options and request-specific options. If it's an object 4804 // with a "url" property, we assume it's a request object containing 4805 // URL-specific options. 4806 if (typeof url === 'string') { 4807 req.url = url; 4808 } else if (url.url) { 4809 // URL-specific options override both global defaults and 4810 // request-specific options. 4811 Y.mix(req, url, false, null, 0, true); 4812 url = url.url; // Make url a string so we can use it later. 4813 } else { 4814 Y.log('URL must be a string or an object with a `url` property.', 'error', 'get'); 4815 continue; 4816 } 4817 4818 Y.mix(req, options, false, null, 0, true); 4819 4820 // If we didn't get an explicit type for this URL either in the 4821 // request options or the URL-specific options, try to determine 4822 // one from the file extension. 4823 if (!req.type) { 4824 if (this.REGEX_CSS.test(url)) { 4825 req.type = 'css'; 4826 } else { 4827 if (!this.REGEX_JS.test(url)) { 4828 Y.log("Can't guess file type from URL. Assuming JS: " + url, 'warn', 'get'); 4829 } 4830 4831 req.type = 'js'; 4832 } 4833 } 4834 4835 // Mix in type-specific default options, but don't overwrite any 4836 // options that have already been set. 4837 Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions, 4838 false, null, 0, true); 4839 4840 // Give the node an id attribute if it doesn't already have one. 4841 req.attributes.id || (req.attributes.id = Y.guid()); 4842 4843 // Backcompat for <3.5.0 behavior. 4844 if (req.win) { 4845 Y.log('The `win` option is deprecated as of 3.5.0. Use `doc` instead.', 'warn', 'get'); 4846 req.doc = req.win.document; 4847 } else { 4848 req.win = req.doc.defaultView || req.doc.parentWindow; 4849 } 4850 4851 if (req.charset) { 4852 Y.log('The `charset` option is deprecated as of 3.5.0. Set `attributes.charset` instead.', 'warn', 'get'); 4853 req.attributes.charset = req.charset; 4854 } 4855 4856 requests.push(req); 4857 } 4858 4859 return new Transaction(requests, options); 4860 }, 4861 4862 _load: function (type, urls, options, callback) { 4863 var transaction; 4864 4865 // Allow callback as third param. 4866 if (typeof options === 'function') { 4867 callback = options; 4868 options = {}; 4869 } 4870 4871 options || (options = {}); 4872 options.type = type; 4873 4874 options._onFinish = Get._onTransactionFinish; 4875 4876 if (!this._env) { 4877 this._getEnv(); 4878 } 4879 4880 transaction = this._getTransaction(urls, options); 4881 4882 this._queue.push({ 4883 callback : callback, 4884 transaction: transaction 4885 }); 4886 4887 this._next(); 4888 4889 return transaction; 4890 }, 4891 4892 _onTransactionFinish : function() { 4893 Get._pending = null; 4894 Get._next(); 4895 }, 4896 4897 _next: function () { 4898 var item; 4899 4900 if (this._pending) { 4901 return; 4902 } 4903 4904 item = this._queue.shift(); 4905 4906 if (item) { 4907 this._pending = item; 4908 item.transaction.execute(item.callback); 4909 } 4910 }, 4911 4912 _purge: function (nodes) { 4913 var purgeNodes = this._purgeNodes, 4914 isTransaction = nodes !== purgeNodes, 4915 index, node; 4916 4917 while (node = nodes.pop()) { // assignment 4918 // Don't purge nodes that haven't finished loading (or errored out), 4919 // since this can hang the transaction. 4920 if (!node._yuiget_finished) { 4921 continue; 4922 } 4923 4924 node.parentNode && node.parentNode.removeChild(node); 4925 4926 // If this is a transaction-level purge and this node also exists in 4927 // the Get-level _purgeNodes array, we need to remove it from 4928 // _purgeNodes to avoid creating a memory leak. The indexOf lookup 4929 // sucks, but until we get WeakMaps, this is the least troublesome 4930 // way to do this (we can't just hold onto node ids because they may 4931 // not be in the same document). 4932 if (isTransaction) { 4933 index = Y.Array.indexOf(purgeNodes, node); 4934 4935 if (index > -1) { 4936 purgeNodes.splice(index, 1); 4937 } 4938 } 4939 } 4940 } 4941 }; 4942 4943 /** 4944 Alias for `js()`. 4945 4946 @method script 4947 @static 4948 **/ 4949 Get.script = Get.js; 4950 4951 /** 4952 Represents a Get transaction, which may contain requests for one or more JS or 4953 CSS files. 4954 4955 This class should not be instantiated manually. Instances will be created and 4956 returned as needed by Y.Get's `css()`, `js()`, and `load()` methods. 4957 4958 @class Get.Transaction 4959 @constructor 4960 @since 3.5.0 4961 **/ 4962 Get.Transaction = Transaction = function (requests, options) { 4963 var self = this; 4964 4965 self.id = Transaction._lastId += 1; 4966 self.data = options.data; 4967 self.errors = []; 4968 self.nodes = []; 4969 self.options = options; 4970 self.requests = requests; 4971 4972 self._callbacks = []; // callbacks to call after execution finishes 4973 self._queue = []; 4974 self._reqsWaiting = 0; 4975 4976 // Deprecated pre-3.5.0 properties. 4977 self.tId = self.id; // Use `id` instead. 4978 self.win = options.win || Y.config.win; 4979 }; 4980 4981 /** 4982 Arbitrary data object associated with this transaction. 4983 4984 This object comes from the options passed to `Get.css()`, `Get.js()`, or 4985 `Get.load()`, and will be `undefined` if no data object was specified. 4986 4987 @property {Object} data 4988 **/ 4989 4990 /** 4991 Array of errors that have occurred during this transaction, if any. Each error 4992 object has the following properties: 4993 `errors.error`: Error message. 4994 `errors.request`: Request object related to the error. 4995 4996 @since 3.5.0 4997 @property {Object[]} errors 4998 **/ 4999 5000 /** 5001 Numeric id for this transaction, unique among all transactions within the same 5002 YUI sandbox in the current pageview. 5003 5004 @property {Number} id 5005 @since 3.5.0 5006 **/ 5007 5008 /** 5009 HTMLElement nodes (native ones, not YUI Node instances) that have been inserted 5010 during the current transaction. 5011 5012 @property {HTMLElement[]} nodes 5013 **/ 5014 5015 /** 5016 Options associated with this transaction. 5017 5018 See `Get.options` for the full list of available options. 5019 5020 @property {Object} options 5021 @since 3.5.0 5022 **/ 5023 5024 /** 5025 Request objects contained in this transaction. Each request object represents 5026 one CSS or JS URL that will be (or has been) requested and loaded into the page. 5027 5028 @property {Object} requests 5029 @since 3.5.0 5030 **/ 5031 5032 /** 5033 Id of the most recent transaction. 5034 5035 @property _lastId 5036 @type Number 5037 @protected 5038 @static 5039 **/ 5040 Transaction._lastId = 0; 5041 5042 Transaction.prototype = { 5043 // -- Public Properties ---------------------------------------------------- 5044 5045 /** 5046 Current state of this transaction. One of "new", "executing", or "done". 5047 5048 @property _state 5049 @type String 5050 @protected 5051 **/ 5052 _state: 'new', // "new", "executing", or "done" 5053 5054 // -- Public Methods ------------------------------------------------------- 5055 5056 /** 5057 Aborts this transaction. 5058 5059 This will cause the transaction's `onFailure` callback to be called and 5060 will prevent any new script and link nodes from being added to the document, 5061 but any resources that have already been requested will continue loading 5062 (there's no safe way to prevent this, unfortunately). 5063 5064 @method abort 5065 @param {String} [msg="Aborted."] Optional message to use in the `errors` 5066 array describing why the transaction was aborted. 5067 **/ 5068 abort: function (msg) { 5069 this._pending = null; 5070 this._pendingCSS = null; 5071 this._pollTimer = clearTimeout(this._pollTimer); 5072 this._queue = []; 5073 this._reqsWaiting = 0; 5074 5075 this.errors.push({error: msg || 'Aborted'}); 5076 this._finish(); 5077 }, 5078 5079 /** 5080 Begins execting the transaction. 5081 5082 There's usually no reason to call this manually, since Get will call it 5083 automatically when other pending transactions have finished. If you really 5084 want to execute your transaction before Get does, you can, but be aware that 5085 this transaction's scripts may end up executing before the scripts in other 5086 pending transactions. 5087 5088 If the transaction is already executing, the specified callback (if any) 5089 will be queued and called after execution finishes. If the transaction has 5090 already finished, the callback will be called immediately (the transaction 5091 will not be executed again). 5092 5093 @method execute 5094 @param {Function} callback Callback function to execute after all requests 5095 in the transaction are complete, or after the transaction is aborted. 5096 **/ 5097 execute: function (callback) { 5098 var self = this, 5099 requests = self.requests, 5100 state = self._state, 5101 i, len, queue, req; 5102 5103 if (state === 'done') { 5104 callback && callback(self.errors.length ? self.errors : null, self); 5105 return; 5106 } else { 5107 callback && self._callbacks.push(callback); 5108 5109 if (state === 'executing') { 5110 return; 5111 } 5112 } 5113 5114 self._state = 'executing'; 5115 self._queue = queue = []; 5116 5117 if (self.options.timeout) { 5118 self._timeout = setTimeout(function () { 5119 self.abort('Timeout'); 5120 }, self.options.timeout); 5121 } 5122 5123 self._reqsWaiting = requests.length; 5124 5125 for (i = 0, len = requests.length; i < len; ++i) { 5126 req = requests[i]; 5127 5128 if (req.async || req.type === 'css') { 5129 // No need to queue CSS or fully async JS. 5130 self._insert(req); 5131 } else { 5132 queue.push(req); 5133 } 5134 } 5135 5136 self._next(); 5137 }, 5138 5139 /** 5140 Manually purges any `<script>` or `<link>` nodes this transaction has 5141 created. 5142 5143 Be careful when purging a transaction that contains CSS requests, since 5144 removing `<link>` nodes will also remove any styles they applied. 5145 5146 @method purge 5147 **/ 5148 purge: function () { 5149 Get._purge(this.nodes); 5150 }, 5151 5152 // -- Protected Methods ---------------------------------------------------- 5153 _createNode: function (name, attrs, doc) { 5154 var node = doc.createElement(name), 5155 attr, testEl; 5156 5157 if (!CUSTOM_ATTRS) { 5158 // IE6 and IE7 expect property names rather than attribute names for 5159 // certain attributes. Rather than sniffing, we do a quick feature 5160 // test the first time _createNode() runs to determine whether we 5161 // need to provide a workaround. 5162 testEl = doc.createElement('div'); 5163 testEl.setAttribute('class', 'a'); 5164 5165 CUSTOM_ATTRS = testEl.className === 'a' ? {} : { 5166 'for' : 'htmlFor', 5167 'class': 'className' 5168 }; 5169 } 5170 5171 for (attr in attrs) { 5172 if (attrs.hasOwnProperty(attr)) { 5173 node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]); 5174 } 5175 } 5176 5177 return node; 5178 }, 5179 5180 _finish: function () { 5181 var errors = this.errors.length ? this.errors : null, 5182 options = this.options, 5183 thisObj = options.context || this, 5184 data, i, len; 5185 5186 if (this._state === 'done') { 5187 return; 5188 } 5189 5190 this._state = 'done'; 5191 5192 for (i = 0, len = this._callbacks.length; i < len; ++i) { 5193 this._callbacks[i].call(thisObj, errors, this); 5194 } 5195 5196 data = this._getEventData(); 5197 5198 if (errors) { 5199 if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') { 5200 options.onTimeout.call(thisObj, data); 5201 } 5202 5203 if (options.onFailure) { 5204 options.onFailure.call(thisObj, data); 5205 } 5206 } else if (options.onSuccess) { 5207 options.onSuccess.call(thisObj, data); 5208 } 5209 5210 if (options.onEnd) { 5211 options.onEnd.call(thisObj, data); 5212 } 5213 5214 if (options._onFinish) { 5215 options._onFinish(); 5216 } 5217 }, 5218 5219 _getEventData: function (req) { 5220 if (req) { 5221 // This merge is necessary for backcompat. I hate it. 5222 return Y.merge(this, { 5223 abort : this.abort, // have to copy these because the prototype isn't preserved 5224 purge : this.purge, 5225 request: req, 5226 url : req.url, 5227 win : req.win 5228 }); 5229 } else { 5230 return this; 5231 } 5232 }, 5233 5234 _getInsertBefore: function (req) { 5235 var doc = req.doc, 5236 el = req.insertBefore, 5237 cache, docStamp; 5238 5239 if (el) { 5240 return typeof el === 'string' ? doc.getElementById(el) : el; 5241 } 5242 5243 cache = Get._insertCache; 5244 docStamp = Y.stamp(doc); 5245 5246 if ((el = cache[docStamp])) { // assignment 5247 return el; 5248 } 5249 5250 // Inserting before a <base> tag apparently works around an IE bug 5251 // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what 5252 // bug that is, exactly. Better safe than sorry? 5253 if ((el = doc.getElementsByTagName('base')[0])) { // assignment 5254 return (cache[docStamp] = el); 5255 } 5256 5257 // Look for a <head> element. 5258 el = doc.head || doc.getElementsByTagName('head')[0]; 5259 5260 if (el) { 5261 // Create a marker node at the end of <head> to use as an insertion 5262 // point. Inserting before this node will ensure that all our CSS 5263 // gets inserted in the correct order, to maintain style precedence. 5264 el.appendChild(doc.createTextNode('')); 5265 return (cache[docStamp] = el.lastChild); 5266 } 5267 5268 // If all else fails, just insert before the first script node on the 5269 // page, which is virtually guaranteed to exist. 5270 return (cache[docStamp] = doc.getElementsByTagName('script')[0]); 5271 }, 5272 5273 _insert: function (req) { 5274 var env = Get._env, 5275 insertBefore = this._getInsertBefore(req), 5276 isScript = req.type === 'js', 5277 node = req.node, 5278 self = this, 5279 ua = Y.UA, 5280 cssTimeout, nodeType; 5281 5282 if (!node) { 5283 if (isScript) { 5284 nodeType = 'script'; 5285 } else if (!env.cssLoad && ua.gecko) { 5286 nodeType = 'style'; 5287 } else { 5288 nodeType = 'link'; 5289 } 5290 5291 node = req.node = this._createNode(nodeType, req.attributes, 5292 req.doc); 5293 } 5294 5295 function onError() { 5296 self._progress('Failed to load ' + req.url, req); 5297 } 5298 5299 function onLoad() { 5300 if (cssTimeout) { 5301 clearTimeout(cssTimeout); 5302 } 5303 5304 self._progress(null, req); 5305 } 5306 5307 // Deal with script asynchronicity. 5308 if (isScript) { 5309 node.setAttribute('src', req.url); 5310 5311 if (req.async) { 5312 // Explicitly indicate that we want the browser to execute this 5313 // script asynchronously. This is necessary for older browsers 5314 // like Firefox <4. 5315 node.async = true; 5316 } else { 5317 if (env.async) { 5318 // This browser treats injected scripts as async by default 5319 // (standard HTML5 behavior) but asynchronous loading isn't 5320 // desired, so tell the browser not to mark this script as 5321 // async. 5322 node.async = false; 5323 } 5324 5325 // If this browser doesn't preserve script execution order based 5326 // on insertion order, we'll need to avoid inserting other 5327 // scripts until this one finishes loading. 5328 if (!env.preservesScriptOrder) { 5329 this._pending = req; 5330 } 5331 } 5332 } else { 5333 if (!env.cssLoad && ua.gecko) { 5334 // In Firefox <9, we can import the requested URL into a <style> 5335 // node and poll for the existence of node.sheet.cssRules. This 5336 // gives us a reliable way to determine CSS load completion that 5337 // also works for cross-domain stylesheets. 5338 // 5339 // Props to Zach Leatherman for calling my attention to this 5340 // technique. 5341 node.innerHTML = (req.attributes.charset ? 5342 '@charset "' + req.attributes.charset + '";' : '') + 5343 '@import "' + req.url + '";'; 5344 } else { 5345 node.setAttribute('href', req.url); 5346 } 5347 } 5348 5349 // Inject the node. 5350 if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) { 5351 // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode. 5352 node.onreadystatechange = function () { 5353 if (/loaded|complete/.test(node.readyState)) { 5354 node.onreadystatechange = null; 5355 onLoad(); 5356 } 5357 }; 5358 } else if (!isScript && !env.cssLoad) { 5359 // CSS on Firefox <9 or WebKit. 5360 this._poll(req); 5361 } else { 5362 // Script or CSS on everything else. Using DOM 0 events because that 5363 // evens the playing field with older IEs. 5364 5365 if (ua.ie >= 10) { 5366 5367 // We currently need to introduce a timeout for IE10, since it 5368 // calls onerror/onload synchronously for 304s - messing up existing 5369 // program flow. 5370 5371 // Remove this block if the following bug gets fixed by GA 5372 /*jshint maxlen: 1500 */ 5373 // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload 5374 node.onerror = function() { setTimeout(onError, 0); }; 5375 node.onload = function() { setTimeout(onLoad, 0); }; 5376 } else { 5377 node.onerror = onError; 5378 node.onload = onLoad; 5379 } 5380 5381 // If this browser doesn't fire an event when CSS fails to load, 5382 // fail after a timeout to avoid blocking the transaction queue. 5383 if (!env.cssFail && !isScript) { 5384 cssTimeout = setTimeout(onError, req.timeout || 3000); 5385 } 5386 } 5387 5388 this.nodes.push(node); 5389 insertBefore.parentNode.insertBefore(node, insertBefore); 5390 }, 5391 5392 _next: function () { 5393 if (this._pending) { 5394 return; 5395 } 5396 5397 // If there are requests in the queue, insert the next queued request. 5398 // Otherwise, if we're waiting on already-inserted requests to finish, 5399 // wait longer. If there are no queued requests and we're not waiting 5400 // for anything to load, then we're done! 5401 if (this._queue.length) { 5402 this._insert(this._queue.shift()); 5403 } else if (!this._reqsWaiting) { 5404 this._finish(); 5405 } 5406 }, 5407 5408 _poll: function (newReq) { 5409 var self = this, 5410 pendingCSS = self._pendingCSS, 5411 isWebKit = Y.UA.webkit, 5412 i, hasRules, j, nodeHref, req, sheets; 5413 5414 if (newReq) { 5415 pendingCSS || (pendingCSS = self._pendingCSS = []); 5416 pendingCSS.push(newReq); 5417 5418 if (self._pollTimer) { 5419 // A poll timeout is already pending, so no need to create a 5420 // new one. 5421 return; 5422 } 5423 } 5424 5425 self._pollTimer = null; 5426 5427 // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s 5428 // will still be treated as a success. There's no good workaround for 5429 // this. 5430 5431 for (i = 0; i < pendingCSS.length; ++i) { 5432 req = pendingCSS[i]; 5433 5434 if (isWebKit) { 5435 // Look for a stylesheet matching the pending URL. 5436 sheets = req.doc.styleSheets; 5437 j = sheets.length; 5438 nodeHref = req.node.href; 5439 5440 while (--j >= 0) { 5441 if (sheets[j].href === nodeHref) { 5442 pendingCSS.splice(i, 1); 5443 i -= 1; 5444 self._progress(null, req); 5445 break; 5446 } 5447 } 5448 } else { 5449 // Many thanks to Zach Leatherman for calling my attention to 5450 // the @import-based cross-domain technique used here, and to 5451 // Oleg Slobodskoi for an earlier same-domain implementation. 5452 // 5453 // See Zach's blog for more details: 5454 // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/ 5455 try { 5456 // We don't really need to store this value since we never 5457 // use it again, but if we don't store it, Closure Compiler 5458 // assumes the code is useless and removes it. 5459 hasRules = !!req.node.sheet.cssRules; 5460 5461 // If we get here, the stylesheet has loaded. 5462 pendingCSS.splice(i, 1); 5463 i -= 1; 5464 self._progress(null, req); 5465 } catch (ex) { 5466 // An exception means the stylesheet is still loading. 5467 } 5468 } 5469 } 5470 5471 if (pendingCSS.length) { 5472 self._pollTimer = setTimeout(function () { 5473 self._poll.call(self); 5474 }, self.options.pollInterval); 5475 } 5476 }, 5477 5478 _progress: function (err, req) { 5479 var options = this.options; 5480 5481 if (err) { 5482 req.error = err; 5483 5484 this.errors.push({ 5485 error : err, 5486 request: req 5487 }); 5488 5489 Y.log(err, 'error', 'get'); 5490 } 5491 5492 req.node._yuiget_finished = req.finished = true; 5493 5494 if (options.onProgress) { 5495 options.onProgress.call(options.context || this, 5496 this._getEventData(req)); 5497 } 5498 5499 if (req.autopurge) { 5500 // Pre-3.5.0 Get always excludes the most recent node from an 5501 // autopurge. I find this odd, but I'm keeping that behavior for 5502 // the sake of backcompat. 5503 Get._autoPurge(this.options.purgethreshold); 5504 Get._purgeNodes.push(req.node); 5505 } 5506 5507 if (this._pending === req) { 5508 this._pending = null; 5509 } 5510 5511 this._reqsWaiting -= 1; 5512 5513 this._next(); 5514 } 5515 }; 5516 5517 5518 }, '3.17.2', {"requires": ["yui-base"]}); 5519 YUI.add('features', function (Y, NAME) { 5520 5521 var feature_tests = {}; 5522 5523 /** 5524 Contains the core of YUI's feature test architecture. 5525 @module features 5526 */ 5527 5528 /** 5529 * Feature detection 5530 * @class Features 5531 * @static 5532 */ 5533 5534 Y.mix(Y.namespace('Features'), { 5535 5536 /** 5537 * Object hash of all registered feature tests 5538 * @property tests 5539 * @type Object 5540 */ 5541 tests: feature_tests, 5542 5543 /** 5544 * Add a test to the system 5545 * 5546 * ``` 5547 * Y.Features.add("load", "1", {}); 5548 * ``` 5549 * 5550 * @method add 5551 * @param {String} cat The category, right now only 'load' is supported 5552 * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3 5553 * @param {Object} o Object containing test properties 5554 * @param {String} o.name The name of the test 5555 * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance 5556 * @param {String} o.trigger The module that triggers this test. 5557 */ 5558 add: function(cat, name, o) { 5559 feature_tests[cat] = feature_tests[cat] || {}; 5560 feature_tests[cat][name] = o; 5561 }, 5562 /** 5563 * Execute all tests of a given category and return the serialized results 5564 * 5565 * ``` 5566 * caps=1:1;2:1;3:0 5567 * ``` 5568 * @method all 5569 * @param {String} cat The category to execute 5570 * @param {Array} args The arguments to pass to the test function 5571 * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0 5572 */ 5573 all: function(cat, args) { 5574 var cat_o = feature_tests[cat], 5575 // results = {}; 5576 result = []; 5577 if (cat_o) { 5578 Y.Object.each(cat_o, function(v, k) { 5579 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0)); 5580 }); 5581 } 5582 5583 return (result.length) ? result.join(';') : ''; 5584 }, 5585 /** 5586 * Run a specific test and return a Boolean response. 5587 * 5588 * ``` 5589 * Y.Features.test("load", "1"); 5590 * ``` 5591 * 5592 * @method test 5593 * @param {String} cat The category of the test to run 5594 * @param {String} name The name of the test to run 5595 * @param {Array} args The arguments to pass to the test function 5596 * @return {Boolean} True or false if the test passed/failed. 5597 */ 5598 test: function(cat, name, args) { 5599 args = args || []; 5600 var result, ua, test, 5601 cat_o = feature_tests[cat], 5602 feature = cat_o && cat_o[name]; 5603 5604 if (!feature) { 5605 Y.log('Feature test ' + cat + ', ' + name + ' not found'); 5606 } else { 5607 5608 result = feature.result; 5609 5610 if (Y.Lang.isUndefined(result)) { 5611 5612 ua = feature.ua; 5613 if (ua) { 5614 result = (Y.UA[ua]); 5615 } 5616 5617 test = feature.test; 5618 if (test && ((!ua) || result)) { 5619 result = test.apply(Y, args); 5620 } 5621 5622 feature.result = result; 5623 } 5624 } 5625 5626 return result; 5627 } 5628 }); 5629 5630 // Y.Features.add("load", "1", {}); 5631 // Y.Features.test("load", "1"); 5632 // caps=1:1;2:0;3:1; 5633 5634 /* This file is auto-generated by (yogi.js loader --mix --yes) */ 5635 /*jshint maxlen:900, eqeqeq: false */ 5636 var add = Y.Features.add; 5637 // app-transitions-native 5638 add('load', '0', { 5639 "name": "app-transitions-native", 5640 "test": function (Y) { 5641 var doc = Y.config.doc, 5642 node = doc ? doc.documentElement : null; 5643 5644 if (node && node.style) { 5645 return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 5646 } 5647 5648 return false; 5649 }, 5650 "trigger": "app-transitions" 5651 }); 5652 // autocomplete-list-keys 5653 add('load', '1', { 5654 "name": "autocomplete-list-keys", 5655 "test": function (Y) { 5656 // Only add keyboard support to autocomplete-list if this doesn't appear to 5657 // be an iOS or Android-based mobile device. 5658 // 5659 // There's currently no feasible way to actually detect whether a device has 5660 // a hardware keyboard, so this sniff will have to do. It can easily be 5661 // overridden by manually loading the autocomplete-list-keys module. 5662 // 5663 // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari 5664 // doesn't fire the keyboard events used by AutoCompleteList, so there's 5665 // no point loading the -keys module even when a bluetooth keyboard may be 5666 // available. 5667 return !(Y.UA.ios || Y.UA.android); 5668 }, 5669 "trigger": "autocomplete-list" 5670 }); 5671 // dd-gestures 5672 add('load', '2', { 5673 "name": "dd-gestures", 5674 "trigger": "dd-drag", 5675 "ua": "touchEnabled" 5676 }); 5677 // dom-style-ie 5678 add('load', '3', { 5679 "name": "dom-style-ie", 5680 "test": function (Y) { 5681 5682 var testFeature = Y.Features.test, 5683 addFeature = Y.Features.add, 5684 WINDOW = Y.config.win, 5685 DOCUMENT = Y.config.doc, 5686 DOCUMENT_ELEMENT = 'documentElement', 5687 ret = false; 5688 5689 addFeature('style', 'computedStyle', { 5690 test: function() { 5691 return WINDOW && 'getComputedStyle' in WINDOW; 5692 } 5693 }); 5694 5695 addFeature('style', 'opacity', { 5696 test: function() { 5697 return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style; 5698 } 5699 }); 5700 5701 ret = (!testFeature('style', 'opacity') && 5702 !testFeature('style', 'computedStyle')); 5703 5704 return ret; 5705 }, 5706 "trigger": "dom-style" 5707 }); 5708 // editor-para-ie 5709 add('load', '4', { 5710 "name": "editor-para-ie", 5711 "trigger": "editor-para", 5712 "ua": "ie", 5713 "when": "instead" 5714 }); 5715 // event-base-ie 5716 add('load', '5', { 5717 "name": "event-base-ie", 5718 "test": function(Y) { 5719 var imp = Y.config.doc && Y.config.doc.implementation; 5720 return (imp && (!imp.hasFeature('Events', '2.0'))); 5721 }, 5722 "trigger": "node-base" 5723 }); 5724 // graphics-canvas 5725 add('load', '6', { 5726 "name": "graphics-canvas", 5727 "test": function(Y) { 5728 var DOCUMENT = Y.config.doc, 5729 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 5730 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5731 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5732 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 5733 }, 5734 "trigger": "graphics" 5735 }); 5736 // graphics-canvas-default 5737 add('load', '7', { 5738 "name": "graphics-canvas-default", 5739 "test": function(Y) { 5740 var DOCUMENT = Y.config.doc, 5741 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 5742 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5743 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5744 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 5745 }, 5746 "trigger": "graphics" 5747 }); 5748 // graphics-svg 5749 add('load', '8', { 5750 "name": "graphics-svg", 5751 "test": function(Y) { 5752 var DOCUMENT = Y.config.doc, 5753 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 5754 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5755 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5756 5757 return svg && (useSVG || !canvas); 5758 }, 5759 "trigger": "graphics" 5760 }); 5761 // graphics-svg-default 5762 add('load', '9', { 5763 "name": "graphics-svg-default", 5764 "test": function(Y) { 5765 var DOCUMENT = Y.config.doc, 5766 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 5767 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 5768 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 5769 5770 return svg && (useSVG || !canvas); 5771 }, 5772 "trigger": "graphics" 5773 }); 5774 // graphics-vml 5775 add('load', '10', { 5776 "name": "graphics-vml", 5777 "test": function(Y) { 5778 var DOCUMENT = Y.config.doc, 5779 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 5780 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 5781 }, 5782 "trigger": "graphics" 5783 }); 5784 // graphics-vml-default 5785 add('load', '11', { 5786 "name": "graphics-vml-default", 5787 "test": function(Y) { 5788 var DOCUMENT = Y.config.doc, 5789 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 5790 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 5791 }, 5792 "trigger": "graphics" 5793 }); 5794 // history-hash-ie 5795 add('load', '12', { 5796 "name": "history-hash-ie", 5797 "test": function (Y) { 5798 var docMode = Y.config.doc && Y.config.doc.documentMode; 5799 5800 return Y.UA.ie && (!('onhashchange' in Y.config.win) || 5801 !docMode || docMode < 8); 5802 }, 5803 "trigger": "history-hash" 5804 }); 5805 // io-nodejs 5806 add('load', '13', { 5807 "name": "io-nodejs", 5808 "trigger": "io-base", 5809 "ua": "nodejs" 5810 }); 5811 // json-parse-shim 5812 add('load', '14', { 5813 "name": "json-parse-shim", 5814 "test": function (Y) { 5815 var _JSON = Y.config.global.JSON, 5816 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 5817 nativeSupport = Y.config.useNativeJSONParse !== false && !!Native; 5818 5819 function workingNative( k, v ) { 5820 return k === "ok" ? true : v; 5821 } 5822 5823 // Double check basic functionality. This is mainly to catch early broken 5824 // implementations of the JSON API in Firefox 3.1 beta1 and beta2 5825 if ( nativeSupport ) { 5826 try { 5827 nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok; 5828 } 5829 catch ( e ) { 5830 nativeSupport = false; 5831 } 5832 } 5833 5834 return !nativeSupport; 5835 }, 5836 "trigger": "json-parse" 5837 }); 5838 // json-stringify-shim 5839 add('load', '15', { 5840 "name": "json-stringify-shim", 5841 "test": function (Y) { 5842 var _JSON = Y.config.global.JSON, 5843 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 5844 nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native; 5845 5846 // Double check basic native functionality. This is primarily to catch broken 5847 // early JSON API implementations in Firefox 3.1 beta1 and beta2. 5848 if ( nativeSupport ) { 5849 try { 5850 nativeSupport = ( '0' === Native.stringify(0) ); 5851 } catch ( e ) { 5852 nativeSupport = false; 5853 } 5854 } 5855 5856 5857 return !nativeSupport; 5858 }, 5859 "trigger": "json-stringify" 5860 }); 5861 // scrollview-base-ie 5862 add('load', '16', { 5863 "name": "scrollview-base-ie", 5864 "trigger": "scrollview-base", 5865 "ua": "ie" 5866 }); 5867 // selector-css2 5868 add('load', '17', { 5869 "name": "selector-css2", 5870 "test": function (Y) { 5871 var DOCUMENT = Y.config.doc, 5872 ret = DOCUMENT && !('querySelectorAll' in DOCUMENT); 5873 5874 return ret; 5875 }, 5876 "trigger": "selector" 5877 }); 5878 // transition-timer 5879 add('load', '18', { 5880 "name": "transition-timer", 5881 "test": function (Y) { 5882 var DOCUMENT = Y.config.doc, 5883 node = (DOCUMENT) ? DOCUMENT.documentElement: null, 5884 ret = true; 5885 5886 if (node && node.style) { 5887 ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 5888 } 5889 5890 return ret; 5891 }, 5892 "trigger": "transition" 5893 }); 5894 // widget-base-ie 5895 add('load', '19', { 5896 "name": "widget-base-ie", 5897 "trigger": "widget-base", 5898 "ua": "ie" 5899 }); 5900 // yql-jsonp 5901 add('load', '20', { 5902 "name": "yql-jsonp", 5903 "test": function (Y) { 5904 /* Only load the JSONP module when not in nodejs or winjs 5905 TODO Make the winjs module a CORS module 5906 */ 5907 return (!Y.UA.nodejs && !Y.UA.winjs); 5908 }, 5909 "trigger": "yql" 5910 }); 5911 // yql-nodejs 5912 add('load', '21', { 5913 "name": "yql-nodejs", 5914 "trigger": "yql", 5915 "ua": "nodejs" 5916 }); 5917 // yql-winjs 5918 add('load', '22', { 5919 "name": "yql-winjs", 5920 "trigger": "yql", 5921 "ua": "winjs" 5922 }); 5923 5924 }, '3.17.2', {"requires": ["yui-base"]}); 5925 YUI.add('intl-base', function (Y, NAME) { 5926 5927 /** 5928 * The Intl utility provides a central location for managing sets of 5929 * localized resources (strings and formatting patterns). 5930 * 5931 * @class Intl 5932 * @uses EventTarget 5933 * @static 5934 */ 5935 5936 var SPLIT_REGEX = /[, ]/; 5937 5938 Y.mix(Y.namespace('Intl'), { 5939 5940 /** 5941 * Returns the language among those available that 5942 * best matches the preferred language list, using the Lookup 5943 * algorithm of BCP 47. 5944 * If none of the available languages meets the user's preferences, 5945 * then "" is returned. 5946 * Extended language ranges are not supported. 5947 * 5948 * @method lookupBestLang 5949 * @param {String[] | String} preferredLanguages The list of preferred 5950 * languages in descending preference order, represented as BCP 47 5951 * language tags. A string array or a comma-separated list. 5952 * @param {String[]} availableLanguages The list of languages 5953 * that the application supports, represented as BCP 47 language 5954 * tags. 5955 * 5956 * @return {String} The available language that best matches the 5957 * preferred language list, or "". 5958 * @since 3.1.0 5959 */ 5960 lookupBestLang: function(preferredLanguages, availableLanguages) { 5961 5962 var i, language, result, index; 5963 5964 // check whether the list of available languages contains language; 5965 // if so return it 5966 function scan(language) { 5967 var i; 5968 for (i = 0; i < availableLanguages.length; i += 1) { 5969 if (language.toLowerCase() === 5970 availableLanguages[i].toLowerCase()) { 5971 return availableLanguages[i]; 5972 } 5973 } 5974 } 5975 5976 if (Y.Lang.isString(preferredLanguages)) { 5977 preferredLanguages = preferredLanguages.split(SPLIT_REGEX); 5978 } 5979 5980 for (i = 0; i < preferredLanguages.length; i += 1) { 5981 language = preferredLanguages[i]; 5982 if (!language || language === '*') { 5983 continue; 5984 } 5985 // check the fallback sequence for one language 5986 while (language.length > 0) { 5987 result = scan(language); 5988 if (result) { 5989 return result; 5990 } else { 5991 index = language.lastIndexOf('-'); 5992 if (index >= 0) { 5993 language = language.substring(0, index); 5994 // one-character subtags get cut along with the 5995 // following subtag 5996 if (index >= 2 && language.charAt(index - 2) === '-') { 5997 language = language.substring(0, index - 2); 5998 } 5999 } else { 6000 // nothing available for this language 6001 break; 6002 } 6003 } 6004 } 6005 } 6006 6007 return ''; 6008 } 6009 }); 6010 6011 6012 }, '3.17.2', {"requires": ["yui-base"]}); 6013 YUI.add('yui-log', function (Y, NAME) { 6014 6015 /** 6016 * Provides console log capability and exposes a custom event for 6017 * console implementations. This module is a `core` YUI module, 6018 * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>. 6019 * 6020 * @module yui 6021 * @submodule yui-log 6022 */ 6023 6024 var INSTANCE = Y, 6025 LOGEVENT = 'yui:log', 6026 UNDEFINED = 'undefined', 6027 LEVELS = { debug: 1, 6028 info: 2, 6029 warn: 4, 6030 error: 8 }; 6031 6032 /** 6033 * If the 'debug' config is true, a 'yui:log' event will be 6034 * dispatched, which the Console widget and anything else 6035 * can consume. If the 'useBrowserConsole' config is true, it will 6036 * write to the browser console if available. YUI-specific log 6037 * messages will only be present in the -debug versions of the 6038 * JS files. The build system is supposed to remove log statements 6039 * from the raw and minified versions of the files. 6040 * 6041 * @method log 6042 * @for YUI 6043 * @param {String} msg The message to log. 6044 * @param {String} cat The log category for the message. Default 6045 * categories are "info", "warn", "error", "debug". 6046 * Custom categories can be used as well. (opt). 6047 * @param {String} src The source of the the message (opt). 6048 * @param {boolean} silent If true, the log event won't fire. 6049 * @return {YUI} YUI instance. 6050 */ 6051 INSTANCE.log = function(msg, cat, src, silent) { 6052 var bail, excl, incl, m, f, minlevel, 6053 Y = INSTANCE, 6054 c = Y.config, 6055 publisher = (Y.fire) ? Y : YUI.Env.globalEvents; 6056 // suppress log message if the config is off or the event stack 6057 // or the event call stack contains a consumer of the yui:log event 6058 if (c.debug) { 6059 // apply source filters 6060 src = src || ""; 6061 if (typeof src !== "undefined") { 6062 excl = c.logExclude; 6063 incl = c.logInclude; 6064 if (incl && !(src in incl)) { 6065 bail = 1; 6066 } else if (incl && (src in incl)) { 6067 bail = !incl[src]; 6068 } else if (excl && (src in excl)) { 6069 bail = excl[src]; 6070 } 6071 6072 // Set a default category of info if the category was not defined. 6073 if ((typeof cat === 'undefined')) { 6074 cat = 'info'; 6075 } 6076 6077 // Determine the current minlevel as defined in configuration 6078 Y.config.logLevel = Y.config.logLevel || 'debug'; 6079 minlevel = LEVELS[Y.config.logLevel.toLowerCase()]; 6080 6081 if (cat in LEVELS && LEVELS[cat] < minlevel) { 6082 // Skip this message if the we don't meet the defined minlevel 6083 bail = 1; 6084 } 6085 } 6086 if (!bail) { 6087 if (c.useBrowserConsole) { 6088 m = (src) ? src + ': ' + msg : msg; 6089 if (Y.Lang.isFunction(c.logFn)) { 6090 c.logFn.call(Y, msg, cat, src); 6091 } else if (typeof console !== UNDEFINED && console.log) { 6092 f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log'; 6093 console[f](m); 6094 } else if (typeof opera !== UNDEFINED) { 6095 opera.postError(m); 6096 } 6097 } 6098 6099 if (publisher && !silent) { 6100 6101 if (publisher === Y && (!publisher.getEvent(LOGEVENT))) { 6102 publisher.publish(LOGEVENT, { 6103 broadcast: 2 6104 }); 6105 } 6106 6107 publisher.fire(LOGEVENT, { 6108 msg: msg, 6109 cat: cat, 6110 src: src 6111 }); 6112 } 6113 } 6114 } 6115 6116 return Y; 6117 }; 6118 6119 /** 6120 * Write a system message. This message will be preserved in the 6121 * minified and raw versions of the YUI files, unlike log statements. 6122 * @method message 6123 * @for YUI 6124 * @param {String} msg The message to log. 6125 * @param {String} cat The log category for the message. Default 6126 * categories are "info", "warn", "error", "debug". 6127 * Custom categories can be used as well. (opt). 6128 * @param {String} src The source of the the message (opt). 6129 * @param {boolean} silent If true, the log event won't fire. 6130 * @return {YUI} YUI instance. 6131 */ 6132 INSTANCE.message = function() { 6133 return INSTANCE.log.apply(INSTANCE, arguments); 6134 }; 6135 6136 6137 }, '3.17.2', {"requires": ["yui-base"]}); 6138 YUI.add('yui-later', function (Y, NAME) { 6139 6140 /** 6141 * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module, 6142 * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>. 6143 * 6144 * @module yui 6145 * @submodule yui-later 6146 */ 6147 6148 var NO_ARGS = []; 6149 6150 /** 6151 * Executes the supplied function in the context of the supplied 6152 * object 'when' milliseconds later. Executes the function a 6153 * single time unless periodic is set to true. 6154 * @for YUI 6155 * @method later 6156 * @param when {Number} the number of milliseconds to wait until the fn 6157 * is executed. 6158 * @param o the context object. 6159 * @param fn {Function|String} the function to execute or the name of 6160 * the method in the 'o' object to execute. 6161 * @param data [Array] data that is provided to the function. This 6162 * accepts either a single item or an array. If an array is provided, 6163 * the function is executed with one parameter for each array item. 6164 * If you need to pass a single array parameter, it needs to be wrapped 6165 * in an array [myarray]. 6166 * 6167 * Note: native methods in IE may not have the call and apply methods. 6168 * In this case, it will work, but you are limited to four arguments. 6169 * 6170 * @param periodic {boolean} if true, executes continuously at supplied 6171 * interval until canceled. 6172 * @return {object} a timer object. Call the cancel() method on this 6173 * object to stop the timer. 6174 */ 6175 Y.later = function(when, o, fn, data, periodic) { 6176 when = when || 0; 6177 data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS; 6178 o = o || Y.config.win || Y; 6179 6180 var cancelled = false, 6181 method = (o && Y.Lang.isString(fn)) ? o[fn] : fn, 6182 wrapper = function() { 6183 // IE 8- may execute a setInterval callback one last time 6184 // after clearInterval was called, so in order to preserve 6185 // the cancel() === no more runny-run, we have to jump through 6186 // an extra hoop. 6187 if (!cancelled) { 6188 if (!method.apply) { 6189 method(data[0], data[1], data[2], data[3]); 6190 } else { 6191 method.apply(o, data || NO_ARGS); 6192 } 6193 } 6194 }, 6195 id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when); 6196 6197 return { 6198 id: id, 6199 interval: periodic, 6200 cancel: function() { 6201 cancelled = true; 6202 if (this.interval) { 6203 clearInterval(id); 6204 } else { 6205 clearTimeout(id); 6206 } 6207 } 6208 }; 6209 }; 6210 6211 Y.Lang.later = Y.later; 6212 6213 6214 6215 }, '3.17.2', {"requires": ["yui-base"]}); 6216 YUI.add('loader-base', function (Y, NAME) { 6217 6218 /** 6219 * The YUI loader core 6220 * @module loader 6221 * @submodule loader-base 6222 */ 6223 6224 (function() { 6225 var VERSION = Y.version, 6226 BUILD = '/build/', 6227 ROOT = VERSION + '/', 6228 CDN_BASE = Y.Env.base, 6229 GALLERY_VERSION = 'gallery-2014.05.29-15-46', 6230 TNT = '2in3', 6231 TNT_VERSION = '4', 6232 YUI2_VERSION = '2.9.0', 6233 COMBO_BASE = CDN_BASE + 'combo?', 6234 META = { 6235 version: VERSION, 6236 root: ROOT, 6237 base: Y.Env.base, 6238 comboBase: COMBO_BASE, 6239 skin: { 6240 defaultSkin: 'sam', 6241 base: 'assets/skins/', 6242 path: 'skin.css', 6243 after: [ 6244 'cssreset', 6245 'cssfonts', 6246 'cssgrids', 6247 'cssbase', 6248 'cssreset-context', 6249 'cssfonts-context' 6250 ] 6251 }, 6252 groups: {}, 6253 patterns: {} 6254 }, 6255 groups = META.groups, 6256 yui2Update = function(tnt, yui2, config) { 6257 var root = TNT + '.' + 6258 (tnt || TNT_VERSION) + '/' + 6259 (yui2 || YUI2_VERSION) + BUILD, 6260 base = (config && config.base) ? config.base : CDN_BASE, 6261 combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE; 6262 6263 groups.yui2.base = base + root; 6264 groups.yui2.root = root; 6265 groups.yui2.comboBase = combo; 6266 }, 6267 galleryUpdate = function(tag, config) { 6268 var root = (tag || GALLERY_VERSION) + BUILD, 6269 base = (config && config.base) ? config.base : CDN_BASE, 6270 combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE; 6271 6272 groups.gallery.base = base + root; 6273 groups.gallery.root = root; 6274 groups.gallery.comboBase = combo; 6275 }; 6276 6277 6278 groups[VERSION] = {}; 6279 6280 groups.gallery = { 6281 ext: false, 6282 combine: true, 6283 comboBase: COMBO_BASE, 6284 update: galleryUpdate, 6285 patterns: { 6286 'gallery-': {}, 6287 'lang/gallery-': {}, 6288 'gallerycss-': { 6289 type: 'css' 6290 } 6291 } 6292 }; 6293 6294 groups.yui2 = { 6295 combine: true, 6296 ext: false, 6297 comboBase: COMBO_BASE, 6298 update: yui2Update, 6299 patterns: { 6300 'yui2-': { 6301 configFn: function(me) { 6302 if (/-skin|reset|fonts|grids|base/.test(me.name)) { 6303 me.type = 'css'; 6304 me.path = me.path.replace(/\.js/, '.css'); 6305 // this makes skins in builds earlier than 6306 // 2.6.0 work as long as combine is false 6307 me.path = me.path.replace(/\/yui2-skin/, 6308 '/assets/skins/sam/yui2-skin'); 6309 } 6310 } 6311 } 6312 } 6313 }; 6314 6315 galleryUpdate(); 6316 yui2Update(); 6317 6318 if (YUI.Env[VERSION]) { 6319 Y.mix(META, YUI.Env[VERSION], false, [ 6320 'modules', 6321 'groups', 6322 'skin' 6323 ], 0, true); 6324 } 6325 6326 YUI.Env[VERSION] = META; 6327 }()); 6328 /*jslint forin: true, maxlen: 350 */ 6329 6330 /** 6331 * Loader dynamically loads script and css files. It includes the dependency 6332 * information for the version of the library in use, and will automatically pull in 6333 * dependencies for the modules requested. It can also load the 6334 * files from the Yahoo! CDN, and it can utilize the combo service provided on 6335 * this network to reduce the number of http connections required to download 6336 * YUI files. 6337 * 6338 * @module loader 6339 * @main loader 6340 * @submodule loader-base 6341 */ 6342 6343 var NOT_FOUND = {}, 6344 NO_REQUIREMENTS = [], 6345 MAX_URL_LENGTH = 1024, 6346 GLOBAL_ENV = YUI.Env, 6347 GLOBAL_LOADED = GLOBAL_ENV._loaded, 6348 CSS = 'css', 6349 JS = 'js', 6350 INTL = 'intl', 6351 DEFAULT_SKIN = 'sam', 6352 VERSION = Y.version, 6353 ROOT_LANG = '', 6354 YObject = Y.Object, 6355 oeach = YObject.each, 6356 yArray = Y.Array, 6357 _queue = GLOBAL_ENV._loaderQueue, 6358 META = GLOBAL_ENV[VERSION], 6359 SKIN_PREFIX = 'skin-', 6360 L = Y.Lang, 6361 ON_PAGE = GLOBAL_ENV.mods, 6362 modulekey, 6363 _path = function(dir, file, type, nomin) { 6364 var path = dir + '/' + file; 6365 if (!nomin) { 6366 path += '-min'; 6367 } 6368 path += '.' + (type || CSS); 6369 6370 return path; 6371 }; 6372 6373 6374 if (!YUI.Env._cssLoaded) { 6375 YUI.Env._cssLoaded = {}; 6376 } 6377 6378 6379 /** 6380 * The component metadata is stored in Y.Env.meta. 6381 * Part of the loader module. 6382 * @property meta 6383 * @for YUI 6384 */ 6385 Y.Env.meta = META; 6386 6387 /** 6388 * Loader dynamically loads script and css files. It includes the dependency 6389 * info for the version of the library in use, and will automatically pull in 6390 * dependencies for the modules requested. It can load the 6391 * files from the Yahoo! CDN, and it can utilize the combo service provided on 6392 * this network to reduce the number of http connections required to download 6393 * YUI files. You can also specify an external, custom combo service to host 6394 * your modules as well. 6395 6396 var Y = YUI(); 6397 var loader = new Y.Loader({ 6398 filter: 'debug', 6399 base: '../../', 6400 root: 'build/', 6401 combine: true, 6402 require: ['node', 'dd', 'console'] 6403 }); 6404 var out = loader.resolve(true); 6405 6406 * If the Loader needs to be patched before it is used for the first time, it 6407 * should be done through the `doBeforeLoader` hook. Simply make the patch 6408 * available via configuration before YUI is loaded: 6409 6410 YUI_config = YUI_config || {}; 6411 YUI_config.doBeforeLoader = function (config) { 6412 var resolve = this.context.Loader.prototype.resolve; 6413 this.context.Loader.prototype.resolve = function () { 6414 // do something here 6415 return resolve.apply(this, arguments); 6416 }; 6417 }; 6418 6419 * @constructor 6420 * @class Loader 6421 * @param {Object} config an optional set of configuration options. 6422 * @param {String} config.base The base dir which to fetch this module from 6423 * @param {String} config.comboBase The Combo service base path. Ex: `http://yui.yahooapis.com/combo?` 6424 * @param {String} config.root The root path to prepend to module names for the combo service. Ex: `2.5.2/build/` 6425 * @param {String|Object} config.filter A filter to apply to result urls. <a href="#property_filter">See filter property</a> 6426 * @param {Object} config.filters Per-component filter specification. If specified for a given component, this overrides the filter config. 6427 * @param {Boolean} config.combine Use a combo service to reduce the number of http connections required to load your dependencies 6428 * @param {Boolean} [config.async=true] Fetch files in async 6429 * @param {Array} config.ignore: A list of modules that should never be dynamically loaded 6430 * @param {Array} config.force A list of modules that should always be loaded when required, even if already present on the page 6431 * @param {HTMLElement|String} config.insertBefore Node or id for a node that should be used as the insertion point for new nodes 6432 * @param {Object} config.jsAttributes Object literal containing attributes to add to script nodes 6433 * @param {Object} config.cssAttributes Object literal containing attributes to add to link nodes 6434 * @param {Number} config.timeout The number of milliseconds before a timeout occurs when dynamically loading nodes. If not set, there is no timeout 6435 * @param {Object} config.context Execution context for all callbacks 6436 * @param {Function} config.onSuccess Callback for the 'success' event 6437 * @param {Function} config.onFailure Callback for the 'failure' event 6438 * @param {Function} config.onTimeout Callback for the 'timeout' event 6439 * @param {Function} config.onProgress Callback executed each time a script or css file is loaded 6440 * @param {Object} config.modules A list of module definitions. See <a href="#method_addModule">Loader.addModule</a> for the supported module metadata 6441 * @param {Object} config.groups A list of group definitions. Each group can contain specific definitions for `base`, `comboBase`, `combine`, and accepts a list of `modules`. 6442 * @param {String} config.2in3 The version of the YUI 2 in 3 wrapper to use. The intrinsic support for YUI 2 modules in YUI 3 relies on versions of the YUI 2 components inside YUI 3 module wrappers. These wrappers change over time to accomodate the issues that arise from running YUI 2 in a YUI 3 sandbox. 6443 * @param {String} config.yui2 When using the 2in3 project, you can select the version of YUI 2 to use. Valid values are `2.2.2`, `2.3.1`, `2.4.1`, `2.5.2`, `2.6.0`, `2.7.0`, `2.8.0`, `2.8.1` and `2.9.0` [default] -- plus all versions of YUI 2 going forward. 6444 * @param {Function} config.doBeforeLoader An optional hook that allows for the patching of the loader instance. The `Y` instance is available as `this.context` and the only argument to the function is the Loader configuration object. 6445 */ 6446 Y.Loader = function(o) { 6447 6448 var self = this; 6449 6450 //Catch no config passed. 6451 o = o || {}; 6452 6453 modulekey = META.md5; 6454 6455 /** 6456 * Internal callback to handle multiple internal insert() calls 6457 * so that css is inserted prior to js 6458 * @property _internalCallback 6459 * @private 6460 */ 6461 // self._internalCallback = null; 6462 6463 /** 6464 * Callback that will be executed when the loader is finished 6465 * with an insert 6466 * @method onSuccess 6467 * @type function 6468 */ 6469 // self.onSuccess = null; 6470 6471 /** 6472 * Callback that will be executed if there is a failure 6473 * @method onFailure 6474 * @type function 6475 */ 6476 // self.onFailure = null; 6477 6478 /** 6479 * Callback executed each time a script or css file is loaded 6480 * @method onProgress 6481 * @type function 6482 */ 6483 // self.onProgress = null; 6484 6485 /** 6486 * Callback that will be executed if a timeout occurs 6487 * @method onTimeout 6488 * @type function 6489 */ 6490 // self.onTimeout = null; 6491 6492 /** 6493 * The execution context for all callbacks 6494 * @property context 6495 * @default {YUI} the YUI instance 6496 */ 6497 self.context = Y; 6498 6499 // Hook that allows the patching of loader 6500 if (o.doBeforeLoader) { 6501 o.doBeforeLoader.apply(self, arguments); 6502 } 6503 6504 /** 6505 * Data that is passed to all callbacks 6506 * @property data 6507 */ 6508 // self.data = null; 6509 6510 /** 6511 * Node reference or id where new nodes should be inserted before 6512 * @property insertBefore 6513 * @type string|HTMLElement 6514 */ 6515 // self.insertBefore = null; 6516 6517 /** 6518 * The charset attribute for inserted nodes 6519 * @property charset 6520 * @type string 6521 * @deprecated , use cssAttributes or jsAttributes. 6522 */ 6523 // self.charset = null; 6524 6525 /** 6526 * An object literal containing attributes to add to link nodes 6527 * @property cssAttributes 6528 * @type object 6529 */ 6530 // self.cssAttributes = null; 6531 6532 /** 6533 * An object literal containing attributes to add to script nodes 6534 * @property jsAttributes 6535 * @type object 6536 */ 6537 // self.jsAttributes = null; 6538 6539 /** 6540 * The base directory. 6541 * @property base 6542 * @type string 6543 * @default http://yui.yahooapis.com/[YUI VERSION]/build/ 6544 */ 6545 self.base = Y.Env.meta.base + Y.Env.meta.root; 6546 6547 /** 6548 * Base path for the combo service 6549 * @property comboBase 6550 * @type string 6551 * @default http://yui.yahooapis.com/combo? 6552 */ 6553 self.comboBase = Y.Env.meta.comboBase; 6554 6555 /* 6556 * Base path for language packs. 6557 */ 6558 // self.langBase = Y.Env.meta.langBase; 6559 // self.lang = ""; 6560 6561 /** 6562 * If configured, the loader will attempt to use the combo 6563 * service for YUI resources and configured external resources. 6564 * @property combine 6565 * @type boolean 6566 * @default true if a base dir isn't in the config 6567 */ 6568 self.combine = o.base && 6569 (o.base.indexOf(self.comboBase.substr(0, 20)) > -1); 6570 6571 /** 6572 * The default seperator to use between files in a combo URL 6573 * @property comboSep 6574 * @type {String} 6575 * @default Ampersand 6576 */ 6577 self.comboSep = '&'; 6578 /** 6579 * Max url length for combo urls. The default is 1024. This is the URL 6580 * limit for the Yahoo! hosted combo servers. If consuming 6581 * a different combo service that has a different URL limit 6582 * it is possible to override this default by supplying 6583 * the maxURLLength config option. The config option will 6584 * only take effect if lower than the default. 6585 * 6586 * @property maxURLLength 6587 * @type int 6588 */ 6589 self.maxURLLength = MAX_URL_LENGTH; 6590 6591 /** 6592 * Ignore modules registered on the YUI global 6593 * @property ignoreRegistered 6594 * @default false 6595 */ 6596 self.ignoreRegistered = o.ignoreRegistered; 6597 6598 /** 6599 * Root path to prepend to module path for the combo 6600 * service 6601 * @property root 6602 * @type string 6603 * @default [YUI VERSION]/build/ 6604 */ 6605 self.root = Y.Env.meta.root; 6606 6607 /** 6608 * Timeout value in milliseconds. If set, self value will be used by 6609 * the get utility. the timeout event will fire if 6610 * a timeout occurs. 6611 * @property timeout 6612 * @type int 6613 */ 6614 self.timeout = 0; 6615 6616 /** 6617 * A list of modules that should not be loaded, even if 6618 * they turn up in the dependency tree 6619 * @property ignore 6620 * @type string[] 6621 */ 6622 // self.ignore = null; 6623 6624 /** 6625 * A list of modules that should always be loaded, even 6626 * if they have already been inserted into the page. 6627 * @property force 6628 * @type string[] 6629 */ 6630 // self.force = null; 6631 6632 self.forceMap = {}; 6633 6634 /** 6635 * Should we allow rollups 6636 * @property allowRollup 6637 * @type boolean 6638 * @default false 6639 */ 6640 self.allowRollup = false; 6641 6642 /** 6643 * A filter to apply to result urls. This filter will modify the default 6644 * path for all modules. The default path for the YUI library is the 6645 * minified version of the files (e.g., event-min.js). The filter property 6646 * can be a predefined filter or a custom filter. The valid predefined 6647 * filters are: 6648 * <dl> 6649 * <dt>DEBUG</dt> 6650 * <dd>Selects the debug versions of the library (e.g., event-debug.js). 6651 * This option will automatically include the Logger widget</dd> 6652 * <dt>RAW</dt> 6653 * <dd>Selects the non-minified version of the library (e.g., event.js). 6654 * </dd> 6655 * </dl> 6656 * You can also define a custom filter, which must be an object literal 6657 * containing a search expression and a replace string: 6658 * 6659 * myFilter: { 6660 * 'searchExp': "-min\\.js", 6661 * 'replaceStr': "-debug.js" 6662 * } 6663 * 6664 * @property filter 6665 * @type string| {searchExp: string, replaceStr: string} 6666 */ 6667 // self.filter = null; 6668 6669 /** 6670 * per-component filter specification. If specified for a given 6671 * component, this overrides the filter config. 6672 * @property filters 6673 * @type object 6674 */ 6675 self.filters = {}; 6676 6677 /** 6678 * The list of requested modules 6679 * @property required 6680 * @type {string: boolean} 6681 */ 6682 self.required = {}; 6683 6684 /** 6685 * If a module name is predefined when requested, it is checked againsts 6686 * the patterns provided in this property. If there is a match, the 6687 * module is added with the default configuration. 6688 * 6689 * At the moment only supporting module prefixes, but anticipate 6690 * supporting at least regular expressions. 6691 * @property patterns 6692 * @type Object 6693 */ 6694 // self.patterns = Y.merge(Y.Env.meta.patterns); 6695 self.patterns = {}; 6696 6697 /** 6698 * Internal loader instance metadata. Use accessor `getModuleInfo()` instead. 6699 */ 6700 self.moduleInfo = {}; 6701 6702 self.groups = Y.merge(Y.Env.meta.groups); 6703 6704 /** 6705 * Provides the information used to skin the skinnable components. 6706 * The following skin definition would result in 'skin1' and 'skin2' 6707 * being loaded for calendar (if calendar was requested), and 6708 * 'sam' for all other skinnable components: 6709 * 6710 * skin: { 6711 * // The default skin, which is automatically applied if not 6712 * // overriden by a component-specific skin definition. 6713 * // Change this in to apply a different skin globally 6714 * defaultSkin: 'sam', 6715 * 6716 * // This is combined with the loader base property to get 6717 * // the default root directory for a skin. ex: 6718 * // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/ 6719 * base: 'assets/skins/', 6720 * 6721 * // Any component-specific overrides can be specified here, 6722 * // making it possible to load different skins for different 6723 * // components. It is possible to load more than one skin 6724 * // for a given component as well. 6725 * overrides: { 6726 * calendar: ['skin1', 'skin2'] 6727 * } 6728 * } 6729 * @property skin 6730 * @type {Object} 6731 */ 6732 self.skin = Y.merge(Y.Env.meta.skin); 6733 6734 /* 6735 * Map of conditional modules 6736 * @since 3.2.0 6737 */ 6738 self.conditions = {}; 6739 6740 // map of modules with a hash of modules that meet the requirement 6741 // self.provides = {}; 6742 6743 self.config = o; 6744 self._internal = true; 6745 6746 self._populateConditionsCache(); 6747 6748 /** 6749 * Set when beginning to compute the dependency tree. 6750 * Composed of what YUI reports to be loaded combined 6751 * with what has been loaded by any instance on the page 6752 * with the version number specified in the metadata. 6753 * @property loaded 6754 * @type {string: boolean} 6755 */ 6756 self.loaded = GLOBAL_LOADED[VERSION]; 6757 6758 6759 /** 6760 * Should Loader fetch scripts in `async`, defaults to `true` 6761 * @property async 6762 */ 6763 6764 self.async = true; 6765 6766 self._inspectPage(); 6767 6768 self._internal = false; 6769 6770 self._config(o); 6771 6772 self.forceMap = (self.force) ? Y.Array.hash(self.force) : {}; 6773 6774 self.testresults = null; 6775 6776 if (Y.config.tests) { 6777 self.testresults = Y.config.tests; 6778 } 6779 6780 /** 6781 * List of rollup files found in the library metadata 6782 * @property rollups 6783 */ 6784 // self.rollups = null; 6785 6786 /** 6787 * Whether or not to load optional dependencies for 6788 * the requested modules 6789 * @property loadOptional 6790 * @type boolean 6791 * @default false 6792 */ 6793 // self.loadOptional = false; 6794 6795 /** 6796 * All of the derived dependencies in sorted order, which 6797 * will be populated when either calculate() or insert() 6798 * is called 6799 * @property sorted 6800 * @type string[] 6801 */ 6802 self.sorted = []; 6803 6804 /* 6805 * A list of modules to attach to the YUI instance when complete. 6806 * If not supplied, the sorted list of dependencies are applied. 6807 * @property attaching 6808 */ 6809 // self.attaching = null; 6810 6811 /** 6812 * Flag to indicate the dependency tree needs to be recomputed 6813 * if insert is called again. 6814 * @property dirty 6815 * @type boolean 6816 * @default true 6817 */ 6818 self.dirty = true; 6819 6820 /** 6821 * List of modules inserted by the utility 6822 * @property inserted 6823 * @type {string: boolean} 6824 */ 6825 self.inserted = {}; 6826 6827 /** 6828 * List of skipped modules during insert() because the module 6829 * was not defined 6830 * @property skipped 6831 */ 6832 self.skipped = {}; 6833 6834 // Y.on('yui:load', self.loadNext, self); 6835 6836 self.tested = {}; 6837 6838 /* 6839 * Cached sorted calculate results 6840 * @property results 6841 * @since 3.2.0 6842 */ 6843 //self.results = {}; 6844 6845 if (self.ignoreRegistered) { 6846 //Clear inpage already processed modules. 6847 self._resetModules(); 6848 } 6849 6850 }; 6851 6852 Y.Loader.prototype = { 6853 /** 6854 * Gets the module info from the local moduleInfo hash, or from the 6855 * default metadata and populate the local moduleInfo hash. 6856 * @method getModuleInfo 6857 * @param {string} name of the module 6858 * @public 6859 */ 6860 getModuleInfo: function(name) { 6861 6862 var m = this.moduleInfo[name], 6863 rawMetaModules, globalRenderedMods, internal, v; 6864 6865 if (m) { 6866 return m; 6867 } 6868 6869 rawMetaModules = META.modules; 6870 globalRenderedMods = GLOBAL_ENV._renderedMods; 6871 internal = this._internal; 6872 6873 /* 6874 The logic here is: 6875 6876 - if the `moduleInfo[name]` is avilable, 6877 then short circuit 6878 - otherwise, if the module is in the globalCache (cross Y instance), 6879 then port it from the global registry into `moduleInfo[name]` 6880 - otherwise, if the module has raw metadata (from meta modules) 6881 then add it to the global registry and to `moduleInfo[name]` 6882 6883 */ 6884 if (globalRenderedMods && globalRenderedMods.hasOwnProperty(name) && !this.ignoreRegistered) { 6885 this.moduleInfo[name] = Y.merge(globalRenderedMods[name]); 6886 } else { 6887 if (rawMetaModules.hasOwnProperty(name)) { 6888 this._internal = true; // making sure that modules from raw data are marked as internal 6889 v = this.addModule(rawMetaModules[name], name); 6890 // Inspect the page for the CSS module and mark it as loaded. 6891 if (v && v.type === CSS) { 6892 if (this.isCSSLoaded(v.name, true)) { 6893 Y.log('Found CSS module on page: ' + v.name, 'info', 'loader'); 6894 this.loaded[v.name] = true; 6895 } 6896 } 6897 this._internal = internal; 6898 } 6899 } 6900 return this.moduleInfo[name]; 6901 }, 6902 /** 6903 * Expand the names that are aliases to other modules. 6904 * @method _expandAliases 6905 * @param {string[]} list a module name or a list of names to be expanded 6906 * @private 6907 * @return {array} 6908 */ 6909 _expandAliases: function(list) { 6910 var expanded = [], 6911 aliases = YUI.Env.aliases, 6912 i, name; 6913 list = Y.Array(list); 6914 for (i = 0; i < list.length; i += 1) { 6915 name = list[i]; 6916 expanded.push.apply(expanded, aliases[name] ? aliases[name] : [name]); 6917 } 6918 return expanded; 6919 }, 6920 /** 6921 * Populate the conditions cache from raw modules, this is necessary 6922 * because no other module will require a conditional module, instead 6923 * the condition has to be executed and then the module is analyzed 6924 * to be included in the final requirement list. Without this cache 6925 * conditional modules will be simply ignored. 6926 * @method _populateConditionsCache 6927 * @private 6928 */ 6929 _populateConditionsCache: function() { 6930 var rawMetaModules = META.modules, 6931 cache = GLOBAL_ENV._conditions, 6932 i, j, t, trigger; 6933 6934 // if we have conditions in cache and cache is enabled 6935 // we should port them to this loader instance 6936 if (cache && !this.ignoreRegistered) { 6937 for (i in cache) { 6938 if (cache.hasOwnProperty(i)) { 6939 this.conditions[i] = Y.merge(cache[i]); 6940 } 6941 } 6942 } else { 6943 for (i in rawMetaModules) { 6944 if (rawMetaModules.hasOwnProperty(i) && rawMetaModules[i].condition) { 6945 t = this._expandAliases(rawMetaModules[i].condition.trigger); 6946 for (j = 0; j < t.length; j += 1) { 6947 trigger = t[j]; 6948 this.conditions[trigger] = this.conditions[trigger] || {}; 6949 this.conditions[trigger][rawMetaModules[i].name || i] = rawMetaModules[i].condition; 6950 } 6951 } 6952 } 6953 GLOBAL_ENV._conditions = this.conditions; 6954 } 6955 }, 6956 /** 6957 * Reset modules in the module cache to a pre-processed state so additional 6958 * computations with a different skin or language will work as expected. 6959 * @method _resetModules 6960 * @private 6961 */ 6962 _resetModules: function() { 6963 var self = this, i, o, 6964 mod, name, details; 6965 for (i in self.moduleInfo) { 6966 if (self.moduleInfo.hasOwnProperty(i) && self.moduleInfo[i]) { 6967 mod = self.moduleInfo[i]; 6968 name = mod.name; 6969 details = (YUI.Env.mods[name] ? YUI.Env.mods[name].details : null); 6970 6971 if (details) { 6972 self.moduleInfo[name]._reset = true; 6973 self.moduleInfo[name].requires = details.requires || []; 6974 self.moduleInfo[name].optional = details.optional || []; 6975 self.moduleInfo[name].supersedes = details.supercedes || []; 6976 } 6977 6978 if (mod.defaults) { 6979 for (o in mod.defaults) { 6980 if (mod.defaults.hasOwnProperty(o)) { 6981 if (mod[o]) { 6982 mod[o] = mod.defaults[o]; 6983 } 6984 } 6985 } 6986 } 6987 mod.langCache = undefined; 6988 mod.skinCache = undefined; 6989 if (mod.skinnable) { 6990 self._addSkin(self.skin.defaultSkin, mod.name); 6991 } 6992 } 6993 } 6994 }, 6995 /** 6996 Regex that matches a CSS URL. Used to guess the file type when it's not 6997 specified. 6998 6999 @property REGEX_CSS 7000 @type RegExp 7001 @final 7002 @protected 7003 @since 3.5.0 7004 **/ 7005 REGEX_CSS: /\.css(?:[?;].*)?$/i, 7006 7007 /** 7008 * Default filters for raw and debug 7009 * @property FILTER_DEFS 7010 * @type Object 7011 * @final 7012 * @protected 7013 */ 7014 FILTER_DEFS: { 7015 RAW: { 7016 'searchExp': '-min\\.js', 7017 'replaceStr': '.js' 7018 }, 7019 DEBUG: { 7020 'searchExp': '-min\\.js', 7021 'replaceStr': '-debug.js' 7022 }, 7023 COVERAGE: { 7024 'searchExp': '-min\\.js', 7025 'replaceStr': '-coverage.js' 7026 } 7027 }, 7028 /* 7029 * Check the pages meta-data and cache the result. 7030 * @method _inspectPage 7031 * @private 7032 */ 7033 _inspectPage: function() { 7034 var self = this, v, m, req, mr, i; 7035 7036 for (i in ON_PAGE) { 7037 if (ON_PAGE.hasOwnProperty(i)) { 7038 v = ON_PAGE[i]; 7039 if (v.details) { 7040 m = self.getModuleInfo(v.name); 7041 req = v.details.requires; 7042 mr = m && m.requires; 7043 7044 if (m) { 7045 if (!m._inspected && req && mr.length !== req.length) { 7046 // console.log('deleting ' + m.name); 7047 delete m.expanded; 7048 } 7049 } else { 7050 m = self.addModule(v.details, i); 7051 } 7052 m._inspected = true; 7053 } 7054 } 7055 } 7056 }, 7057 /* 7058 * returns true if b is not loaded, and is required directly or by means of modules it supersedes. 7059 * @private 7060 * @method _requires 7061 * @param {String} mod1 The first module to compare 7062 * @param {String} mod2 The second module to compare 7063 */ 7064 _requires: function(mod1, mod2) { 7065 7066 var i, rm, after_map, s, 7067 m = this.getModuleInfo(mod1), 7068 other = this.getModuleInfo(mod2); 7069 7070 if (!m || !other) { 7071 return false; 7072 } 7073 7074 rm = m.expanded_map; 7075 after_map = m.after_map; 7076 7077 // check if this module should be sorted after the other 7078 // do this first to short circut circular deps 7079 if (after_map && (mod2 in after_map)) { 7080 return true; 7081 } 7082 7083 after_map = other.after_map; 7084 7085 // and vis-versa 7086 if (after_map && (mod1 in after_map)) { 7087 return false; 7088 } 7089 7090 // check if this module requires one the other supersedes 7091 s = other.supersedes; 7092 if (s) { 7093 for (i = 0; i < s.length; i++) { 7094 if (this._requires(mod1, s[i])) { 7095 return true; 7096 } 7097 } 7098 } 7099 7100 s = m.supersedes; 7101 if (s) { 7102 for (i = 0; i < s.length; i++) { 7103 if (this._requires(mod2, s[i])) { 7104 return false; 7105 } 7106 } 7107 } 7108 7109 // check if this module requires the other directly 7110 // if (r && yArray.indexOf(r, mod2) > -1) { 7111 if (rm && (mod2 in rm)) { 7112 return true; 7113 } 7114 7115 // external css files should be sorted below yui css 7116 if (m.ext && m.type === CSS && !other.ext && other.type === CSS) { 7117 return true; 7118 } 7119 7120 return false; 7121 }, 7122 /** 7123 * Apply a new config to the Loader instance 7124 * @method _config 7125 * @private 7126 * @param {Object} o The new configuration 7127 */ 7128 _config: function(o) { 7129 var i, j, val, a, f, group, groupName, self = this, 7130 mods = [], mod, modInfo; 7131 // apply config values 7132 if (o) { 7133 for (i in o) { 7134 if (o.hasOwnProperty(i)) { 7135 val = o[i]; 7136 //TODO This should be a case 7137 if (i === 'require') { 7138 self.require(val); 7139 } else if (i === 'skin') { 7140 //If the config.skin is a string, format to the expected object 7141 if (typeof val === 'string') { 7142 self.skin.defaultSkin = o.skin; 7143 val = { 7144 defaultSkin: val 7145 }; 7146 } 7147 7148 Y.mix(self.skin, val, true); 7149 } else if (i === 'groups') { 7150 for (j in val) { 7151 if (val.hasOwnProperty(j)) { 7152 // Y.log('group: ' + j); 7153 groupName = j; 7154 group = val[j]; 7155 self.addGroup(group, groupName); 7156 if (group.aliases) { 7157 for (a in group.aliases) { 7158 if (group.aliases.hasOwnProperty(a)) { 7159 self.addAlias(group.aliases[a], a); 7160 } 7161 } 7162 } 7163 } 7164 } 7165 7166 } else if (i === 'modules') { 7167 // add a hash of module definitions 7168 for (j in val) { 7169 if (val.hasOwnProperty(j)) { 7170 self.addModule(val[j], j); 7171 } 7172 } 7173 } else if (i === 'aliases') { 7174 for (j in val) { 7175 if (val.hasOwnProperty(j)) { 7176 self.addAlias(val[j], j); 7177 } 7178 } 7179 } else if (i === 'gallery') { 7180 if (this.groups.gallery.update) { 7181 this.groups.gallery.update(val, o); 7182 } 7183 } else if (i === 'yui2' || i === '2in3') { 7184 if (this.groups.yui2.update) { 7185 this.groups.yui2.update(o['2in3'], o.yui2, o); 7186 } 7187 } else { 7188 self[i] = val; 7189 } 7190 } 7191 } 7192 } 7193 7194 // fix filter 7195 f = self.filter; 7196 7197 if (L.isString(f)) { 7198 f = f.toUpperCase(); 7199 self.filterName = f; 7200 self.filter = self.FILTER_DEFS[f]; 7201 if (f === 'DEBUG') { 7202 self.require('yui-log', 'dump'); 7203 } 7204 } 7205 7206 if (self.filterName && self.coverage) { 7207 if (self.filterName === 'COVERAGE' && L.isArray(self.coverage) && self.coverage.length) { 7208 for (i = 0; i < self.coverage.length; i++) { 7209 mod = self.coverage[i]; 7210 modInfo = self.getModuleInfo(mod); 7211 if (modInfo && modInfo.use) { 7212 mods = mods.concat(modInfo.use); 7213 } else { 7214 mods.push(mod); 7215 } 7216 } 7217 self.filters = self.filters || {}; 7218 Y.Array.each(mods, function(mod) { 7219 self.filters[mod] = self.FILTER_DEFS.COVERAGE; 7220 }); 7221 self.filterName = 'RAW'; 7222 self.filter = self.FILTER_DEFS[self.filterName]; 7223 } 7224 } 7225 7226 }, 7227 7228 /** 7229 * Returns the skin module name for the specified skin name. If a 7230 * module name is supplied, the returned skin module name is 7231 * specific to the module passed in. 7232 * @method formatSkin 7233 * @param {string} skin the name of the skin. 7234 * @param {string} mod optional: the name of a module to skin. 7235 * @return {string} the full skin module name. 7236 */ 7237 formatSkin: function(skin, mod) { 7238 var s = SKIN_PREFIX + skin; 7239 if (mod) { 7240 s = s + '-' + mod; 7241 } 7242 7243 return s; 7244 }, 7245 7246 /** 7247 * Adds the skin def to the module info 7248 * @method _addSkin 7249 * @param {string} skin the name of the skin. 7250 * @param {string} mod the name of the module. 7251 * @param {string} parent parent module if this is a skin of a 7252 * submodule or plugin. 7253 * @return {string} the module name for the skin. 7254 * @private 7255 */ 7256 _addSkin: function(skin, mod, parent) { 7257 var pkg, name, nmod, 7258 sinf = this.skin, 7259 mdef = mod && this.getModuleInfo(mod), 7260 ext = mdef && mdef.ext; 7261 7262 // Add a module definition for the module-specific skin css 7263 if (mod) { 7264 name = this.formatSkin(skin, mod); 7265 if (!this.getModuleInfo(name)) { 7266 pkg = mdef.pkg || mod; 7267 nmod = { 7268 skin: true, 7269 name: name, 7270 group: mdef.group, 7271 type: 'css', 7272 after: sinf.after, 7273 path: (parent || pkg) + '/' + sinf.base + skin + 7274 '/' + mod + '.css', 7275 ext: ext 7276 }; 7277 if (mdef.base) { 7278 nmod.base = mdef.base; 7279 } 7280 if (mdef.configFn) { 7281 nmod.configFn = mdef.configFn; 7282 } 7283 this.addModule(nmod, name); 7284 7285 Y.log('Adding skin (' + name + '), ' + parent + ', ' + pkg + ', ' + nmod.path, 'info', 'loader'); 7286 } 7287 } 7288 7289 return name; 7290 }, 7291 /** 7292 * Adds an alias module to the system 7293 * @method addAlias 7294 * @param {Array} use An array of modules that makes up this alias 7295 * @param {String} name The name of the alias 7296 * @example 7297 * var loader = new Y.Loader({}); 7298 * loader.addAlias([ 'node', 'yql' ], 'davglass'); 7299 * loader.require(['davglass']); 7300 * var out = loader.resolve(true); 7301 * 7302 * //out.js will contain Node and YQL modules 7303 */ 7304 addAlias: function(use, name) { 7305 YUI.Env.aliases[name] = use; 7306 this.addModule({ 7307 name: name, 7308 use: use 7309 }); 7310 }, 7311 /** 7312 * Add a new module group 7313 * @method addGroup 7314 * @param {Object} config An object containing the group configuration data 7315 * @param {String} config.name required, the group name 7316 * @param {String} config.base The base directory for this module group 7317 * @param {String} config.root The root path to add to each combo resource path 7318 * @param {Boolean} config.combine Should the request be combined 7319 * @param {String} config.comboBase Combo service base path 7320 * @param {Object} config.modules The group of modules 7321 * @param {String} name the group name. 7322 * @example 7323 * var loader = new Y.Loader({}); 7324 * loader.addGroup({ 7325 * name: 'davglass', 7326 * combine: true, 7327 * comboBase: '/combo?', 7328 * root: '', 7329 * modules: { 7330 * //Module List here 7331 * } 7332 * }, 'davglass'); 7333 */ 7334 addGroup: function(o, name) { 7335 var mods = o.modules, 7336 self = this, i, v; 7337 7338 name = name || o.name; 7339 o.name = name; 7340 self.groups[name] = o; 7341 7342 if (o.patterns) { 7343 for (i in o.patterns) { 7344 if (o.patterns.hasOwnProperty(i)) { 7345 o.patterns[i].group = name; 7346 self.patterns[i] = o.patterns[i]; 7347 } 7348 } 7349 } 7350 7351 if (mods) { 7352 for (i in mods) { 7353 if (mods.hasOwnProperty(i)) { 7354 v = mods[i]; 7355 if (typeof v === 'string') { 7356 v = { name: i, fullpath: v }; 7357 } 7358 v.group = name; 7359 self.addModule(v, i); 7360 } 7361 } 7362 } 7363 }, 7364 7365 /** 7366 * Add a new module to the component metadata. 7367 * @method addModule 7368 * @param {Object} config An object containing the module data. 7369 * @param {String} config.name Required, the component name 7370 * @param {String} config.type Required, the component type (js or css) 7371 * @param {String} config.path Required, the path to the script from `base` 7372 * @param {Array} config.requires Array of modules required by this component 7373 * @param {Array} [config.optional] Array of optional modules for this component 7374 * @param {Array} [config.supersedes] Array of the modules this component replaces 7375 * @param {Array} [config.after] Array of modules the components which, if present, should be sorted above this one 7376 * @param {Object} [config.after_map] Faster alternative to 'after' -- supply a hash instead of an array 7377 * @param {Number} [config.rollup] The number of superseded modules required for automatic rollup 7378 * @param {String} [config.fullpath] If `fullpath` is specified, this is used instead of the configured `base + path` 7379 * @param {Boolean} [config.skinnable] Flag to determine if skin assets should automatically be pulled in 7380 * @param {Object} [config.submodules] Hash of submodules 7381 * @param {String} [config.group] The group the module belongs to -- this is set automatically when it is added as part of a group configuration. 7382 * @param {Array} [config.lang] Array of BCP 47 language tags of languages for which this module has localized resource bundles, e.g., `["en-GB", "zh-Hans-CN"]` 7383 * @param {Object} [config.condition] Specifies that the module should be loaded automatically if a condition is met. This is an object with up to four fields: 7384 * @param {String} [config.condition.trigger] The name of a module that can trigger the auto-load 7385 * @param {Function} [config.condition.test] A function that returns true when the module is to be loaded. 7386 * @param {String} [config.condition.ua] The UA name of <a href="UA.html">Y.UA</a> object that returns true when the module is to be loaded. e.g., `"ie"`, `"nodejs"`. 7387 * @param {String} [config.condition.when] Specifies the load order of the conditional module 7388 * with regard to the position of the trigger module. 7389 * This should be one of three values: `before`, `after`, or `instead`. The default is `after`. 7390 * @param {Object} [config.testresults] A hash of test results from `Y.Features.all()` 7391 * @param {Function} [config.configFn] A function to exectute when configuring this module 7392 * @param {Object} config.configFn.mod The module config, modifying this object will modify it's config. Returning false will delete the module's config. 7393 * @param {String[]} [config.optionalRequires] List of dependencies that 7394 may optionally be loaded by this loader. This is targeted mostly at 7395 polyfills, since they should not be in the list of requires because 7396 polyfills are assumed to be available in the global scope. 7397 * @param {Function} [config.test] Test to be called when this module is 7398 added as an optional dependency of another module. If the test function 7399 returns `false`, the module will be ignored and will not be attached to 7400 this YUI instance. 7401 * @param {String} [name] The module name, required if not in the module data. 7402 * @return {Object} the module definition or null if the object passed in did not provide all required attributes. 7403 */ 7404 addModule: function(o, name) { 7405 name = name || o.name; 7406 7407 if (typeof o === 'string') { 7408 o = { name: name, fullpath: o }; 7409 } 7410 7411 7412 var subs, i, l, t, sup, s, smod, plugins, plug, 7413 j, langs, packName, supName, flatSup, flatLang, lang, ret, 7414 overrides, skinname, when, g, p, 7415 modInfo = this.moduleInfo[name], 7416 conditions = this.conditions, trigger; 7417 7418 //Only merge this data if the temp flag is set 7419 //from an earlier pass from a pattern or else 7420 //an override module (YUI_config) can not be used to 7421 //replace a default module. 7422 if (modInfo && modInfo.temp) { 7423 //This catches temp modules loaded via a pattern 7424 // The module will be added twice, once from the pattern and 7425 // Once from the actual add call, this ensures that properties 7426 // that were added to the module the first time around (group: gallery) 7427 // are also added the second time around too. 7428 o = Y.merge(modInfo, o); 7429 } 7430 7431 o.name = name; 7432 7433 if (!o || !o.name) { 7434 return null; 7435 } 7436 7437 if (!o.type) { 7438 //Always assume it's javascript unless the CSS pattern is matched. 7439 o.type = JS; 7440 p = o.path || o.fullpath; 7441 if (p && this.REGEX_CSS.test(p)) { 7442 Y.log('Auto determined module type as CSS', 'warn', 'loader'); 7443 o.type = CSS; 7444 } 7445 } 7446 7447 if (!o.path && !o.fullpath) { 7448 o.path = _path(name, name, o.type); 7449 } 7450 o.supersedes = o.supersedes || o.use; 7451 7452 o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true; 7453 7454 // Handle submodule logic 7455 subs = o.submodules; 7456 7457 this.moduleInfo[name] = o; 7458 7459 o.requires = o.requires || []; 7460 7461 /* 7462 Only allowing the cascade of requires information, since 7463 optional and supersedes are far more fine grained than 7464 a blanket requires is. 7465 */ 7466 if (this.requires) { 7467 for (i = 0; i < this.requires.length; i++) { 7468 o.requires.push(this.requires[i]); 7469 } 7470 } 7471 if (o.group && this.groups && this.groups[o.group]) { 7472 g = this.groups[o.group]; 7473 if (g.requires) { 7474 for (i = 0; i < g.requires.length; i++) { 7475 o.requires.push(g.requires[i]); 7476 } 7477 } 7478 } 7479 7480 7481 if (!o.defaults) { 7482 o.defaults = { 7483 requires: o.requires ? [].concat(o.requires) : null, 7484 supersedes: o.supersedes ? [].concat(o.supersedes) : null, 7485 optional: o.optional ? [].concat(o.optional) : null 7486 }; 7487 } 7488 7489 if (o.skinnable && o.ext && o.temp) { 7490 skinname = this._addSkin(this.skin.defaultSkin, name); 7491 o.requires.unshift(skinname); 7492 } 7493 7494 if (o.requires.length) { 7495 o.requires = this.filterRequires(o.requires) || []; 7496 } 7497 7498 if (!o.langPack && o.lang) { 7499 langs = yArray(o.lang); 7500 for (j = 0; j < langs.length; j++) { 7501 lang = langs[j]; 7502 packName = this.getLangPackName(lang, name); 7503 smod = this.getModuleInfo(packName); 7504 if (!smod) { 7505 smod = this._addLangPack(lang, o, packName); 7506 } 7507 } 7508 } 7509 7510 7511 if (subs) { 7512 sup = o.supersedes || []; 7513 l = 0; 7514 7515 for (i in subs) { 7516 if (subs.hasOwnProperty(i)) { 7517 s = subs[i]; 7518 7519 s.path = s.path || _path(name, i, o.type); 7520 s.pkg = name; 7521 s.group = o.group; 7522 7523 if (s.supersedes) { 7524 sup = sup.concat(s.supersedes); 7525 } 7526 7527 smod = this.addModule(s, i); 7528 sup.push(i); 7529 7530 if (smod.skinnable) { 7531 o.skinnable = true; 7532 overrides = this.skin.overrides; 7533 if (overrides && overrides[i]) { 7534 for (j = 0; j < overrides[i].length; j++) { 7535 skinname = this._addSkin(overrides[i][j], 7536 i, name); 7537 sup.push(skinname); 7538 } 7539 } 7540 skinname = this._addSkin(this.skin.defaultSkin, 7541 i, name); 7542 sup.push(skinname); 7543 } 7544 7545 // looks like we are expected to work out the metadata 7546 // for the parent module language packs from what is 7547 // specified in the child modules. 7548 if (s.lang && s.lang.length) { 7549 7550 langs = yArray(s.lang); 7551 for (j = 0; j < langs.length; j++) { 7552 lang = langs[j]; 7553 packName = this.getLangPackName(lang, name); 7554 supName = this.getLangPackName(lang, i); 7555 smod = this.getModuleInfo(packName); 7556 7557 if (!smod) { 7558 smod = this._addLangPack(lang, o, packName); 7559 } 7560 7561 flatSup = flatSup || yArray.hash(smod.supersedes); 7562 7563 if (!(supName in flatSup)) { 7564 smod.supersedes.push(supName); 7565 } 7566 7567 o.lang = o.lang || []; 7568 7569 flatLang = flatLang || yArray.hash(o.lang); 7570 7571 if (!(lang in flatLang)) { 7572 o.lang.push(lang); 7573 } 7574 7575 // Y.log('pack ' + packName + ' should supersede ' + supName); 7576 // Add rollup file, need to add to supersedes list too 7577 7578 // default packages 7579 packName = this.getLangPackName(ROOT_LANG, name); 7580 supName = this.getLangPackName(ROOT_LANG, i); 7581 7582 smod = this.getModuleInfo(packName); 7583 7584 if (!smod) { 7585 smod = this._addLangPack(lang, o, packName); 7586 } 7587 7588 if (!(supName in flatSup)) { 7589 smod.supersedes.push(supName); 7590 } 7591 7592 // Y.log('pack ' + packName + ' should supersede ' + supName); 7593 // Add rollup file, need to add to supersedes list too 7594 7595 } 7596 } 7597 7598 l++; 7599 } 7600 } 7601 //o.supersedes = YObject.keys(yArray.hash(sup)); 7602 o.supersedes = yArray.dedupe(sup); 7603 if (this.allowRollup) { 7604 o.rollup = (l < 4) ? l : Math.min(l - 1, 4); 7605 } 7606 } 7607 7608 plugins = o.plugins; 7609 if (plugins) { 7610 for (i in plugins) { 7611 if (plugins.hasOwnProperty(i)) { 7612 plug = plugins[i]; 7613 plug.pkg = name; 7614 plug.path = plug.path || _path(name, i, o.type); 7615 plug.requires = plug.requires || []; 7616 plug.group = o.group; 7617 this.addModule(plug, i); 7618 if (o.skinnable) { 7619 this._addSkin(this.skin.defaultSkin, i, name); 7620 } 7621 7622 } 7623 } 7624 } 7625 7626 if (o.condition) { 7627 t = this._expandAliases(o.condition.trigger); 7628 for (i = 0; i < t.length; i++) { 7629 trigger = t[i]; 7630 when = o.condition.when; 7631 conditions[trigger] = conditions[trigger] || {}; 7632 conditions[trigger][name] = o.condition; 7633 // the 'when' attribute can be 'before', 'after', or 'instead' 7634 // the default is after. 7635 if (when && when !== 'after') { 7636 if (when === 'instead') { // replace the trigger 7637 o.supersedes = o.supersedes || []; 7638 o.supersedes.push(trigger); 7639 } 7640 // before the trigger 7641 // the trigger requires the conditional mod, 7642 // so it should appear before the conditional 7643 // mod if we do not intersede. 7644 } else { // after the trigger 7645 o.after = o.after || []; 7646 o.after.push(trigger); 7647 } 7648 } 7649 } 7650 7651 if (o.supersedes) { 7652 o.supersedes = this.filterRequires(o.supersedes); 7653 } 7654 7655 if (o.after) { 7656 o.after = this.filterRequires(o.after); 7657 o.after_map = yArray.hash(o.after); 7658 } 7659 7660 // this.dirty = true; 7661 7662 if (o.configFn) { 7663 ret = o.configFn(o); 7664 if (ret === false) { 7665 Y.log('Config function returned false for ' + name + ', skipping.', 'info', 'loader'); 7666 delete this.moduleInfo[name]; 7667 delete GLOBAL_ENV._renderedMods[name]; 7668 o = null; 7669 } 7670 } 7671 //Add to global cache 7672 if (o) { 7673 if (!GLOBAL_ENV._renderedMods) { 7674 GLOBAL_ENV._renderedMods = {}; 7675 } 7676 GLOBAL_ENV._renderedMods[name] = Y.mix(GLOBAL_ENV._renderedMods[name] || {}, o); 7677 GLOBAL_ENV._conditions = conditions; 7678 } 7679 7680 return o; 7681 }, 7682 7683 /** 7684 * Add a requirement for one or more module 7685 * @method require 7686 * @param {string[] | string*} what the modules to load. 7687 */ 7688 require: function(what) { 7689 var a = (typeof what === 'string') ? yArray(arguments) : what; 7690 this.dirty = true; 7691 this.required = Y.merge(this.required, yArray.hash(this.filterRequires(a))); 7692 7693 this._explodeRollups(); 7694 }, 7695 /** 7696 * Grab all the items that were asked for, check to see if the Loader 7697 * meta-data contains a "use" array. If it doesm remove the asked item and replace it with 7698 * the content of the "use". 7699 * This will make asking for: "dd" 7700 * Actually ask for: "dd-ddm-base,dd-ddm,dd-ddm-drop,dd-drag,dd-proxy,dd-constrain,dd-drop,dd-scroll,dd-drop-plugin" 7701 * @private 7702 * @method _explodeRollups 7703 */ 7704 _explodeRollups: function() { 7705 var self = this, m, m2, i, a, v, len, len2, 7706 r = self.required; 7707 7708 if (!self.allowRollup) { 7709 for (i in r) { 7710 if (r.hasOwnProperty(i)) { 7711 m = self.getModule(i); 7712 if (m && m.use) { 7713 len = m.use.length; 7714 for (a = 0; a < len; a++) { 7715 m2 = self.getModule(m.use[a]); 7716 if (m2 && m2.use) { 7717 len2 = m2.use.length; 7718 for (v = 0; v < len2; v++) { 7719 r[m2.use[v]] = true; 7720 } 7721 } else { 7722 r[m.use[a]] = true; 7723 } 7724 } 7725 } 7726 } 7727 } 7728 self.required = r; 7729 } 7730 7731 }, 7732 /** 7733 * Explodes the required array to remove aliases and replace them with real modules 7734 * @method filterRequires 7735 * @param {Array} r The original requires array 7736 * @return {Array} The new array of exploded requirements 7737 */ 7738 filterRequires: function(r) { 7739 if (r) { 7740 if (!Y.Lang.isArray(r)) { 7741 r = [r]; 7742 } 7743 r = Y.Array(r); 7744 var c = [], i, mod, o, m; 7745 7746 for (i = 0; i < r.length; i++) { 7747 mod = this.getModule(r[i]); 7748 if (mod && mod.use) { 7749 for (o = 0; o < mod.use.length; o++) { 7750 //Must walk the other modules in case a module is a rollup of rollups (datatype) 7751 m = this.getModule(mod.use[o]); 7752 if (m && m.use && (m.name !== mod.name)) { 7753 c = Y.Array.dedupe([].concat(c, this.filterRequires(m.use))); 7754 } else { 7755 c.push(mod.use[o]); 7756 } 7757 } 7758 } else { 7759 c.push(r[i]); 7760 } 7761 } 7762 r = c; 7763 } 7764 return r; 7765 }, 7766 7767 /** 7768 Returns `true` if the module can be attached to the YUI instance. Runs 7769 the module's test if there is one and caches its result. 7770 7771 @method _canBeAttached 7772 @param {String} module Name of the module to check. 7773 @return {Boolean} Result of the module's test if it has one, or `true`. 7774 **/ 7775 _canBeAttached: function (m) { 7776 m = this.getModule(m); 7777 if (m && m.test) { 7778 if (!m.hasOwnProperty('_testResult')) { 7779 m._testResult = m.test(Y); 7780 } 7781 return m._testResult; 7782 } 7783 // return `true` for modules not registered as Loader will know what 7784 // to do with them later on 7785 return true; 7786 }, 7787 7788 /** 7789 * Returns an object containing properties for all modules required 7790 * in order to load the requested module 7791 * @method getRequires 7792 * @param {object} mod The module definition from moduleInfo. 7793 * @return {array} the expanded requirement list. 7794 */ 7795 getRequires: function(mod) { 7796 7797 if (!mod) { 7798 //console.log('returning no reqs for ' + mod.name); 7799 return NO_REQUIREMENTS; 7800 } 7801 7802 if (mod._parsed) { 7803 //console.log('returning requires for ' + mod.name, mod.requires); 7804 return mod.expanded || NO_REQUIREMENTS; 7805 } 7806 7807 //TODO add modue cache here out of scope.. 7808 7809 var i, m, j, length, add, packName, lang, testresults = this.testresults, 7810 name = mod.name, cond, 7811 adddef = ON_PAGE[name] && ON_PAGE[name].details, 7812 optReqs = mod.optionalRequires, 7813 d, go, def, 7814 r, old_mod, 7815 o, skinmod, skindef, skinpar, skinname, 7816 intl = mod.lang || mod.intl, 7817 ftests = Y.Features && Y.Features.tests.load, 7818 hash, reparse; 7819 7820 // console.log(name); 7821 7822 // pattern match leaves module stub that needs to be filled out 7823 if (mod.temp && adddef) { 7824 old_mod = mod; 7825 mod = this.addModule(adddef, name); 7826 mod.group = old_mod.group; 7827 mod.pkg = old_mod.pkg; 7828 delete mod.expanded; 7829 } 7830 7831 // console.log('cache: ' + mod.langCache + ' == ' + this.lang); 7832 7833 //If a skin or a lang is different, reparse.. 7834 reparse = !((!this.lang || mod.langCache === this.lang) && (mod.skinCache === this.skin.defaultSkin)); 7835 7836 if (mod.expanded && !reparse) { 7837 //Y.log('Already expanded ' + name + ', ' + mod.expanded); 7838 return mod.expanded; 7839 } 7840 7841 // Optional dependencies are dependencies that may or may not be 7842 // available. 7843 // This feature was designed specifically to be used when transpiling 7844 // ES6 modules, in order to use polyfills and regular scripts that define 7845 // global variables without having to import them since they should be 7846 // available in the global scope. 7847 if (optReqs) { 7848 for (i = 0, length = optReqs.length; i < length; i++) { 7849 if (this._canBeAttached(optReqs[i])) { 7850 mod.requires.push(optReqs[i]); 7851 } 7852 } 7853 } 7854 7855 d = []; 7856 hash = {}; 7857 r = this.filterRequires(mod.requires); 7858 if (mod.lang) { 7859 //If a module has a lang attribute, auto add the intl requirement. 7860 d.unshift('intl'); 7861 r.unshift('intl'); 7862 intl = true; 7863 } 7864 o = this.filterRequires(mod.optional); 7865 7866 // Y.log("getRequires: " + name + " (dirty:" + this.dirty + 7867 // ", expanded:" + mod.expanded + ")"); 7868 7869 mod._parsed = true; 7870 mod.langCache = this.lang; 7871 mod.skinCache = this.skin.defaultSkin; 7872 7873 for (i = 0; i < r.length; i++) { 7874 //Y.log(name + ' requiring ' + r[i], 'info', 'loader'); 7875 if (!hash[r[i]]) { 7876 d.push(r[i]); 7877 hash[r[i]] = true; 7878 m = this.getModule(r[i]); 7879 if (m) { 7880 add = this.getRequires(m); 7881 intl = intl || (m.expanded_map && 7882 (INTL in m.expanded_map)); 7883 for (j = 0; j < add.length; j++) { 7884 d.push(add[j]); 7885 } 7886 } 7887 } 7888 } 7889 7890 // get the requirements from superseded modules, if any 7891 r = this.filterRequires(mod.supersedes); 7892 if (r) { 7893 for (i = 0; i < r.length; i++) { 7894 if (!hash[r[i]]) { 7895 // if this module has submodules, the requirements list is 7896 // expanded to include the submodules. This is so we can 7897 // prevent dups when a submodule is already loaded and the 7898 // parent is requested. 7899 if (mod.submodules) { 7900 d.push(r[i]); 7901 } 7902 7903 hash[r[i]] = true; 7904 m = this.getModule(r[i]); 7905 7906 if (m) { 7907 add = this.getRequires(m); 7908 intl = intl || (m.expanded_map && 7909 (INTL in m.expanded_map)); 7910 for (j = 0; j < add.length; j++) { 7911 d.push(add[j]); 7912 } 7913 } 7914 } 7915 } 7916 } 7917 7918 if (o && this.loadOptional) { 7919 for (i = 0; i < o.length; i++) { 7920 if (!hash[o[i]]) { 7921 d.push(o[i]); 7922 hash[o[i]] = true; 7923 m = this.getModuleInfo(o[i]); 7924 if (m) { 7925 add = this.getRequires(m); 7926 intl = intl || (m.expanded_map && 7927 (INTL in m.expanded_map)); 7928 for (j = 0; j < add.length; j++) { 7929 d.push(add[j]); 7930 } 7931 } 7932 } 7933 } 7934 } 7935 7936 cond = this.conditions[name]; 7937 7938 if (cond) { 7939 //Set the module to not parsed since we have conditionals and this could change the dependency tree. 7940 mod._parsed = false; 7941 if (testresults && ftests) { 7942 oeach(testresults, function(result, id) { 7943 var condmod = ftests[id].name; 7944 if (!hash[condmod] && ftests[id].trigger === name) { 7945 if (result && ftests[id]) { 7946 hash[condmod] = true; 7947 d.push(condmod); 7948 } 7949 } 7950 }); 7951 } else { 7952 for (i in cond) { 7953 if (cond.hasOwnProperty(i)) { 7954 if (!hash[i]) { 7955 def = cond[i]; 7956 //first see if they've specfied a ua check 7957 //then see if they've got a test fn & if it returns true 7958 //otherwise just having a condition block is enough 7959 go = def && ((!def.ua && !def.test) || (def.ua && Y.UA[def.ua]) || 7960 (def.test && def.test(Y, r))); 7961 7962 if (go) { 7963 hash[i] = true; 7964 d.push(i); 7965 m = this.getModule(i); 7966 if (m) { 7967 add = this.getRequires(m); 7968 for (j = 0; j < add.length; j++) { 7969 d.push(add[j]); 7970 } 7971 7972 } 7973 } 7974 } 7975 } 7976 } 7977 } 7978 } 7979 7980 // Create skin modules 7981 if (mod.skinnable) { 7982 skindef = this.skin.overrides; 7983 for (i in YUI.Env.aliases) { 7984 if (YUI.Env.aliases.hasOwnProperty(i)) { 7985 if (Y.Array.indexOf(YUI.Env.aliases[i], name) > -1) { 7986 skinpar = i; 7987 } 7988 } 7989 } 7990 if (skindef && (skindef[name] || (skinpar && skindef[skinpar]))) { 7991 skinname = name; 7992 if (skindef[skinpar]) { 7993 skinname = skinpar; 7994 } 7995 for (i = 0; i < skindef[skinname].length; i++) { 7996 skinmod = this._addSkin(skindef[skinname][i], name); 7997 if (!this.isCSSLoaded(skinmod, this._boot)) { 7998 d.push(skinmod); 7999 } 8000 } 8001 } else { 8002 skinmod = this._addSkin(this.skin.defaultSkin, name); 8003 if (!this.isCSSLoaded(skinmod, this._boot)) { 8004 d.push(skinmod); 8005 } 8006 } 8007 } 8008 8009 mod._parsed = false; 8010 8011 if (intl) { 8012 8013 if (mod.lang && !mod.langPack && Y.Intl) { 8014 lang = Y.Intl.lookupBestLang(this.lang || ROOT_LANG, mod.lang); 8015 //Y.log('Best lang: ' + lang + ', this.lang: ' + this.lang + ', mod.lang: ' + mod.lang); 8016 packName = this.getLangPackName(lang, name); 8017 if (packName) { 8018 d.unshift(packName); 8019 } 8020 } 8021 d.unshift(INTL); 8022 } 8023 8024 mod.expanded_map = yArray.hash(d); 8025 8026 mod.expanded = YObject.keys(mod.expanded_map); 8027 8028 return mod.expanded; 8029 }, 8030 /** 8031 * Check to see if named css module is already loaded on the page 8032 * @method isCSSLoaded 8033 * @param {String} name The name of the css file 8034 * @param {Boolean} skip To skip the short-circuit for ignoreRegister 8035 * @return Boolean 8036 */ 8037 isCSSLoaded: function(name, skip) { 8038 //TODO - Make this call a batching call with name being an array 8039 if (!name || !YUI.Env.cssStampEl || (!skip && this.ignoreRegistered)) { 8040 Y.log('isCSSLoaded was skipped for ' + name, 'warn', 'loader'); 8041 return false; 8042 } 8043 var el = YUI.Env.cssStampEl, 8044 ret = false, 8045 mod = YUI.Env._cssLoaded[name], 8046 style = el.currentStyle; //IE 8047 8048 8049 if (mod !== undefined) { 8050 //Y.log('isCSSLoaded was cached for ' + name, 'warn', 'loader'); 8051 return mod; 8052 } 8053 8054 //Add the classname to the element 8055 el.className = name; 8056 8057 if (!style) { 8058 style = Y.config.doc.defaultView.getComputedStyle(el, null); 8059 } 8060 8061 if (style && style.display === 'none') { 8062 ret = true; 8063 } 8064 8065 Y.log('Has Skin? ' + name + ' : ' + ret, 'info', 'loader'); 8066 8067 el.className = ''; //Reset the classname to '' 8068 8069 YUI.Env._cssLoaded[name] = ret; 8070 8071 return ret; 8072 }, 8073 8074 /** 8075 * Returns a hash of module names the supplied module satisfies. 8076 * @method getProvides 8077 * @param {string} name The name of the module. 8078 * @return {object} what this module provides. 8079 */ 8080 getProvides: function(name) { 8081 var m = this.getModule(name), o, s; 8082 // supmap = this.provides; 8083 8084 if (!m) { 8085 return NOT_FOUND; 8086 } 8087 8088 if (m && !m.provides) { 8089 o = {}; 8090 s = m.supersedes; 8091 8092 if (s) { 8093 yArray.each(s, function(v) { 8094 Y.mix(o, this.getProvides(v)); 8095 }, this); 8096 } 8097 8098 o[name] = true; 8099 m.provides = o; 8100 8101 } 8102 8103 return m.provides; 8104 }, 8105 8106 /** 8107 * Calculates the dependency tree, the result is stored in the sorted 8108 * property. 8109 * @method calculate 8110 * @param {object} o optional options object. 8111 * @param {string} type optional argument to prune modules. 8112 */ 8113 calculate: function(o, type) { 8114 if (o || type || this.dirty) { 8115 8116 if (o) { 8117 this._config(o); 8118 } 8119 8120 if (!this._init) { 8121 this._setup(); 8122 } 8123 8124 this._explode(); 8125 8126 if (this.allowRollup) { 8127 this._rollup(); 8128 } else { 8129 this._explodeRollups(); 8130 } 8131 this._reduce(); 8132 this._sort(); 8133 } 8134 }, 8135 /** 8136 * Creates a "psuedo" package for languages provided in the lang array 8137 * @method _addLangPack 8138 * @private 8139 * @param {String} lang The language to create 8140 * @param {Object} m The module definition to create the language pack around 8141 * @param {String} packName The name of the package (e.g: lang/datatype-date-en-US) 8142 * @return {Object} The module definition 8143 */ 8144 _addLangPack: function(lang, m, packName) { 8145 var name = m.name, 8146 packPath, conf, 8147 existing = this.getModuleInfo(packName); 8148 8149 if (!existing) { 8150 8151 packPath = _path((m.pkg || name), packName, JS, true); 8152 8153 conf = { 8154 path: packPath, 8155 intl: true, 8156 langPack: true, 8157 ext: m.ext, 8158 group: m.group, 8159 supersedes: [] 8160 }; 8161 if (m.root) { 8162 conf.root = m.root; 8163 } 8164 if (m.base) { 8165 conf.base = m.base; 8166 } 8167 8168 if (m.configFn) { 8169 conf.configFn = m.configFn; 8170 } 8171 8172 this.addModule(conf, packName); 8173 8174 if (lang) { 8175 Y.Env.lang = Y.Env.lang || {}; 8176 Y.Env.lang[lang] = Y.Env.lang[lang] || {}; 8177 Y.Env.lang[lang][name] = true; 8178 } 8179 } 8180 8181 return this.getModuleInfo(packName); 8182 }, 8183 8184 /** 8185 * Investigates the current YUI configuration on the page. By default, 8186 * modules already detected will not be loaded again unless a force 8187 * option is encountered. Called by calculate() 8188 * @method _setup 8189 * @private 8190 */ 8191 _setup: function() { 8192 var info = this.moduleInfo, name, i, j, m, l, 8193 packName; 8194 8195 for (name in info) { 8196 if (info.hasOwnProperty(name)) { 8197 m = info[name]; 8198 if (m) { 8199 8200 // remove dups 8201 //m.requires = YObject.keys(yArray.hash(m.requires)); 8202 m.requires = yArray.dedupe(m.requires); 8203 8204 // Create lang pack modules 8205 //if (m.lang && m.lang.length) { 8206 if (m.lang) { 8207 // Setup root package if the module has lang defined, 8208 // it needs to provide a root language pack 8209 packName = this.getLangPackName(ROOT_LANG, name); 8210 this._addLangPack(null, m, packName); 8211 } 8212 8213 } 8214 } 8215 } 8216 8217 8218 //l = Y.merge(this.inserted); 8219 l = {}; 8220 8221 // available modules 8222 if (!this.ignoreRegistered) { 8223 Y.mix(l, GLOBAL_ENV.mods); 8224 } 8225 8226 // add the ignore list to the list of loaded packages 8227 if (this.ignore) { 8228 Y.mix(l, yArray.hash(this.ignore)); 8229 } 8230 8231 // expand the list to include superseded modules 8232 for (j in l) { 8233 if (l.hasOwnProperty(j)) { 8234 Y.mix(l, this.getProvides(j)); 8235 } 8236 } 8237 8238 // remove modules on the force list from the loaded list 8239 if (this.force) { 8240 for (i = 0; i < this.force.length; i++) { 8241 if (this.force[i] in l) { 8242 delete l[this.force[i]]; 8243 } 8244 } 8245 } 8246 8247 Y.mix(this.loaded, l); 8248 8249 this._init = true; 8250 }, 8251 8252 /** 8253 * Builds a module name for a language pack 8254 * @method getLangPackName 8255 * @param {string} lang the language code. 8256 * @param {string} mname the module to build it for. 8257 * @return {string} the language pack module name. 8258 */ 8259 getLangPackName: function(lang, mname) { 8260 return ('lang/' + mname + ((lang) ? '_' + lang : '')); 8261 }, 8262 /** 8263 * Inspects the required modules list looking for additional 8264 * dependencies. Expands the required list to include all 8265 * required modules. Called by calculate() 8266 * @method _explode 8267 * @private 8268 */ 8269 _explode: function() { 8270 //TODO Move done out of scope 8271 var r = this.required, m, reqs, done = {}, 8272 self = this, name, expound; 8273 8274 // the setup phase is over, all modules have been created 8275 self.dirty = false; 8276 8277 self._explodeRollups(); 8278 r = self.required; 8279 8280 for (name in r) { 8281 if (r.hasOwnProperty(name)) { 8282 if (!done[name]) { 8283 done[name] = true; 8284 m = self.getModule(name); 8285 if (m) { 8286 expound = m.expound; 8287 8288 if (expound) { 8289 r[expound] = self.getModule(expound); 8290 reqs = self.getRequires(r[expound]); 8291 Y.mix(r, yArray.hash(reqs)); 8292 } 8293 8294 reqs = self.getRequires(m); 8295 Y.mix(r, yArray.hash(reqs)); 8296 } 8297 } 8298 } 8299 } 8300 8301 // Y.log('After explode: ' + YObject.keys(r)); 8302 }, 8303 /** 8304 * The default method used to test a module against a pattern 8305 * @method _patternTest 8306 * @private 8307 * @param {String} mname The module being tested 8308 * @param {String} pname The pattern to match 8309 */ 8310 _patternTest: function(mname, pname) { 8311 return (mname.indexOf(pname) > -1); 8312 }, 8313 /** 8314 * Get's the loader meta data for the requested module 8315 * @method getModule 8316 * @param {String} mname The module name to get 8317 * @return {Object} The module metadata 8318 */ 8319 getModule: function(mname) { 8320 //TODO: Remove name check - it's a quick hack to fix pattern WIP 8321 if (!mname) { 8322 return null; 8323 } 8324 8325 var p, found, pname, 8326 m = this.getModuleInfo(mname), 8327 patterns = this.patterns; 8328 8329 // check the patterns library to see if we should automatically add 8330 // the module with defaults 8331 if (!m || (m && m.ext)) { 8332 // Y.log('testing patterns ' + YObject.keys(patterns)); 8333 for (pname in patterns) { 8334 if (patterns.hasOwnProperty(pname)) { 8335 // Y.log('testing pattern ' + i); 8336 p = patterns[pname]; 8337 8338 //There is no test method, create a default one that tests 8339 // the pattern against the mod name 8340 if (!p.test) { 8341 p.test = this._patternTest; 8342 } 8343 8344 if (p.test(mname, pname)) { 8345 // use the metadata supplied for the pattern 8346 // as the module definition. 8347 found = p; 8348 break; 8349 } 8350 } 8351 } 8352 } 8353 8354 if (!m) { 8355 if (found) { 8356 if (p.action) { 8357 // Y.log('executing pattern action: ' + pname); 8358 p.action.call(this, mname, pname); 8359 } else { 8360 Y.log('Undefined module: ' + mname + ', matched a pattern: ' + 8361 pname, 'info', 'loader'); 8362 // ext true or false? 8363 m = this.addModule(Y.merge(found, { 8364 test: void 0, 8365 temp: true 8366 }), mname); 8367 if (found.configFn) { 8368 m.configFn = found.configFn; 8369 } 8370 } 8371 } 8372 } else { 8373 if (found && m && found.configFn && !m.configFn) { 8374 m.configFn = found.configFn; 8375 m.configFn(m); 8376 } 8377 } 8378 8379 return m; 8380 }, 8381 8382 // impl in rollup submodule 8383 _rollup: function() { }, 8384 8385 /** 8386 * Remove superceded modules and loaded modules. Called by 8387 * calculate() after we have the mega list of all dependencies 8388 * @method _reduce 8389 * @return {object} the reduced dependency hash. 8390 * @private 8391 */ 8392 _reduce: function(r) { 8393 8394 r = r || this.required; 8395 8396 var i, j, s, m, type = this.loadType, 8397 ignore = this.ignore ? yArray.hash(this.ignore) : false; 8398 8399 for (i in r) { 8400 if (r.hasOwnProperty(i)) { 8401 m = this.getModule(i); 8402 // remove if already loaded 8403 if (((this.loaded[i] || ON_PAGE[i]) && 8404 !this.forceMap[i] && !this.ignoreRegistered) || 8405 (type && m && m.type !== type)) { 8406 delete r[i]; 8407 } 8408 if (ignore && ignore[i]) { 8409 delete r[i]; 8410 } 8411 // remove anything this module supersedes 8412 s = m && m.supersedes; 8413 if (s) { 8414 for (j = 0; j < s.length; j++) { 8415 if (s[j] in r) { 8416 delete r[s[j]]; 8417 } 8418 } 8419 } 8420 } 8421 } 8422 8423 return r; 8424 }, 8425 /** 8426 * Handles the queue when a module has been loaded for all cases 8427 * @method _finish 8428 * @private 8429 * @param {String} msg The message from Loader 8430 * @param {Boolean} success A boolean denoting success or failure 8431 */ 8432 _finish: function(msg, success) { 8433 Y.log('loader finishing: ' + msg + ', ' + Y.id + ', ' + 8434 this.data, 'info', 'loader'); 8435 8436 _queue.running = false; 8437 8438 var onEnd = this.onEnd; 8439 if (onEnd) { 8440 onEnd.call(this.context, { 8441 msg: msg, 8442 data: this.data, 8443 success: success 8444 }); 8445 } 8446 this._continue(); 8447 }, 8448 /** 8449 * The default Loader onSuccess handler, calls this.onSuccess with a payload 8450 * @method _onSuccess 8451 * @private 8452 */ 8453 _onSuccess: function() { 8454 var self = this, skipped = Y.merge(self.skipped), fn, 8455 failed = [], rreg = self.requireRegistration, 8456 success, msg, i, mod; 8457 8458 for (i in skipped) { 8459 if (skipped.hasOwnProperty(i)) { 8460 delete self.inserted[i]; 8461 } 8462 } 8463 8464 self.skipped = {}; 8465 8466 for (i in self.inserted) { 8467 if (self.inserted.hasOwnProperty(i)) { 8468 mod = self.getModule(i); 8469 if (mod && rreg && mod.type === JS && !(i in YUI.Env.mods)) { 8470 failed.push(i); 8471 } else { 8472 Y.mix(self.loaded, self.getProvides(i)); 8473 } 8474 } 8475 } 8476 8477 fn = self.onSuccess; 8478 msg = (failed.length) ? 'notregistered' : 'success'; 8479 success = !(failed.length); 8480 if (fn) { 8481 fn.call(self.context, { 8482 msg: msg, 8483 data: self.data, 8484 success: success, 8485 failed: failed, 8486 skipped: skipped 8487 }); 8488 } 8489 self._finish(msg, success); 8490 }, 8491 /** 8492 * The default Loader onProgress handler, calls this.onProgress with a payload 8493 * @method _onProgress 8494 * @private 8495 */ 8496 _onProgress: function(e) { 8497 var self = this, i; 8498 //set the internal cache to what just came in. 8499 if (e.data && e.data.length) { 8500 for (i = 0; i < e.data.length; i++) { 8501 e.data[i] = self.getModule(e.data[i].name); 8502 } 8503 } 8504 if (self.onProgress) { 8505 self.onProgress.call(self.context, { 8506 name: e.url, 8507 data: e.data 8508 }); 8509 } 8510 }, 8511 /** 8512 * The default Loader onFailure handler, calls this.onFailure with a payload 8513 * @method _onFailure 8514 * @private 8515 */ 8516 _onFailure: function(o) { 8517 var f = this.onFailure, msg = [], i = 0, len = o.errors.length; 8518 8519 for (i; i < len; i++) { 8520 msg.push(o.errors[i].error); 8521 } 8522 8523 msg = msg.join(','); 8524 8525 Y.log('load error: ' + msg + ', ' + Y.id, 'error', 'loader'); 8526 8527 if (f) { 8528 f.call(this.context, { 8529 msg: msg, 8530 data: this.data, 8531 success: false 8532 }); 8533 } 8534 8535 this._finish(msg, false); 8536 8537 }, 8538 8539 /** 8540 * The default Loader onTimeout handler, calls this.onTimeout with a payload 8541 * @method _onTimeout 8542 * @param {Get.Transaction} transaction The Transaction object from `Y.Get` 8543 * @private 8544 */ 8545 _onTimeout: function(transaction) { 8546 Y.log('loader timeout: ' + Y.id, 'error', 'loader'); 8547 var f = this.onTimeout; 8548 if (f) { 8549 f.call(this.context, { 8550 msg: 'timeout', 8551 data: this.data, 8552 success: false, 8553 transaction: transaction 8554 }); 8555 } 8556 }, 8557 8558 /** 8559 * Sorts the dependency tree. The last step of calculate() 8560 * @method _sort 8561 * @private 8562 */ 8563 _sort: function() { 8564 var name, 8565 8566 // Object containing module names. 8567 required = this.required, 8568 8569 // Keep track of whether we've visited a module. 8570 visited = {}; 8571 8572 // Will contain modules names, in the correct order, 8573 // according to dependencies. 8574 this.sorted = []; 8575 8576 for (name in required) { 8577 if (!visited[name] && required.hasOwnProperty(name)) { 8578 this._visit(name, visited); 8579 } 8580 } 8581 }, 8582 8583 /** 8584 * Recursively visits the dependencies of the module name 8585 * passed in, and appends each module name to the `sorted` property. 8586 * @param {String} name The name of a module. 8587 * @param {Object} visited Keeps track of whether a module was visited. 8588 * @method _visit 8589 * @private 8590 */ 8591 _visit: function (name, visited) { 8592 var required, condition, moduleInfo, dependency, dependencies, 8593 trigger, isAfter, i, l; 8594 8595 visited[name] = true; 8596 required = this.required; 8597 moduleInfo = this.moduleInfo[name]; 8598 condition = this.conditions[name] || {}; 8599 8600 if (moduleInfo) { 8601 // Recurse on each dependency of this module, 8602 // figuring out its dependencies, and so on. 8603 dependencies = moduleInfo.expanded || moduleInfo.requires; 8604 8605 for (i = 0, l = dependencies.length; i < l; ++i) { 8606 dependency = dependencies[i]; 8607 trigger = condition[dependency]; 8608 8609 // We cannot process this dependency yet if it must 8610 // appear after our current module. 8611 isAfter = trigger && (!trigger.when || trigger.when === "after"); 8612 8613 // Is this module name in the required list of modules, 8614 // and have we not already visited it? 8615 if (required[dependency] && !visited[dependency] && !isAfter) { 8616 this._visit(dependency, visited); 8617 } 8618 } 8619 } 8620 8621 this.sorted.push(name); 8622 }, 8623 8624 /** 8625 * Handles the actual insertion of script/link tags 8626 * @method _insert 8627 * @private 8628 * @param {Object} source The YUI instance the request came from 8629 * @param {Object} o The metadata to include 8630 * @param {String} type JS or CSS 8631 * @param {Boolean} [skipcalc=false] Do a Loader.calculate on the meta 8632 */ 8633 _insert: function(source, o, type, skipcalc) { 8634 8635 Y.log('private _insert() ' + (type || '') + ', ' + Y.id, "info", "loader"); 8636 8637 // restore the state at the time of the request 8638 if (source) { 8639 this._config(source); 8640 } 8641 8642 // build the dependency list 8643 // don't include type so we can process CSS and script in 8644 // one pass when the type is not specified. 8645 8646 var modules = this.resolve(!skipcalc), 8647 self = this, comp = 0, actions = 0, 8648 mods = {}, deps, complete; 8649 8650 self._refetch = []; 8651 8652 if (type) { 8653 //Filter out the opposite type and reset the array so the checks later work 8654 modules[((type === JS) ? CSS : JS)] = []; 8655 } 8656 if (!self.fetchCSS) { 8657 modules.css = []; 8658 } 8659 if (modules.js.length) { 8660 comp++; 8661 } 8662 if (modules.css.length) { 8663 comp++; 8664 } 8665 8666 //console.log('Resolved Modules: ', modules); 8667 8668 complete = function(d) { 8669 actions++; 8670 var errs = {}, i = 0, o = 0, u = '', fn, 8671 modName, resMods; 8672 8673 if (d && d.errors) { 8674 for (i = 0; i < d.errors.length; i++) { 8675 if (d.errors[i].request) { 8676 u = d.errors[i].request.url; 8677 } else { 8678 u = d.errors[i]; 8679 } 8680 errs[u] = u; 8681 } 8682 } 8683 8684 if (d && d.data && d.data.length && (d.type === 'success')) { 8685 for (i = 0; i < d.data.length; i++) { 8686 self.inserted[d.data[i].name] = true; 8687 //If the external module has a skin or a lang, reprocess it 8688 if (d.data[i].lang || d.data[i].skinnable) { 8689 delete self.inserted[d.data[i].name]; 8690 self._refetch.push(d.data[i].name); 8691 } 8692 } 8693 } 8694 8695 if (actions === comp) { 8696 self._loading = null; 8697 Y.log('Loader actions complete!', 'info', 'loader'); 8698 if (self._refetch.length) { 8699 //Get the deps for the new meta-data and reprocess 8700 Y.log('Found potential modules to refetch', 'info', 'loader'); 8701 for (i = 0; i < self._refetch.length; i++) { 8702 deps = self.getRequires(self.getModule(self._refetch[i])); 8703 for (o = 0; o < deps.length; o++) { 8704 if (!self.inserted[deps[o]]) { 8705 //We wouldn't be to this point without the module being here 8706 mods[deps[o]] = deps[o]; 8707 } 8708 } 8709 } 8710 mods = Y.Object.keys(mods); 8711 if (mods.length) { 8712 Y.log('Refetching modules with new meta-data', 'info', 'loader'); 8713 self.require(mods); 8714 resMods = self.resolve(true); 8715 if (resMods.cssMods.length) { 8716 for (i=0; i < resMods.cssMods.length; i++) { 8717 modName = resMods.cssMods[i].name; 8718 delete YUI.Env._cssLoaded[modName]; 8719 if (self.isCSSLoaded(modName)) { 8720 self.inserted[modName] = true; 8721 delete self.required[modName]; 8722 } 8723 } 8724 self.sorted = []; 8725 self._sort(); 8726 } 8727 d = null; //bail 8728 self._insert(); //insert the new deps 8729 } 8730 } 8731 if (d && d.fn) { 8732 Y.log('Firing final Loader callback!', 'info', 'loader'); 8733 fn = d.fn; 8734 delete d.fn; 8735 fn.call(self, d); 8736 } 8737 } 8738 }; 8739 8740 this._loading = true; 8741 8742 if (!modules.js.length && !modules.css.length) { 8743 Y.log('No modules resolved..', 'warn', 'loader'); 8744 actions = -1; 8745 complete({ 8746 fn: self._onSuccess 8747 }); 8748 return; 8749 } 8750 8751 8752 if (modules.css.length) { //Load CSS first 8753 Y.log('Loading CSS modules', 'info', 'loader'); 8754 Y.Get.css(modules.css, { 8755 data: modules.cssMods, 8756 attributes: self.cssAttributes, 8757 insertBefore: self.insertBefore, 8758 charset: self.charset, 8759 timeout: self.timeout, 8760 context: self, 8761 onProgress: function(e) { 8762 self._onProgress.call(self, e); 8763 }, 8764 onTimeout: function(d) { 8765 self._onTimeout.call(self, d); 8766 }, 8767 onSuccess: function(d) { 8768 d.type = 'success'; 8769 d.fn = self._onSuccess; 8770 complete.call(self, d); 8771 }, 8772 onFailure: function(d) { 8773 d.type = 'failure'; 8774 d.fn = self._onFailure; 8775 complete.call(self, d); 8776 } 8777 }); 8778 } 8779 8780 if (modules.js.length) { 8781 Y.log('Loading JS modules', 'info', 'loader'); 8782 Y.Get.js(modules.js, { 8783 data: modules.jsMods, 8784 insertBefore: self.insertBefore, 8785 attributes: self.jsAttributes, 8786 charset: self.charset, 8787 timeout: self.timeout, 8788 autopurge: false, 8789 context: self, 8790 async: self.async, 8791 onProgress: function(e) { 8792 self._onProgress.call(self, e); 8793 }, 8794 onTimeout: function(d) { 8795 self._onTimeout.call(self, d); 8796 }, 8797 onSuccess: function(d) { 8798 d.type = 'success'; 8799 d.fn = self._onSuccess; 8800 complete.call(self, d); 8801 }, 8802 onFailure: function(d) { 8803 d.type = 'failure'; 8804 d.fn = self._onFailure; 8805 complete.call(self, d); 8806 } 8807 }); 8808 } 8809 }, 8810 /** 8811 * Once a loader operation is completely finished, process any additional queued items. 8812 * @method _continue 8813 * @private 8814 */ 8815 _continue: function() { 8816 if (!(_queue.running) && _queue.size() > 0) { 8817 _queue.running = true; 8818 _queue.next()(); 8819 } 8820 }, 8821 8822 /** 8823 * inserts the requested modules and their dependencies. 8824 * <code>type</code> can be "js" or "css". Both script and 8825 * css are inserted if type is not provided. 8826 * @method insert 8827 * @param {object} o optional options object. 8828 * @param {string} type the type of dependency to insert. 8829 */ 8830 insert: function(o, type, skipsort) { 8831 Y.log('public insert() ' + (type || '') + ', ' + Y.Object.keys(this.required), "info", "loader"); 8832 var self = this, copy = Y.merge(this); 8833 delete copy.require; 8834 delete copy.dirty; 8835 _queue.add(function() { 8836 self._insert(copy, o, type, skipsort); 8837 }); 8838 this._continue(); 8839 }, 8840 8841 /** 8842 * Executed every time a module is loaded, and if we are in a load 8843 * cycle, we attempt to load the next script. Public so that it 8844 * is possible to call this if using a method other than 8845 * Y.register to determine when scripts are fully loaded 8846 * @method loadNext 8847 * @deprecated 8848 * @param {string} mname optional the name of the module that has 8849 * been loaded (which is usually why it is time to load the next 8850 * one). 8851 */ 8852 loadNext: function() { 8853 Y.log('loadNext was called..', 'error', 'loader'); 8854 return; 8855 }, 8856 8857 /** 8858 * Apply filter defined for this instance to a url/path 8859 * @method _filter 8860 * @param {string} u the string to filter. 8861 * @param {string} name the name of the module, if we are processing 8862 * a single module as opposed to a combined url. 8863 * @return {string} the filtered string. 8864 * @private 8865 */ 8866 _filter: function(u, name, group) { 8867 var f = this.filter, 8868 hasFilter = name && (name in this.filters), 8869 modFilter = hasFilter && this.filters[name], 8870 groupName = group || (this.getModuleInfo(name) || {}).group || null; 8871 8872 if (groupName && this.groups[groupName] && this.groups[groupName].filter) { 8873 modFilter = this.groups[groupName].filter; 8874 hasFilter = true; 8875 } 8876 8877 if (u) { 8878 if (hasFilter) { 8879 f = (L.isString(modFilter)) ? this.FILTER_DEFS[modFilter.toUpperCase()] || null : modFilter; 8880 } 8881 if (f) { 8882 u = u.replace(new RegExp(f.searchExp, 'g'), f.replaceStr); 8883 } 8884 } 8885 return u; 8886 }, 8887 8888 /** 8889 * Generates the full url for a module 8890 * @method _url 8891 * @param {string} path the path fragment. 8892 * @param {String} name The name of the module 8893 * @param {String} [base] The base url to use. Defaults to self.base 8894 * @return {string} the full url. 8895 * @private 8896 */ 8897 _url: function(path, name, base) { 8898 return this._filter((base || this.base || '') + path, name); 8899 }, 8900 /** 8901 * Returns an Object hash of file arrays built from `loader.sorted` or from an arbitrary list of sorted modules. 8902 * @method resolve 8903 * @param {Boolean} [calc=false] Perform a loader.calculate() before anything else 8904 * @param {Array} [sorted=loader.sorted] An override for the loader.sorted array 8905 * @return {Object} Object hash (js and css) of two arrays of file lists 8906 * @example This method can be used as an off-line dep calculator 8907 * 8908 * var Y = YUI(); 8909 * var loader = new Y.Loader({ 8910 * filter: 'debug', 8911 * base: '../../', 8912 * root: 'build/', 8913 * combine: true, 8914 * require: ['node', 'dd', 'console'] 8915 * }); 8916 * var out = loader.resolve(true); 8917 * 8918 */ 8919 resolve: function(calc, sorted) { 8920 var self = this, 8921 resolved = { js: [], jsMods: [], css: [], cssMods: [] }, 8922 addSingle; 8923 8924 if (self.skin.overrides || self.skin.defaultSkin !== DEFAULT_SKIN || self.ignoreRegistered) { 8925 self._resetModules(); 8926 } 8927 8928 if (calc) { 8929 self.calculate(); 8930 } 8931 sorted = sorted || self.sorted; 8932 8933 addSingle = function(mod) { 8934 if (mod) { 8935 var group = (mod.group && self.groups[mod.group]) || NOT_FOUND, 8936 url; 8937 8938 //Always assume it's async 8939 if (group.async === false) { 8940 mod.async = group.async; 8941 } 8942 8943 url = (mod.fullpath) ? self._filter(mod.fullpath, mod.name) : 8944 self._url(mod.path, mod.name, group.base || mod.base); 8945 8946 if (mod.attributes || mod.async === false) { 8947 url = { 8948 url: url, 8949 async: mod.async 8950 }; 8951 if (mod.attributes) { 8952 url.attributes = mod.attributes; 8953 } 8954 } 8955 resolved[mod.type].push(url); 8956 resolved[mod.type + 'Mods'].push(mod); 8957 } else { 8958 Y.log('Undefined Module', 'warn', 'loader'); 8959 } 8960 8961 }; 8962 8963 /*jslint vars: true */ 8964 var inserted = (self.ignoreRegistered) ? {} : self.inserted, 8965 comboSources = {}, 8966 maxURLLength, 8967 comboMeta, 8968 comboBase, 8969 comboSep, 8970 group, 8971 mod, 8972 len, 8973 i; 8974 /*jslint vars: false */ 8975 8976 for (i = 0, len = sorted.length; i < len; i++) { 8977 mod = self.getModule(sorted[i]); 8978 if (!mod || inserted[mod.name]) { 8979 continue; 8980 } 8981 8982 group = self.groups[mod.group]; 8983 8984 comboBase = self.comboBase; 8985 8986 if (group) { 8987 if (!group.combine || mod.fullpath) { 8988 //This is not a combo module, skip it and load it singly later. 8989 addSingle(mod); 8990 continue; 8991 } 8992 mod.combine = true; 8993 8994 if (typeof group.root === 'string') { 8995 mod.root = group.root; 8996 } 8997 8998 comboBase = group.comboBase || comboBase; 8999 comboSep = group.comboSep; 9000 maxURLLength = group.maxURLLength; 9001 } else { 9002 if (!self.combine) { 9003 //This is not a combo module, skip it and load it singly later. 9004 addSingle(mod); 9005 continue; 9006 } 9007 } 9008 9009 if (!mod.combine && mod.ext) { 9010 addSingle(mod); 9011 continue; 9012 } 9013 9014 comboSources[comboBase] = comboSources[comboBase] || 9015 { js: [], jsMods: [], css: [], cssMods: [] }; 9016 9017 comboMeta = comboSources[comboBase]; 9018 comboMeta.group = mod.group; 9019 comboMeta.comboSep = comboSep || self.comboSep; 9020 comboMeta.maxURLLength = maxURLLength || self.maxURLLength; 9021 9022 comboMeta[mod.type + 'Mods'].push(mod); 9023 } 9024 9025 // TODO: Refactor the encoding logic below into its own method. 9026 9027 /*jslint vars: true */ 9028 var fragSubset, 9029 modules, 9030 tmpBase, 9031 baseLen, 9032 frags, 9033 frag, 9034 type; 9035 /*jslint vars: false */ 9036 9037 for (comboBase in comboSources) { 9038 if (comboSources.hasOwnProperty(comboBase)) { 9039 comboMeta = comboSources[comboBase]; 9040 comboSep = comboMeta.comboSep; 9041 maxURLLength = comboMeta.maxURLLength; 9042 Y.log('Using maxURLLength of ' + maxURLLength, 'info', 'loader'); 9043 for (type in comboMeta) { 9044 if (type === JS || type === CSS) { 9045 modules = comboMeta[type + 'Mods']; 9046 frags = []; 9047 for (i = 0, len = modules.length; i < len; i += 1) { 9048 mod = modules[i]; 9049 frag = ((typeof mod.root === 'string') ? mod.root : self.root) + (mod.path || mod.fullpath); 9050 frags.push( 9051 self._filter(frag, mod.name) 9052 ); 9053 } 9054 tmpBase = comboBase + frags.join(comboSep); 9055 baseLen = tmpBase.length; 9056 if (maxURLLength <= comboBase.length) { 9057 Y.log('maxURLLength (' + maxURLLength + ') is lower than the comboBase length (' + comboBase.length + '), resetting to default (' + MAX_URL_LENGTH + ')', 'error', 'loader'); 9058 maxURLLength = MAX_URL_LENGTH; 9059 } 9060 9061 if (frags.length) { 9062 if (baseLen > maxURLLength) { 9063 Y.log('Exceeded maxURLLength (' + maxURLLength + ') for ' + type + ', splitting', 'info', 'loader'); 9064 fragSubset = []; 9065 for (i = 0, len = frags.length; i < len; i++) { 9066 fragSubset.push(frags[i]); 9067 tmpBase = comboBase + fragSubset.join(comboSep); 9068 9069 if (tmpBase.length > maxURLLength) { 9070 frag = fragSubset.pop(); 9071 tmpBase = comboBase + fragSubset.join(comboSep); 9072 resolved[type].push(self._filter(tmpBase, null, comboMeta.group)); 9073 fragSubset = []; 9074 if (frag) { 9075 fragSubset.push(frag); 9076 } 9077 } 9078 } 9079 if (fragSubset.length) { 9080 tmpBase = comboBase + fragSubset.join(comboSep); 9081 resolved[type].push(self._filter(tmpBase, null, comboMeta.group)); 9082 } 9083 } else { 9084 resolved[type].push(self._filter(tmpBase, null, comboMeta.group)); 9085 } 9086 } 9087 resolved[type + 'Mods'] = resolved[type + 'Mods'].concat(modules); 9088 } 9089 } 9090 } 9091 } 9092 9093 return resolved; 9094 }, 9095 9096 /** 9097 Shortcut to calculate, resolve and load all modules. 9098 9099 var loader = new Y.Loader({ 9100 ignoreRegistered: true, 9101 modules: { 9102 mod: { 9103 path: 'mod.js' 9104 } 9105 }, 9106 requires: [ 'mod' ] 9107 }); 9108 loader.load(function() { 9109 console.log('All modules have loaded..'); 9110 }); 9111 9112 9113 @method load 9114 @param {Function} cb Executed after all load operations are complete 9115 */ 9116 load: function(cb) { 9117 if (!cb) { 9118 Y.log('No callback supplied to load()', 'error', 'loader'); 9119 return; 9120 } 9121 var self = this, 9122 out = self.resolve(true); 9123 9124 self.data = out; 9125 9126 self.onEnd = function() { 9127 cb.apply(self.context || self, arguments); 9128 }; 9129 9130 self.insert(); 9131 } 9132 }; 9133 9134 9135 9136 }, '3.17.2', {"requires": ["get", "features"]}); 9137 YUI.add('loader-rollup', function (Y, NAME) { 9138 9139 /** 9140 * Optional automatic rollup logic for reducing http connections 9141 * when not using a combo service. 9142 * @module loader 9143 * @submodule rollup 9144 */ 9145 9146 /** 9147 * Look for rollup packages to determine if all of the modules a 9148 * rollup supersedes are required. If so, include the rollup to 9149 * help reduce the total number of connections required. Called 9150 * by calculate(). This is an optional feature, and requires the 9151 * appropriate submodule to function. 9152 * @method _rollup 9153 * @for Loader 9154 * @private 9155 */ 9156 Y.Loader.prototype._rollup = function() { 9157 var i, j, m, s, r = this.required, roll, 9158 info = this.moduleInfo, rolled, c, smod; 9159 9160 // find and cache rollup modules 9161 if (this.dirty || !this.rollups) { 9162 this.rollups = {}; 9163 for (i in info) { 9164 if (info.hasOwnProperty(i)) { 9165 m = this.getModule(i); 9166 // if (m && m.rollup && m.supersedes) { 9167 if (m && m.rollup) { 9168 this.rollups[i] = m; 9169 } 9170 } 9171 } 9172 } 9173 9174 // make as many passes as needed to pick up rollup rollups 9175 for (;;) { 9176 rolled = false; 9177 9178 // go through the rollup candidates 9179 for (i in this.rollups) { 9180 if (this.rollups.hasOwnProperty(i)) { 9181 // there can be only one, unless forced 9182 if (!r[i] && ((!this.loaded[i]) || this.forceMap[i])) { 9183 m = this.getModule(i); 9184 s = m.supersedes || []; 9185 roll = false; 9186 9187 // @TODO remove continue 9188 if (!m.rollup) { 9189 continue; 9190 } 9191 9192 c = 0; 9193 9194 // check the threshold 9195 for (j = 0; j < s.length; j++) { 9196 smod = info[s[j]]; 9197 9198 // if the superseded module is loaded, we can't 9199 // load the rollup unless it has been forced. 9200 if (this.loaded[s[j]] && !this.forceMap[s[j]]) { 9201 roll = false; 9202 break; 9203 // increment the counter if this module is required. 9204 // if we are beyond the rollup threshold, we will 9205 // use the rollup module 9206 } else if (r[s[j]] && m.type === smod.type) { 9207 c++; 9208 // Y.log("adding to thresh: " + c + ", " + s[j]); 9209 roll = (c >= m.rollup); 9210 if (roll) { 9211 // Y.log("over thresh " + c + ", " + s[j]); 9212 break; 9213 } 9214 } 9215 } 9216 9217 if (roll) { 9218 // Y.log("adding rollup: " + i); 9219 // add the rollup 9220 r[i] = true; 9221 rolled = true; 9222 9223 // expand the rollup's dependencies 9224 this.getRequires(m); 9225 } 9226 } 9227 } 9228 } 9229 9230 // if we made it here w/o rolling up something, we are done 9231 if (!rolled) { 9232 break; 9233 } 9234 } 9235 }; 9236 9237 9238 }, '3.17.2', {"requires": ["loader-base"]}); 9239 YUI.add('loader-yui3', function (Y, NAME) { 9240 9241 /* This file is auto-generated by (yogi.js loader --mix --yes) */ 9242 9243 /*jshint maxlen:900, eqeqeq: false */ 9244 9245 /** 9246 * YUI 3 module metadata 9247 * @module loader 9248 * @submodule loader-yui3 9249 */ 9250 YUI.Env[Y.version].modules = YUI.Env[Y.version].modules || {}; 9251 Y.mix(YUI.Env[Y.version].modules, { 9252 "align-plugin": { 9253 "requires": [ 9254 "node-screen", 9255 "node-pluginhost" 9256 ] 9257 }, 9258 "anim": { 9259 "use": [ 9260 "anim-base", 9261 "anim-color", 9262 "anim-curve", 9263 "anim-easing", 9264 "anim-node-plugin", 9265 "anim-scroll", 9266 "anim-xy" 9267 ] 9268 }, 9269 "anim-base": { 9270 "requires": [ 9271 "base-base", 9272 "node-style", 9273 "color-base" 9274 ] 9275 }, 9276 "anim-color": { 9277 "requires": [ 9278 "anim-base" 9279 ] 9280 }, 9281 "anim-curve": { 9282 "requires": [ 9283 "anim-xy" 9284 ] 9285 }, 9286 "anim-easing": { 9287 "requires": [ 9288 "anim-base" 9289 ] 9290 }, 9291 "anim-node-plugin": { 9292 "requires": [ 9293 "node-pluginhost", 9294 "anim-base" 9295 ] 9296 }, 9297 "anim-scroll": { 9298 "requires": [ 9299 "anim-base" 9300 ] 9301 }, 9302 "anim-shape": { 9303 "requires": [ 9304 "anim-base", 9305 "anim-easing", 9306 "anim-color", 9307 "matrix" 9308 ] 9309 }, 9310 "anim-shape-transform": { 9311 "use": [ 9312 "anim-shape" 9313 ] 9314 }, 9315 "anim-xy": { 9316 "requires": [ 9317 "anim-base", 9318 "node-screen" 9319 ] 9320 }, 9321 "app": { 9322 "use": [ 9323 "app-base", 9324 "app-content", 9325 "app-transitions", 9326 "lazy-model-list", 9327 "model", 9328 "model-list", 9329 "model-sync-rest", 9330 "model-sync-local", 9331 "router", 9332 "view", 9333 "view-node-map" 9334 ] 9335 }, 9336 "app-base": { 9337 "requires": [ 9338 "classnamemanager", 9339 "pjax-base", 9340 "router", 9341 "view" 9342 ] 9343 }, 9344 "app-content": { 9345 "requires": [ 9346 "app-base", 9347 "pjax-content" 9348 ] 9349 }, 9350 "app-transitions": { 9351 "requires": [ 9352 "app-base" 9353 ] 9354 }, 9355 "app-transitions-css": { 9356 "type": "css" 9357 }, 9358 "app-transitions-native": { 9359 "condition": { 9360 "name": "app-transitions-native", 9361 "test": function (Y) { 9362 var doc = Y.config.doc, 9363 node = doc ? doc.documentElement : null; 9364 9365 if (node && node.style) { 9366 return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 9367 } 9368 9369 return false; 9370 }, 9371 "trigger": "app-transitions" 9372 }, 9373 "requires": [ 9374 "app-transitions", 9375 "app-transitions-css", 9376 "parallel", 9377 "transition" 9378 ] 9379 }, 9380 "array-extras": { 9381 "requires": [ 9382 "yui-base" 9383 ] 9384 }, 9385 "array-invoke": { 9386 "requires": [ 9387 "yui-base" 9388 ] 9389 }, 9390 "arraylist": { 9391 "requires": [ 9392 "yui-base" 9393 ] 9394 }, 9395 "arraylist-add": { 9396 "requires": [ 9397 "arraylist" 9398 ] 9399 }, 9400 "arraylist-filter": { 9401 "requires": [ 9402 "arraylist" 9403 ] 9404 }, 9405 "arraysort": { 9406 "requires": [ 9407 "yui-base" 9408 ] 9409 }, 9410 "async-queue": { 9411 "requires": [ 9412 "event-custom" 9413 ] 9414 }, 9415 "attribute": { 9416 "use": [ 9417 "attribute-base", 9418 "attribute-complex" 9419 ] 9420 }, 9421 "attribute-base": { 9422 "requires": [ 9423 "attribute-core", 9424 "attribute-observable", 9425 "attribute-extras" 9426 ] 9427 }, 9428 "attribute-complex": { 9429 "requires": [ 9430 "attribute-base" 9431 ] 9432 }, 9433 "attribute-core": { 9434 "requires": [ 9435 "oop" 9436 ] 9437 }, 9438 "attribute-events": { 9439 "use": [ 9440 "attribute-observable" 9441 ] 9442 }, 9443 "attribute-extras": { 9444 "requires": [ 9445 "oop" 9446 ] 9447 }, 9448 "attribute-observable": { 9449 "requires": [ 9450 "event-custom" 9451 ] 9452 }, 9453 "autocomplete": { 9454 "use": [ 9455 "autocomplete-base", 9456 "autocomplete-sources", 9457 "autocomplete-list", 9458 "autocomplete-plugin" 9459 ] 9460 }, 9461 "autocomplete-base": { 9462 "optional": [ 9463 "autocomplete-sources" 9464 ], 9465 "requires": [ 9466 "array-extras", 9467 "base-build", 9468 "escape", 9469 "event-valuechange", 9470 "node-base" 9471 ] 9472 }, 9473 "autocomplete-filters": { 9474 "requires": [ 9475 "array-extras", 9476 "text-wordbreak" 9477 ] 9478 }, 9479 "autocomplete-filters-accentfold": { 9480 "requires": [ 9481 "array-extras", 9482 "text-accentfold", 9483 "text-wordbreak" 9484 ] 9485 }, 9486 "autocomplete-highlighters": { 9487 "requires": [ 9488 "array-extras", 9489 "highlight-base" 9490 ] 9491 }, 9492 "autocomplete-highlighters-accentfold": { 9493 "requires": [ 9494 "array-extras", 9495 "highlight-accentfold" 9496 ] 9497 }, 9498 "autocomplete-list": { 9499 "after": [ 9500 "autocomplete-sources" 9501 ], 9502 "lang": [ 9503 "en", 9504 "es", 9505 "hu", 9506 "it" 9507 ], 9508 "requires": [ 9509 "autocomplete-base", 9510 "event-resize", 9511 "node-screen", 9512 "selector-css3", 9513 "shim-plugin", 9514 "widget", 9515 "widget-position", 9516 "widget-position-align" 9517 ], 9518 "skinnable": true 9519 }, 9520 "autocomplete-list-keys": { 9521 "condition": { 9522 "name": "autocomplete-list-keys", 9523 "test": function (Y) { 9524 // Only add keyboard support to autocomplete-list if this doesn't appear to 9525 // be an iOS or Android-based mobile device. 9526 // 9527 // There's currently no feasible way to actually detect whether a device has 9528 // a hardware keyboard, so this sniff will have to do. It can easily be 9529 // overridden by manually loading the autocomplete-list-keys module. 9530 // 9531 // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari 9532 // doesn't fire the keyboard events used by AutoCompleteList, so there's 9533 // no point loading the -keys module even when a bluetooth keyboard may be 9534 // available. 9535 return !(Y.UA.ios || Y.UA.android); 9536 }, 9537 "trigger": "autocomplete-list" 9538 }, 9539 "requires": [ 9540 "autocomplete-list", 9541 "base-build" 9542 ] 9543 }, 9544 "autocomplete-plugin": { 9545 "requires": [ 9546 "autocomplete-list", 9547 "node-pluginhost" 9548 ] 9549 }, 9550 "autocomplete-sources": { 9551 "optional": [ 9552 "io-base", 9553 "json-parse", 9554 "jsonp", 9555 "yql" 9556 ], 9557 "requires": [ 9558 "autocomplete-base" 9559 ] 9560 }, 9561 "axes": { 9562 "use": [ 9563 "axis-numeric", 9564 "axis-category", 9565 "axis-time", 9566 "axis-stacked" 9567 ] 9568 }, 9569 "axes-base": { 9570 "use": [ 9571 "axis-numeric-base", 9572 "axis-category-base", 9573 "axis-time-base", 9574 "axis-stacked-base" 9575 ] 9576 }, 9577 "axis": { 9578 "requires": [ 9579 "dom", 9580 "widget", 9581 "widget-position", 9582 "widget-stack", 9583 "graphics", 9584 "axis-base" 9585 ] 9586 }, 9587 "axis-base": { 9588 "requires": [ 9589 "classnamemanager", 9590 "datatype-number", 9591 "datatype-date", 9592 "base", 9593 "event-custom" 9594 ] 9595 }, 9596 "axis-category": { 9597 "requires": [ 9598 "axis", 9599 "axis-category-base" 9600 ] 9601 }, 9602 "axis-category-base": { 9603 "requires": [ 9604 "axis-base" 9605 ] 9606 }, 9607 "axis-numeric": { 9608 "requires": [ 9609 "axis", 9610 "axis-numeric-base" 9611 ] 9612 }, 9613 "axis-numeric-base": { 9614 "requires": [ 9615 "axis-base" 9616 ] 9617 }, 9618 "axis-stacked": { 9619 "requires": [ 9620 "axis-numeric", 9621 "axis-stacked-base" 9622 ] 9623 }, 9624 "axis-stacked-base": { 9625 "requires": [ 9626 "axis-numeric-base" 9627 ] 9628 }, 9629 "axis-time": { 9630 "requires": [ 9631 "axis", 9632 "axis-time-base" 9633 ] 9634 }, 9635 "axis-time-base": { 9636 "requires": [ 9637 "axis-base" 9638 ] 9639 }, 9640 "base": { 9641 "use": [ 9642 "base-base", 9643 "base-pluginhost", 9644 "base-build" 9645 ] 9646 }, 9647 "base-base": { 9648 "requires": [ 9649 "attribute-base", 9650 "base-core", 9651 "base-observable" 9652 ] 9653 }, 9654 "base-build": { 9655 "requires": [ 9656 "base-base" 9657 ] 9658 }, 9659 "base-core": { 9660 "requires": [ 9661 "attribute-core" 9662 ] 9663 }, 9664 "base-observable": { 9665 "requires": [ 9666 "attribute-observable", 9667 "base-core" 9668 ] 9669 }, 9670 "base-pluginhost": { 9671 "requires": [ 9672 "base-base", 9673 "pluginhost" 9674 ] 9675 }, 9676 "button": { 9677 "requires": [ 9678 "button-core", 9679 "cssbutton", 9680 "widget" 9681 ] 9682 }, 9683 "button-core": { 9684 "requires": [ 9685 "attribute-core", 9686 "classnamemanager", 9687 "node-base", 9688 "escape" 9689 ] 9690 }, 9691 "button-group": { 9692 "requires": [ 9693 "button-plugin", 9694 "cssbutton", 9695 "widget" 9696 ] 9697 }, 9698 "button-plugin": { 9699 "requires": [ 9700 "button-core", 9701 "cssbutton", 9702 "node-pluginhost" 9703 ] 9704 }, 9705 "cache": { 9706 "use": [ 9707 "cache-base", 9708 "cache-offline", 9709 "cache-plugin" 9710 ] 9711 }, 9712 "cache-base": { 9713 "requires": [ 9714 "base" 9715 ] 9716 }, 9717 "cache-offline": { 9718 "requires": [ 9719 "cache-base", 9720 "json" 9721 ] 9722 }, 9723 "cache-plugin": { 9724 "requires": [ 9725 "plugin", 9726 "cache-base" 9727 ] 9728 }, 9729 "calendar": { 9730 "requires": [ 9731 "calendar-base", 9732 "calendarnavigator" 9733 ], 9734 "skinnable": true 9735 }, 9736 "calendar-base": { 9737 "lang": [ 9738 "de", 9739 "en", 9740 "es", 9741 "es-AR", 9742 "fr", 9743 "hu", 9744 "it", 9745 "ja", 9746 "nb-NO", 9747 "nl", 9748 "pt-BR", 9749 "ru", 9750 "zh-Hans", 9751 "zh-Hans-CN", 9752 "zh-Hant", 9753 "zh-Hant-HK", 9754 "zh-HANT-TW" 9755 ], 9756 "requires": [ 9757 "widget", 9758 "datatype-date", 9759 "datatype-date-math", 9760 "cssgrids" 9761 ], 9762 "skinnable": true 9763 }, 9764 "calendarnavigator": { 9765 "requires": [ 9766 "plugin", 9767 "classnamemanager", 9768 "datatype-date", 9769 "node" 9770 ], 9771 "skinnable": true 9772 }, 9773 "charts": { 9774 "use": [ 9775 "charts-base" 9776 ] 9777 }, 9778 "charts-base": { 9779 "requires": [ 9780 "dom", 9781 "event-mouseenter", 9782 "event-touch", 9783 "graphics-group", 9784 "axes", 9785 "series-pie", 9786 "series-line", 9787 "series-marker", 9788 "series-area", 9789 "series-spline", 9790 "series-column", 9791 "series-bar", 9792 "series-areaspline", 9793 "series-combo", 9794 "series-combospline", 9795 "series-line-stacked", 9796 "series-marker-stacked", 9797 "series-area-stacked", 9798 "series-spline-stacked", 9799 "series-column-stacked", 9800 "series-bar-stacked", 9801 "series-areaspline-stacked", 9802 "series-combo-stacked", 9803 "series-combospline-stacked" 9804 ] 9805 }, 9806 "charts-legend": { 9807 "requires": [ 9808 "charts-base" 9809 ] 9810 }, 9811 "classnamemanager": { 9812 "requires": [ 9813 "yui-base" 9814 ] 9815 }, 9816 "clickable-rail": { 9817 "requires": [ 9818 "slider-base" 9819 ] 9820 }, 9821 "collection": { 9822 "use": [ 9823 "array-extras", 9824 "arraylist", 9825 "arraylist-add", 9826 "arraylist-filter", 9827 "array-invoke" 9828 ] 9829 }, 9830 "color": { 9831 "use": [ 9832 "color-base", 9833 "color-hsl", 9834 "color-harmony" 9835 ] 9836 }, 9837 "color-base": { 9838 "requires": [ 9839 "yui-base" 9840 ] 9841 }, 9842 "color-harmony": { 9843 "requires": [ 9844 "color-hsl" 9845 ] 9846 }, 9847 "color-hsl": { 9848 "requires": [ 9849 "color-base" 9850 ] 9851 }, 9852 "color-hsv": { 9853 "requires": [ 9854 "color-base" 9855 ] 9856 }, 9857 "console": { 9858 "lang": [ 9859 "en", 9860 "es", 9861 "hu", 9862 "it", 9863 "ja" 9864 ], 9865 "requires": [ 9866 "yui-log", 9867 "widget" 9868 ], 9869 "skinnable": true 9870 }, 9871 "console-filters": { 9872 "requires": [ 9873 "plugin", 9874 "console" 9875 ], 9876 "skinnable": true 9877 }, 9878 "content-editable": { 9879 "requires": [ 9880 "node-base", 9881 "editor-selection", 9882 "stylesheet", 9883 "plugin" 9884 ] 9885 }, 9886 "controller": { 9887 "use": [ 9888 "router" 9889 ] 9890 }, 9891 "cookie": { 9892 "requires": [ 9893 "yui-base" 9894 ] 9895 }, 9896 "createlink-base": { 9897 "requires": [ 9898 "editor-base" 9899 ] 9900 }, 9901 "cssbase": { 9902 "after": [ 9903 "cssreset", 9904 "cssfonts", 9905 "cssgrids", 9906 "cssreset-context", 9907 "cssfonts-context", 9908 "cssgrids-context" 9909 ], 9910 "type": "css" 9911 }, 9912 "cssbase-context": { 9913 "after": [ 9914 "cssreset", 9915 "cssfonts", 9916 "cssgrids", 9917 "cssreset-context", 9918 "cssfonts-context", 9919 "cssgrids-context" 9920 ], 9921 "type": "css" 9922 }, 9923 "cssbutton": { 9924 "type": "css" 9925 }, 9926 "cssfonts": { 9927 "type": "css" 9928 }, 9929 "cssfonts-context": { 9930 "type": "css" 9931 }, 9932 "cssgrids": { 9933 "optional": [ 9934 "cssnormalize" 9935 ], 9936 "type": "css" 9937 }, 9938 "cssgrids-base": { 9939 "optional": [ 9940 "cssnormalize" 9941 ], 9942 "type": "css" 9943 }, 9944 "cssgrids-responsive": { 9945 "optional": [ 9946 "cssnormalize" 9947 ], 9948 "requires": [ 9949 "cssgrids", 9950 "cssgrids-responsive-base" 9951 ], 9952 "type": "css" 9953 }, 9954 "cssgrids-units": { 9955 "optional": [ 9956 "cssnormalize" 9957 ], 9958 "requires": [ 9959 "cssgrids-base" 9960 ], 9961 "type": "css" 9962 }, 9963 "cssnormalize": { 9964 "type": "css" 9965 }, 9966 "cssnormalize-context": { 9967 "type": "css" 9968 }, 9969 "cssreset": { 9970 "type": "css" 9971 }, 9972 "cssreset-context": { 9973 "type": "css" 9974 }, 9975 "dataschema": { 9976 "use": [ 9977 "dataschema-base", 9978 "dataschema-json", 9979 "dataschema-xml", 9980 "dataschema-array", 9981 "dataschema-text" 9982 ] 9983 }, 9984 "dataschema-array": { 9985 "requires": [ 9986 "dataschema-base" 9987 ] 9988 }, 9989 "dataschema-base": { 9990 "requires": [ 9991 "base" 9992 ] 9993 }, 9994 "dataschema-json": { 9995 "requires": [ 9996 "dataschema-base", 9997 "json" 9998 ] 9999 }, 10000 "dataschema-text": { 10001 "requires": [ 10002 "dataschema-base" 10003 ] 10004 }, 10005 "dataschema-xml": { 10006 "requires": [ 10007 "dataschema-base" 10008 ] 10009 }, 10010 "datasource": { 10011 "use": [ 10012 "datasource-local", 10013 "datasource-io", 10014 "datasource-get", 10015 "datasource-function", 10016 "datasource-cache", 10017 "datasource-jsonschema", 10018 "datasource-xmlschema", 10019 "datasource-arrayschema", 10020 "datasource-textschema", 10021 "datasource-polling" 10022 ] 10023 }, 10024 "datasource-arrayschema": { 10025 "requires": [ 10026 "datasource-local", 10027 "plugin", 10028 "dataschema-array" 10029 ] 10030 }, 10031 "datasource-cache": { 10032 "requires": [ 10033 "datasource-local", 10034 "plugin", 10035 "cache-base" 10036 ] 10037 }, 10038 "datasource-function": { 10039 "requires": [ 10040 "datasource-local" 10041 ] 10042 }, 10043 "datasource-get": { 10044 "requires": [ 10045 "datasource-local", 10046 "get" 10047 ] 10048 }, 10049 "datasource-io": { 10050 "requires": [ 10051 "datasource-local", 10052 "io-base" 10053 ] 10054 }, 10055 "datasource-jsonschema": { 10056 "requires": [ 10057 "datasource-local", 10058 "plugin", 10059 "dataschema-json" 10060 ] 10061 }, 10062 "datasource-local": { 10063 "requires": [ 10064 "base" 10065 ] 10066 }, 10067 "datasource-polling": { 10068 "requires": [ 10069 "datasource-local" 10070 ] 10071 }, 10072 "datasource-textschema": { 10073 "requires": [ 10074 "datasource-local", 10075 "plugin", 10076 "dataschema-text" 10077 ] 10078 }, 10079 "datasource-xmlschema": { 10080 "requires": [ 10081 "datasource-local", 10082 "plugin", 10083 "datatype-xml", 10084 "dataschema-xml" 10085 ] 10086 }, 10087 "datatable": { 10088 "use": [ 10089 "datatable-core", 10090 "datatable-table", 10091 "datatable-head", 10092 "datatable-body", 10093 "datatable-base", 10094 "datatable-column-widths", 10095 "datatable-message", 10096 "datatable-mutable", 10097 "datatable-sort", 10098 "datatable-datasource" 10099 ] 10100 }, 10101 "datatable-base": { 10102 "requires": [ 10103 "datatable-core", 10104 "datatable-table", 10105 "datatable-head", 10106 "datatable-body", 10107 "base-build", 10108 "widget" 10109 ], 10110 "skinnable": true 10111 }, 10112 "datatable-body": { 10113 "requires": [ 10114 "datatable-core", 10115 "view", 10116 "classnamemanager" 10117 ] 10118 }, 10119 "datatable-column-widths": { 10120 "requires": [ 10121 "datatable-base" 10122 ] 10123 }, 10124 "datatable-core": { 10125 "requires": [ 10126 "escape", 10127 "model-list", 10128 "node-event-delegate" 10129 ] 10130 }, 10131 "datatable-datasource": { 10132 "requires": [ 10133 "datatable-base", 10134 "plugin", 10135 "datasource-local" 10136 ] 10137 }, 10138 "datatable-foot": { 10139 "requires": [ 10140 "datatable-core", 10141 "view" 10142 ] 10143 }, 10144 "datatable-formatters": { 10145 "requires": [ 10146 "datatable-body", 10147 "datatype-number-format", 10148 "datatype-date-format", 10149 "escape" 10150 ] 10151 }, 10152 "datatable-head": { 10153 "requires": [ 10154 "datatable-core", 10155 "view", 10156 "classnamemanager" 10157 ] 10158 }, 10159 "datatable-highlight": { 10160 "requires": [ 10161 "datatable-base", 10162 "event-hover" 10163 ], 10164 "skinnable": true 10165 }, 10166 "datatable-keynav": { 10167 "requires": [ 10168 "datatable-base" 10169 ] 10170 }, 10171 "datatable-message": { 10172 "lang": [ 10173 "en", 10174 "fr", 10175 "es", 10176 "hu", 10177 "it" 10178 ], 10179 "requires": [ 10180 "datatable-base" 10181 ], 10182 "skinnable": true 10183 }, 10184 "datatable-mutable": { 10185 "requires": [ 10186 "datatable-base" 10187 ] 10188 }, 10189 "datatable-paginator": { 10190 "lang": [ 10191 "en", 10192 "fr" 10193 ], 10194 "requires": [ 10195 "model", 10196 "view", 10197 "paginator-core", 10198 "datatable-foot", 10199 "datatable-paginator-templates" 10200 ], 10201 "skinnable": true 10202 }, 10203 "datatable-paginator-templates": { 10204 "requires": [ 10205 "template" 10206 ] 10207 }, 10208 "datatable-scroll": { 10209 "requires": [ 10210 "datatable-base", 10211 "datatable-column-widths", 10212 "dom-screen" 10213 ], 10214 "skinnable": true 10215 }, 10216 "datatable-sort": { 10217 "lang": [ 10218 "en", 10219 "fr", 10220 "es", 10221 "hu" 10222 ], 10223 "requires": [ 10224 "datatable-base" 10225 ], 10226 "skinnable": true 10227 }, 10228 "datatable-table": { 10229 "requires": [ 10230 "datatable-core", 10231 "datatable-head", 10232 "datatable-body", 10233 "view", 10234 "classnamemanager" 10235 ] 10236 }, 10237 "datatype": { 10238 "use": [ 10239 "datatype-date", 10240 "datatype-number", 10241 "datatype-xml" 10242 ] 10243 }, 10244 "datatype-date": { 10245 "use": [ 10246 "datatype-date-parse", 10247 "datatype-date-format", 10248 "datatype-date-math" 10249 ] 10250 }, 10251 "datatype-date-format": { 10252 "lang": [ 10253 "ar", 10254 "ar-JO", 10255 "ca", 10256 "ca-ES", 10257 "da", 10258 "da-DK", 10259 "de", 10260 "de-AT", 10261 "de-DE", 10262 "el", 10263 "el-GR", 10264 "en", 10265 "en-AU", 10266 "en-CA", 10267 "en-GB", 10268 "en-IE", 10269 "en-IN", 10270 "en-JO", 10271 "en-MY", 10272 "en-NZ", 10273 "en-PH", 10274 "en-SG", 10275 "en-US", 10276 "es", 10277 "es-AR", 10278 "es-BO", 10279 "es-CL", 10280 "es-CO", 10281 "es-EC", 10282 "es-ES", 10283 "es-MX", 10284 "es-PE", 10285 "es-PY", 10286 "es-US", 10287 "es-UY", 10288 "es-VE", 10289 "fi", 10290 "fi-FI", 10291 "fr", 10292 "fr-BE", 10293 "fr-CA", 10294 "fr-FR", 10295 "hi", 10296 "hi-IN", 10297 "hu", 10298 "id", 10299 "id-ID", 10300 "it", 10301 "it-IT", 10302 "ja", 10303 "ja-JP", 10304 "ko", 10305 "ko-KR", 10306 "ms", 10307 "ms-MY", 10308 "nb", 10309 "nb-NO", 10310 "nl", 10311 "nl-BE", 10312 "nl-NL", 10313 "pl", 10314 "pl-PL", 10315 "pt", 10316 "pt-BR", 10317 "ro", 10318 "ro-RO", 10319 "ru", 10320 "ru-RU", 10321 "sv", 10322 "sv-SE", 10323 "th", 10324 "th-TH", 10325 "tr", 10326 "tr-TR", 10327 "vi", 10328 "vi-VN", 10329 "zh-Hans", 10330 "zh-Hans-CN", 10331 "zh-Hant", 10332 "zh-Hant-HK", 10333 "zh-Hant-TW" 10334 ] 10335 }, 10336 "datatype-date-math": { 10337 "requires": [ 10338 "yui-base" 10339 ] 10340 }, 10341 "datatype-date-parse": {}, 10342 "datatype-number": { 10343 "use": [ 10344 "datatype-number-parse", 10345 "datatype-number-format" 10346 ] 10347 }, 10348 "datatype-number-format": {}, 10349 "datatype-number-parse": { 10350 "requires": [ 10351 "escape" 10352 ] 10353 }, 10354 "datatype-xml": { 10355 "use": [ 10356 "datatype-xml-parse", 10357 "datatype-xml-format" 10358 ] 10359 }, 10360 "datatype-xml-format": {}, 10361 "datatype-xml-parse": {}, 10362 "dd": { 10363 "use": [ 10364 "dd-ddm-base", 10365 "dd-ddm", 10366 "dd-ddm-drop", 10367 "dd-drag", 10368 "dd-proxy", 10369 "dd-constrain", 10370 "dd-drop", 10371 "dd-scroll", 10372 "dd-delegate" 10373 ] 10374 }, 10375 "dd-constrain": { 10376 "requires": [ 10377 "dd-drag" 10378 ] 10379 }, 10380 "dd-ddm": { 10381 "requires": [ 10382 "dd-ddm-base", 10383 "event-resize" 10384 ] 10385 }, 10386 "dd-ddm-base": { 10387 "requires": [ 10388 "node", 10389 "base", 10390 "yui-throttle", 10391 "classnamemanager" 10392 ] 10393 }, 10394 "dd-ddm-drop": { 10395 "requires": [ 10396 "dd-ddm" 10397 ] 10398 }, 10399 "dd-delegate": { 10400 "requires": [ 10401 "dd-drag", 10402 "dd-drop-plugin", 10403 "event-mouseenter" 10404 ] 10405 }, 10406 "dd-drag": { 10407 "requires": [ 10408 "dd-ddm-base" 10409 ] 10410 }, 10411 "dd-drop": { 10412 "requires": [ 10413 "dd-drag", 10414 "dd-ddm-drop" 10415 ] 10416 }, 10417 "dd-drop-plugin": { 10418 "requires": [ 10419 "dd-drop" 10420 ] 10421 }, 10422 "dd-gestures": { 10423 "condition": { 10424 "name": "dd-gestures", 10425 "trigger": "dd-drag", 10426 "ua": "touchEnabled" 10427 }, 10428 "requires": [ 10429 "dd-drag", 10430 "event-synthetic", 10431 "event-gestures" 10432 ] 10433 }, 10434 "dd-plugin": { 10435 "optional": [ 10436 "dd-constrain", 10437 "dd-proxy" 10438 ], 10439 "requires": [ 10440 "dd-drag" 10441 ] 10442 }, 10443 "dd-proxy": { 10444 "requires": [ 10445 "dd-drag" 10446 ] 10447 }, 10448 "dd-scroll": { 10449 "requires": [ 10450 "dd-drag" 10451 ] 10452 }, 10453 "dial": { 10454 "lang": [ 10455 "en", 10456 "es", 10457 "hu" 10458 ], 10459 "requires": [ 10460 "widget", 10461 "dd-drag", 10462 "event-mouseenter", 10463 "event-move", 10464 "event-key", 10465 "transition", 10466 "intl" 10467 ], 10468 "skinnable": true 10469 }, 10470 "dom": { 10471 "use": [ 10472 "dom-base", 10473 "dom-screen", 10474 "dom-style", 10475 "selector-native", 10476 "selector" 10477 ] 10478 }, 10479 "dom-base": { 10480 "requires": [ 10481 "dom-core" 10482 ] 10483 }, 10484 "dom-core": { 10485 "requires": [ 10486 "oop", 10487 "features" 10488 ] 10489 }, 10490 "dom-screen": { 10491 "requires": [ 10492 "dom-base", 10493 "dom-style" 10494 ] 10495 }, 10496 "dom-style": { 10497 "requires": [ 10498 "dom-base" 10499 ] 10500 }, 10501 "dom-style-ie": { 10502 "condition": { 10503 "name": "dom-style-ie", 10504 "test": function (Y) { 10505 10506 var testFeature = Y.Features.test, 10507 addFeature = Y.Features.add, 10508 WINDOW = Y.config.win, 10509 DOCUMENT = Y.config.doc, 10510 DOCUMENT_ELEMENT = 'documentElement', 10511 ret = false; 10512 10513 addFeature('style', 'computedStyle', { 10514 test: function() { 10515 return WINDOW && 'getComputedStyle' in WINDOW; 10516 } 10517 }); 10518 10519 addFeature('style', 'opacity', { 10520 test: function() { 10521 return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style; 10522 } 10523 }); 10524 10525 ret = (!testFeature('style', 'opacity') && 10526 !testFeature('style', 'computedStyle')); 10527 10528 return ret; 10529 }, 10530 "trigger": "dom-style" 10531 }, 10532 "requires": [ 10533 "dom-style", 10534 "color-base" 10535 ] 10536 }, 10537 "dump": { 10538 "requires": [ 10539 "yui-base" 10540 ] 10541 }, 10542 "editor": { 10543 "use": [ 10544 "frame", 10545 "editor-selection", 10546 "exec-command", 10547 "editor-base", 10548 "editor-para", 10549 "editor-br", 10550 "editor-bidi", 10551 "editor-tab", 10552 "createlink-base" 10553 ] 10554 }, 10555 "editor-base": { 10556 "requires": [ 10557 "base", 10558 "frame", 10559 "node", 10560 "exec-command", 10561 "editor-selection" 10562 ] 10563 }, 10564 "editor-bidi": { 10565 "requires": [ 10566 "editor-base" 10567 ] 10568 }, 10569 "editor-br": { 10570 "requires": [ 10571 "editor-base" 10572 ] 10573 }, 10574 "editor-inline": { 10575 "requires": [ 10576 "editor-base", 10577 "content-editable" 10578 ] 10579 }, 10580 "editor-lists": { 10581 "requires": [ 10582 "editor-base" 10583 ] 10584 }, 10585 "editor-para": { 10586 "requires": [ 10587 "editor-para-base" 10588 ] 10589 }, 10590 "editor-para-base": { 10591 "requires": [ 10592 "editor-base" 10593 ] 10594 }, 10595 "editor-para-ie": { 10596 "condition": { 10597 "name": "editor-para-ie", 10598 "trigger": "editor-para", 10599 "ua": "ie", 10600 "when": "instead" 10601 }, 10602 "requires": [ 10603 "editor-para-base" 10604 ] 10605 }, 10606 "editor-selection": { 10607 "requires": [ 10608 "node" 10609 ] 10610 }, 10611 "editor-tab": { 10612 "requires": [ 10613 "editor-base" 10614 ] 10615 }, 10616 "escape": { 10617 "requires": [ 10618 "yui-base" 10619 ] 10620 }, 10621 "event": { 10622 "after": [ 10623 "node-base" 10624 ], 10625 "use": [ 10626 "event-base", 10627 "event-delegate", 10628 "event-synthetic", 10629 "event-mousewheel", 10630 "event-mouseenter", 10631 "event-key", 10632 "event-focus", 10633 "event-resize", 10634 "event-hover", 10635 "event-outside", 10636 "event-touch", 10637 "event-move", 10638 "event-flick", 10639 "event-valuechange", 10640 "event-tap" 10641 ] 10642 }, 10643 "event-base": { 10644 "after": [ 10645 "node-base" 10646 ], 10647 "requires": [ 10648 "event-custom-base" 10649 ] 10650 }, 10651 "event-base-ie": { 10652 "after": [ 10653 "event-base" 10654 ], 10655 "condition": { 10656 "name": "event-base-ie", 10657 "test": function(Y) { 10658 var imp = Y.config.doc && Y.config.doc.implementation; 10659 return (imp && (!imp.hasFeature('Events', '2.0'))); 10660 }, 10661 "trigger": "node-base" 10662 }, 10663 "requires": [ 10664 "node-base" 10665 ] 10666 }, 10667 "event-contextmenu": { 10668 "requires": [ 10669 "event-synthetic", 10670 "dom-screen" 10671 ] 10672 }, 10673 "event-custom": { 10674 "use": [ 10675 "event-custom-base", 10676 "event-custom-complex" 10677 ] 10678 }, 10679 "event-custom-base": { 10680 "requires": [ 10681 "oop" 10682 ] 10683 }, 10684 "event-custom-complex": { 10685 "requires": [ 10686 "event-custom-base" 10687 ] 10688 }, 10689 "event-delegate": { 10690 "requires": [ 10691 "node-base" 10692 ] 10693 }, 10694 "event-flick": { 10695 "requires": [ 10696 "node-base", 10697 "event-touch", 10698 "event-synthetic" 10699 ] 10700 }, 10701 "event-focus": { 10702 "requires": [ 10703 "event-synthetic" 10704 ] 10705 }, 10706 "event-gestures": { 10707 "use": [ 10708 "event-flick", 10709 "event-move" 10710 ] 10711 }, 10712 "event-hover": { 10713 "requires": [ 10714 "event-mouseenter" 10715 ] 10716 }, 10717 "event-key": { 10718 "requires": [ 10719 "event-synthetic" 10720 ] 10721 }, 10722 "event-mouseenter": { 10723 "requires": [ 10724 "event-synthetic" 10725 ] 10726 }, 10727 "event-mousewheel": { 10728 "requires": [ 10729 "node-base" 10730 ] 10731 }, 10732 "event-move": { 10733 "requires": [ 10734 "node-base", 10735 "event-touch", 10736 "event-synthetic" 10737 ] 10738 }, 10739 "event-outside": { 10740 "requires": [ 10741 "event-synthetic" 10742 ] 10743 }, 10744 "event-resize": { 10745 "requires": [ 10746 "node-base", 10747 "event-synthetic" 10748 ] 10749 }, 10750 "event-simulate": { 10751 "requires": [ 10752 "event-base" 10753 ] 10754 }, 10755 "event-synthetic": { 10756 "requires": [ 10757 "node-base", 10758 "event-custom-complex" 10759 ] 10760 }, 10761 "event-tap": { 10762 "requires": [ 10763 "node-base", 10764 "event-base", 10765 "event-touch", 10766 "event-synthetic" 10767 ] 10768 }, 10769 "event-touch": { 10770 "requires": [ 10771 "node-base" 10772 ] 10773 }, 10774 "event-valuechange": { 10775 "requires": [ 10776 "event-focus", 10777 "event-synthetic" 10778 ] 10779 }, 10780 "exec-command": { 10781 "requires": [ 10782 "frame" 10783 ] 10784 }, 10785 "features": { 10786 "requires": [ 10787 "yui-base" 10788 ] 10789 }, 10790 "file": { 10791 "requires": [ 10792 "file-flash", 10793 "file-html5" 10794 ] 10795 }, 10796 "file-flash": { 10797 "requires": [ 10798 "base" 10799 ] 10800 }, 10801 "file-html5": { 10802 "requires": [ 10803 "base" 10804 ] 10805 }, 10806 "frame": { 10807 "requires": [ 10808 "base", 10809 "node", 10810 "plugin", 10811 "selector-css3", 10812 "yui-throttle" 10813 ] 10814 }, 10815 "gesture-simulate": { 10816 "requires": [ 10817 "async-queue", 10818 "event-simulate", 10819 "node-screen" 10820 ] 10821 }, 10822 "get": { 10823 "requires": [ 10824 "yui-base" 10825 ] 10826 }, 10827 "graphics": { 10828 "requires": [ 10829 "node", 10830 "event-custom", 10831 "pluginhost", 10832 "matrix", 10833 "classnamemanager" 10834 ] 10835 }, 10836 "graphics-canvas": { 10837 "condition": { 10838 "name": "graphics-canvas", 10839 "test": function(Y) { 10840 var DOCUMENT = Y.config.doc, 10841 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 10842 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 10843 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 10844 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 10845 }, 10846 "trigger": "graphics" 10847 }, 10848 "requires": [ 10849 "graphics", 10850 "color-base" 10851 ] 10852 }, 10853 "graphics-canvas-default": { 10854 "condition": { 10855 "name": "graphics-canvas-default", 10856 "test": function(Y) { 10857 var DOCUMENT = Y.config.doc, 10858 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", 10859 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 10860 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 10861 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); 10862 }, 10863 "trigger": "graphics" 10864 } 10865 }, 10866 "graphics-group": { 10867 "requires": [ 10868 "graphics" 10869 ] 10870 }, 10871 "graphics-svg": { 10872 "condition": { 10873 "name": "graphics-svg", 10874 "test": function(Y) { 10875 var DOCUMENT = Y.config.doc, 10876 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 10877 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 10878 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 10879 10880 return svg && (useSVG || !canvas); 10881 }, 10882 "trigger": "graphics" 10883 }, 10884 "requires": [ 10885 "graphics" 10886 ] 10887 }, 10888 "graphics-svg-default": { 10889 "condition": { 10890 "name": "graphics-svg-default", 10891 "test": function(Y) { 10892 var DOCUMENT = Y.config.doc, 10893 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", 10894 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), 10895 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); 10896 10897 return svg && (useSVG || !canvas); 10898 }, 10899 "trigger": "graphics" 10900 } 10901 }, 10902 "graphics-vml": { 10903 "condition": { 10904 "name": "graphics-vml", 10905 "test": function(Y) { 10906 var DOCUMENT = Y.config.doc, 10907 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 10908 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 10909 }, 10910 "trigger": "graphics" 10911 }, 10912 "requires": [ 10913 "graphics", 10914 "color-base" 10915 ] 10916 }, 10917 "graphics-vml-default": { 10918 "condition": { 10919 "name": "graphics-vml-default", 10920 "test": function(Y) { 10921 var DOCUMENT = Y.config.doc, 10922 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); 10923 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); 10924 }, 10925 "trigger": "graphics" 10926 } 10927 }, 10928 "handlebars": { 10929 "use": [ 10930 "handlebars-compiler" 10931 ] 10932 }, 10933 "handlebars-base": { 10934 "requires": [] 10935 }, 10936 "handlebars-compiler": { 10937 "requires": [ 10938 "handlebars-base" 10939 ] 10940 }, 10941 "highlight": { 10942 "use": [ 10943 "highlight-base", 10944 "highlight-accentfold" 10945 ] 10946 }, 10947 "highlight-accentfold": { 10948 "requires": [ 10949 "highlight-base", 10950 "text-accentfold" 10951 ] 10952 }, 10953 "highlight-base": { 10954 "requires": [ 10955 "array-extras", 10956 "classnamemanager", 10957 "escape", 10958 "text-wordbreak" 10959 ] 10960 }, 10961 "history": { 10962 "use": [ 10963 "history-base", 10964 "history-hash", 10965 "history-html5" 10966 ] 10967 }, 10968 "history-base": { 10969 "requires": [ 10970 "event-custom-complex" 10971 ] 10972 }, 10973 "history-hash": { 10974 "after": [ 10975 "history-html5" 10976 ], 10977 "requires": [ 10978 "event-synthetic", 10979 "history-base", 10980 "yui-later" 10981 ] 10982 }, 10983 "history-hash-ie": { 10984 "condition": { 10985 "name": "history-hash-ie", 10986 "test": function (Y) { 10987 var docMode = Y.config.doc && Y.config.doc.documentMode; 10988 10989 return Y.UA.ie && (!('onhashchange' in Y.config.win) || 10990 !docMode || docMode < 8); 10991 }, 10992 "trigger": "history-hash" 10993 }, 10994 "requires": [ 10995 "history-hash", 10996 "node-base" 10997 ] 10998 }, 10999 "history-html5": { 11000 "optional": [ 11001 "json" 11002 ], 11003 "requires": [ 11004 "event-base", 11005 "history-base", 11006 "node-base" 11007 ] 11008 }, 11009 "imageloader": { 11010 "requires": [ 11011 "base-base", 11012 "node-style", 11013 "node-screen" 11014 ] 11015 }, 11016 "intl": { 11017 "requires": [ 11018 "intl-base", 11019 "event-custom" 11020 ] 11021 }, 11022 "intl-base": { 11023 "requires": [ 11024 "yui-base" 11025 ] 11026 }, 11027 "io": { 11028 "use": [ 11029 "io-base", 11030 "io-xdr", 11031 "io-form", 11032 "io-upload-iframe", 11033 "io-queue" 11034 ] 11035 }, 11036 "io-base": { 11037 "requires": [ 11038 "event-custom-base", 11039 "querystring-stringify-simple" 11040 ] 11041 }, 11042 "io-form": { 11043 "requires": [ 11044 "io-base", 11045 "node-base" 11046 ] 11047 }, 11048 "io-nodejs": { 11049 "condition": { 11050 "name": "io-nodejs", 11051 "trigger": "io-base", 11052 "ua": "nodejs" 11053 }, 11054 "requires": [ 11055 "io-base" 11056 ] 11057 }, 11058 "io-queue": { 11059 "requires": [ 11060 "io-base", 11061 "queue-promote" 11062 ] 11063 }, 11064 "io-upload-iframe": { 11065 "requires": [ 11066 "io-base", 11067 "node-base" 11068 ] 11069 }, 11070 "io-xdr": { 11071 "requires": [ 11072 "io-base", 11073 "datatype-xml-parse" 11074 ] 11075 }, 11076 "json": { 11077 "use": [ 11078 "json-parse", 11079 "json-stringify" 11080 ] 11081 }, 11082 "json-parse": { 11083 "requires": [ 11084 "yui-base" 11085 ] 11086 }, 11087 "json-parse-shim": { 11088 "condition": { 11089 "name": "json-parse-shim", 11090 "test": function (Y) { 11091 var _JSON = Y.config.global.JSON, 11092 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 11093 nativeSupport = Y.config.useNativeJSONParse !== false && !!Native; 11094 11095 function workingNative( k, v ) { 11096 return k === "ok" ? true : v; 11097 } 11098 11099 // Double check basic functionality. This is mainly to catch early broken 11100 // implementations of the JSON API in Firefox 3.1 beta1 and beta2 11101 if ( nativeSupport ) { 11102 try { 11103 nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok; 11104 } 11105 catch ( e ) { 11106 nativeSupport = false; 11107 } 11108 } 11109 11110 return !nativeSupport; 11111 }, 11112 "trigger": "json-parse" 11113 }, 11114 "requires": [ 11115 "json-parse" 11116 ] 11117 }, 11118 "json-stringify": { 11119 "requires": [ 11120 "yui-base" 11121 ] 11122 }, 11123 "json-stringify-shim": { 11124 "condition": { 11125 "name": "json-stringify-shim", 11126 "test": function (Y) { 11127 var _JSON = Y.config.global.JSON, 11128 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, 11129 nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native; 11130 11131 // Double check basic native functionality. This is primarily to catch broken 11132 // early JSON API implementations in Firefox 3.1 beta1 and beta2. 11133 if ( nativeSupport ) { 11134 try { 11135 nativeSupport = ( '0' === Native.stringify(0) ); 11136 } catch ( e ) { 11137 nativeSupport = false; 11138 } 11139 } 11140 11141 11142 return !nativeSupport; 11143 }, 11144 "trigger": "json-stringify" 11145 }, 11146 "requires": [ 11147 "json-stringify" 11148 ] 11149 }, 11150 "jsonp": { 11151 "requires": [ 11152 "get", 11153 "oop" 11154 ] 11155 }, 11156 "jsonp-url": { 11157 "requires": [ 11158 "jsonp" 11159 ] 11160 }, 11161 "lazy-model-list": { 11162 "requires": [ 11163 "model-list" 11164 ] 11165 }, 11166 "loader": { 11167 "use": [ 11168 "loader-base", 11169 "loader-rollup", 11170 "loader-yui3" 11171 ] 11172 }, 11173 "loader-base": { 11174 "requires": [ 11175 "get", 11176 "features" 11177 ] 11178 }, 11179 "loader-rollup": { 11180 "requires": [ 11181 "loader-base" 11182 ] 11183 }, 11184 "loader-yui3": { 11185 "requires": [ 11186 "loader-base" 11187 ] 11188 }, 11189 "matrix": { 11190 "requires": [ 11191 "yui-base" 11192 ] 11193 }, 11194 "model": { 11195 "requires": [ 11196 "base-build", 11197 "escape", 11198 "json-parse" 11199 ] 11200 }, 11201 "model-list": { 11202 "requires": [ 11203 "array-extras", 11204 "array-invoke", 11205 "arraylist", 11206 "base-build", 11207 "escape", 11208 "json-parse", 11209 "model" 11210 ] 11211 }, 11212 "model-sync-local": { 11213 "requires": [ 11214 "model", 11215 "json-stringify" 11216 ] 11217 }, 11218 "model-sync-rest": { 11219 "requires": [ 11220 "model", 11221 "io-base", 11222 "json-stringify" 11223 ] 11224 }, 11225 "node": { 11226 "use": [ 11227 "node-base", 11228 "node-event-delegate", 11229 "node-pluginhost", 11230 "node-screen", 11231 "node-style" 11232 ] 11233 }, 11234 "node-base": { 11235 "requires": [ 11236 "event-base", 11237 "node-core", 11238 "dom-base", 11239 "dom-style" 11240 ] 11241 }, 11242 "node-core": { 11243 "requires": [ 11244 "dom-core", 11245 "selector" 11246 ] 11247 }, 11248 "node-event-delegate": { 11249 "requires": [ 11250 "node-base", 11251 "event-delegate" 11252 ] 11253 }, 11254 "node-event-html5": { 11255 "requires": [ 11256 "node-base" 11257 ] 11258 }, 11259 "node-event-simulate": { 11260 "requires": [ 11261 "node-base", 11262 "event-simulate", 11263 "gesture-simulate" 11264 ] 11265 }, 11266 "node-flick": { 11267 "requires": [ 11268 "classnamemanager", 11269 "transition", 11270 "event-flick", 11271 "plugin" 11272 ], 11273 "skinnable": true 11274 }, 11275 "node-focusmanager": { 11276 "requires": [ 11277 "attribute", 11278 "node", 11279 "plugin", 11280 "node-event-simulate", 11281 "event-key", 11282 "event-focus" 11283 ] 11284 }, 11285 "node-load": { 11286 "requires": [ 11287 "node-base", 11288 "io-base" 11289 ] 11290 }, 11291 "node-menunav": { 11292 "requires": [ 11293 "node", 11294 "classnamemanager", 11295 "plugin", 11296 "node-focusmanager" 11297 ], 11298 "skinnable": true 11299 }, 11300 "node-pluginhost": { 11301 "requires": [ 11302 "node-base", 11303 "pluginhost" 11304 ] 11305 }, 11306 "node-screen": { 11307 "requires": [ 11308 "dom-screen", 11309 "node-base" 11310 ] 11311 }, 11312 "node-scroll-info": { 11313 "requires": [ 11314 "array-extras", 11315 "base-build", 11316 "event-resize", 11317 "node-pluginhost", 11318 "plugin", 11319 "selector" 11320 ] 11321 }, 11322 "node-style": { 11323 "requires": [ 11324 "dom-style", 11325 "node-base" 11326 ] 11327 }, 11328 "oop": { 11329 "requires": [ 11330 "yui-base" 11331 ] 11332 }, 11333 "overlay": { 11334 "requires": [ 11335 "widget", 11336 "widget-stdmod", 11337 "widget-position", 11338 "widget-position-align", 11339 "widget-stack", 11340 "widget-position-constrain" 11341 ], 11342 "skinnable": true 11343 }, 11344 "paginator": { 11345 "requires": [ 11346 "paginator-core" 11347 ] 11348 }, 11349 "paginator-core": { 11350 "requires": [ 11351 "base" 11352 ] 11353 }, 11354 "paginator-url": { 11355 "requires": [ 11356 "paginator" 11357 ] 11358 }, 11359 "panel": { 11360 "requires": [ 11361 "widget", 11362 "widget-autohide", 11363 "widget-buttons", 11364 "widget-modality", 11365 "widget-position", 11366 "widget-position-align", 11367 "widget-position-constrain", 11368 "widget-stack", 11369 "widget-stdmod" 11370 ], 11371 "skinnable": true 11372 }, 11373 "parallel": { 11374 "requires": [ 11375 "yui-base" 11376 ] 11377 }, 11378 "pjax": { 11379 "requires": [ 11380 "pjax-base", 11381 "pjax-content" 11382 ] 11383 }, 11384 "pjax-base": { 11385 "requires": [ 11386 "classnamemanager", 11387 "node-event-delegate", 11388 "router" 11389 ] 11390 }, 11391 "pjax-content": { 11392 "requires": [ 11393 "io-base", 11394 "node-base", 11395 "router" 11396 ] 11397 }, 11398 "pjax-plugin": { 11399 "requires": [ 11400 "node-pluginhost", 11401 "pjax", 11402 "plugin" 11403 ] 11404 }, 11405 "plugin": { 11406 "requires": [ 11407 "base-base" 11408 ] 11409 }, 11410 "pluginhost": { 11411 "use": [ 11412 "pluginhost-base", 11413 "pluginhost-config" 11414 ] 11415 }, 11416 "pluginhost-base": { 11417 "requires": [ 11418 "yui-base" 11419 ] 11420 }, 11421 "pluginhost-config": { 11422 "requires": [ 11423 "pluginhost-base" 11424 ] 11425 }, 11426 "promise": { 11427 "requires": [ 11428 "timers" 11429 ] 11430 }, 11431 "querystring": { 11432 "use": [ 11433 "querystring-parse", 11434 "querystring-stringify" 11435 ] 11436 }, 11437 "querystring-parse": { 11438 "requires": [ 11439 "yui-base", 11440 "array-extras" 11441 ] 11442 }, 11443 "querystring-parse-simple": { 11444 "requires": [ 11445 "yui-base" 11446 ] 11447 }, 11448 "querystring-stringify": { 11449 "requires": [ 11450 "yui-base" 11451 ] 11452 }, 11453 "querystring-stringify-simple": { 11454 "requires": [ 11455 "yui-base" 11456 ] 11457 }, 11458 "queue-promote": { 11459 "requires": [ 11460 "yui-base" 11461 ] 11462 }, 11463 "range-slider": { 11464 "requires": [ 11465 "slider-base", 11466 "slider-value-range", 11467 "clickable-rail" 11468 ] 11469 }, 11470 "recordset": { 11471 "use": [ 11472 "recordset-base", 11473 "recordset-sort", 11474 "recordset-filter", 11475 "recordset-indexer" 11476 ] 11477 }, 11478 "recordset-base": { 11479 "requires": [ 11480 "base", 11481 "arraylist" 11482 ] 11483 }, 11484 "recordset-filter": { 11485 "requires": [ 11486 "recordset-base", 11487 "array-extras", 11488 "plugin" 11489 ] 11490 }, 11491 "recordset-indexer": { 11492 "requires": [ 11493 "recordset-base", 11494 "plugin" 11495 ] 11496 }, 11497 "recordset-sort": { 11498 "requires": [ 11499 "arraysort", 11500 "recordset-base", 11501 "plugin" 11502 ] 11503 }, 11504 "resize": { 11505 "use": [ 11506 "resize-base", 11507 "resize-proxy", 11508 "resize-constrain" 11509 ] 11510 }, 11511 "resize-base": { 11512 "requires": [ 11513 "base", 11514 "widget", 11515 "event", 11516 "oop", 11517 "dd-drag", 11518 "dd-delegate", 11519 "dd-drop" 11520 ], 11521 "skinnable": true 11522 }, 11523 "resize-constrain": { 11524 "requires": [ 11525 "plugin", 11526 "resize-base" 11527 ] 11528 }, 11529 "resize-plugin": { 11530 "optional": [ 11531 "resize-constrain" 11532 ], 11533 "requires": [ 11534 "resize-base", 11535 "plugin" 11536 ] 11537 }, 11538 "resize-proxy": { 11539 "requires": [ 11540 "plugin", 11541 "resize-base" 11542 ] 11543 }, 11544 "router": { 11545 "optional": [ 11546 "querystring-parse" 11547 ], 11548 "requires": [ 11549 "array-extras", 11550 "base-build", 11551 "history" 11552 ] 11553 }, 11554 "scrollview": { 11555 "requires": [ 11556 "scrollview-base", 11557 "scrollview-scrollbars" 11558 ] 11559 }, 11560 "scrollview-base": { 11561 "requires": [ 11562 "widget", 11563 "event-gestures", 11564 "event-mousewheel", 11565 "transition" 11566 ], 11567 "skinnable": true 11568 }, 11569 "scrollview-base-ie": { 11570 "condition": { 11571 "name": "scrollview-base-ie", 11572 "trigger": "scrollview-base", 11573 "ua": "ie" 11574 }, 11575 "requires": [ 11576 "scrollview-base" 11577 ] 11578 }, 11579 "scrollview-list": { 11580 "requires": [ 11581 "plugin", 11582 "classnamemanager" 11583 ], 11584 "skinnable": true 11585 }, 11586 "scrollview-paginator": { 11587 "requires": [ 11588 "plugin", 11589 "classnamemanager" 11590 ] 11591 }, 11592 "scrollview-scrollbars": { 11593 "requires": [ 11594 "classnamemanager", 11595 "transition", 11596 "plugin" 11597 ], 11598 "skinnable": true 11599 }, 11600 "selector": { 11601 "requires": [ 11602 "selector-native" 11603 ] 11604 }, 11605 "selector-css2": { 11606 "condition": { 11607 "name": "selector-css2", 11608 "test": function (Y) { 11609 var DOCUMENT = Y.config.doc, 11610 ret = DOCUMENT && !('querySelectorAll' in DOCUMENT); 11611 11612 return ret; 11613 }, 11614 "trigger": "selector" 11615 }, 11616 "requires": [ 11617 "selector-native" 11618 ] 11619 }, 11620 "selector-css3": { 11621 "requires": [ 11622 "selector-native", 11623 "selector-css2" 11624 ] 11625 }, 11626 "selector-native": { 11627 "requires": [ 11628 "dom-base" 11629 ] 11630 }, 11631 "series-area": { 11632 "requires": [ 11633 "series-cartesian", 11634 "series-fill-util" 11635 ] 11636 }, 11637 "series-area-stacked": { 11638 "requires": [ 11639 "series-stacked", 11640 "series-area" 11641 ] 11642 }, 11643 "series-areaspline": { 11644 "requires": [ 11645 "series-area", 11646 "series-curve-util" 11647 ] 11648 }, 11649 "series-areaspline-stacked": { 11650 "requires": [ 11651 "series-stacked", 11652 "series-areaspline" 11653 ] 11654 }, 11655 "series-bar": { 11656 "requires": [ 11657 "series-marker", 11658 "series-histogram-base" 11659 ] 11660 }, 11661 "series-bar-stacked": { 11662 "requires": [ 11663 "series-stacked", 11664 "series-bar" 11665 ] 11666 }, 11667 "series-base": { 11668 "requires": [ 11669 "graphics", 11670 "axis-base" 11671 ] 11672 }, 11673 "series-candlestick": { 11674 "requires": [ 11675 "series-range" 11676 ] 11677 }, 11678 "series-cartesian": { 11679 "requires": [ 11680 "series-base" 11681 ] 11682 }, 11683 "series-column": { 11684 "requires": [ 11685 "series-marker", 11686 "series-histogram-base" 11687 ] 11688 }, 11689 "series-column-stacked": { 11690 "requires": [ 11691 "series-stacked", 11692 "series-column" 11693 ] 11694 }, 11695 "series-combo": { 11696 "requires": [ 11697 "series-cartesian", 11698 "series-line-util", 11699 "series-plot-util", 11700 "series-fill-util" 11701 ] 11702 }, 11703 "series-combo-stacked": { 11704 "requires": [ 11705 "series-stacked", 11706 "series-combo" 11707 ] 11708 }, 11709 "series-combospline": { 11710 "requires": [ 11711 "series-combo", 11712 "series-curve-util" 11713 ] 11714 }, 11715 "series-combospline-stacked": { 11716 "requires": [ 11717 "series-combo-stacked", 11718 "series-curve-util" 11719 ] 11720 }, 11721 "series-curve-util": {}, 11722 "series-fill-util": {}, 11723 "series-histogram-base": { 11724 "requires": [ 11725 "series-cartesian", 11726 "series-plot-util" 11727 ] 11728 }, 11729 "series-line": { 11730 "requires": [ 11731 "series-cartesian", 11732 "series-line-util" 11733 ] 11734 }, 11735 "series-line-stacked": { 11736 "requires": [ 11737 "series-stacked", 11738 "series-line" 11739 ] 11740 }, 11741 "series-line-util": {}, 11742 "series-marker": { 11743 "requires": [ 11744 "series-cartesian", 11745 "series-plot-util" 11746 ] 11747 }, 11748 "series-marker-stacked": { 11749 "requires": [ 11750 "series-stacked", 11751 "series-marker" 11752 ] 11753 }, 11754 "series-ohlc": { 11755 "requires": [ 11756 "series-range" 11757 ] 11758 }, 11759 "series-pie": { 11760 "requires": [ 11761 "series-base", 11762 "series-plot-util" 11763 ] 11764 }, 11765 "series-plot-util": {}, 11766 "series-range": { 11767 "requires": [ 11768 "series-cartesian" 11769 ] 11770 }, 11771 "series-spline": { 11772 "requires": [ 11773 "series-line", 11774 "series-curve-util" 11775 ] 11776 }, 11777 "series-spline-stacked": { 11778 "requires": [ 11779 "series-stacked", 11780 "series-spline" 11781 ] 11782 }, 11783 "series-stacked": { 11784 "requires": [ 11785 "axis-stacked" 11786 ] 11787 }, 11788 "shim-plugin": { 11789 "requires": [ 11790 "node-style", 11791 "node-pluginhost" 11792 ] 11793 }, 11794 "slider": { 11795 "use": [ 11796 "slider-base", 11797 "slider-value-range", 11798 "clickable-rail", 11799 "range-slider" 11800 ] 11801 }, 11802 "slider-base": { 11803 "requires": [ 11804 "widget", 11805 "dd-constrain", 11806 "event-key" 11807 ], 11808 "skinnable": true 11809 }, 11810 "slider-value-range": { 11811 "requires": [ 11812 "slider-base" 11813 ] 11814 }, 11815 "sortable": { 11816 "requires": [ 11817 "dd-delegate", 11818 "dd-drop-plugin", 11819 "dd-proxy" 11820 ] 11821 }, 11822 "sortable-scroll": { 11823 "requires": [ 11824 "dd-scroll", 11825 "sortable" 11826 ] 11827 }, 11828 "stylesheet": { 11829 "requires": [ 11830 "yui-base" 11831 ] 11832 }, 11833 "substitute": { 11834 "optional": [ 11835 "dump" 11836 ], 11837 "requires": [ 11838 "yui-base" 11839 ] 11840 }, 11841 "swf": { 11842 "requires": [ 11843 "event-custom", 11844 "node", 11845 "swfdetect", 11846 "escape" 11847 ] 11848 }, 11849 "swfdetect": { 11850 "requires": [ 11851 "yui-base" 11852 ] 11853 }, 11854 "tabview": { 11855 "requires": [ 11856 "widget", 11857 "widget-parent", 11858 "widget-child", 11859 "tabview-base", 11860 "node-pluginhost", 11861 "node-focusmanager" 11862 ], 11863 "skinnable": true 11864 }, 11865 "tabview-base": { 11866 "requires": [ 11867 "node-event-delegate", 11868 "classnamemanager" 11869 ] 11870 }, 11871 "tabview-plugin": { 11872 "requires": [ 11873 "tabview-base" 11874 ] 11875 }, 11876 "template": { 11877 "use": [ 11878 "template-base", 11879 "template-micro" 11880 ] 11881 }, 11882 "template-base": { 11883 "requires": [ 11884 "yui-base" 11885 ] 11886 }, 11887 "template-micro": { 11888 "requires": [ 11889 "escape" 11890 ] 11891 }, 11892 "test": { 11893 "requires": [ 11894 "event-simulate", 11895 "event-custom", 11896 "json-stringify" 11897 ] 11898 }, 11899 "test-console": { 11900 "requires": [ 11901 "console-filters", 11902 "test", 11903 "array-extras" 11904 ], 11905 "skinnable": true 11906 }, 11907 "text": { 11908 "use": [ 11909 "text-accentfold", 11910 "text-wordbreak" 11911 ] 11912 }, 11913 "text-accentfold": { 11914 "requires": [ 11915 "array-extras", 11916 "text-data-accentfold" 11917 ] 11918 }, 11919 "text-data-accentfold": { 11920 "requires": [ 11921 "yui-base" 11922 ] 11923 }, 11924 "text-data-wordbreak": { 11925 "requires": [ 11926 "yui-base" 11927 ] 11928 }, 11929 "text-wordbreak": { 11930 "requires": [ 11931 "array-extras", 11932 "text-data-wordbreak" 11933 ] 11934 }, 11935 "timers": { 11936 "requires": [ 11937 "yui-base" 11938 ] 11939 }, 11940 "transition": { 11941 "requires": [ 11942 "node-style" 11943 ] 11944 }, 11945 "transition-timer": { 11946 "condition": { 11947 "name": "transition-timer", 11948 "test": function (Y) { 11949 var DOCUMENT = Y.config.doc, 11950 node = (DOCUMENT) ? DOCUMENT.documentElement: null, 11951 ret = true; 11952 11953 if (node && node.style) { 11954 ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); 11955 } 11956 11957 return ret; 11958 }, 11959 "trigger": "transition" 11960 }, 11961 "requires": [ 11962 "transition" 11963 ] 11964 }, 11965 "tree": { 11966 "requires": [ 11967 "base-build", 11968 "tree-node" 11969 ] 11970 }, 11971 "tree-labelable": { 11972 "requires": [ 11973 "tree" 11974 ] 11975 }, 11976 "tree-lazy": { 11977 "requires": [ 11978 "base-pluginhost", 11979 "plugin", 11980 "tree" 11981 ] 11982 }, 11983 "tree-node": {}, 11984 "tree-openable": { 11985 "requires": [ 11986 "tree" 11987 ] 11988 }, 11989 "tree-selectable": { 11990 "requires": [ 11991 "tree" 11992 ] 11993 }, 11994 "tree-sortable": { 11995 "requires": [ 11996 "tree" 11997 ] 11998 }, 11999 "uploader": { 12000 "requires": [ 12001 "uploader-html5", 12002 "uploader-flash" 12003 ] 12004 }, 12005 "uploader-flash": { 12006 "requires": [ 12007 "swfdetect", 12008 "escape", 12009 "widget", 12010 "base", 12011 "cssbutton", 12012 "node", 12013 "event-custom", 12014 "uploader-queue" 12015 ] 12016 }, 12017 "uploader-html5": { 12018 "requires": [ 12019 "widget", 12020 "node-event-simulate", 12021 "file-html5", 12022 "uploader-queue" 12023 ] 12024 }, 12025 "uploader-queue": { 12026 "requires": [ 12027 "base" 12028 ] 12029 }, 12030 "view": { 12031 "requires": [ 12032 "base-build", 12033 "node-event-delegate" 12034 ] 12035 }, 12036 "view-node-map": { 12037 "requires": [ 12038 "view" 12039 ] 12040 }, 12041 "widget": { 12042 "use": [ 12043 "widget-base", 12044 "widget-htmlparser", 12045 "widget-skin", 12046 "widget-uievents" 12047 ] 12048 }, 12049 "widget-anim": { 12050 "requires": [ 12051 "anim-base", 12052 "plugin", 12053 "widget" 12054 ] 12055 }, 12056 "widget-autohide": { 12057 "requires": [ 12058 "base-build", 12059 "event-key", 12060 "event-outside", 12061 "widget" 12062 ] 12063 }, 12064 "widget-base": { 12065 "requires": [ 12066 "attribute", 12067 "base-base", 12068 "base-pluginhost", 12069 "classnamemanager", 12070 "event-focus", 12071 "node-base", 12072 "node-style" 12073 ], 12074 "skinnable": true 12075 }, 12076 "widget-base-ie": { 12077 "condition": { 12078 "name": "widget-base-ie", 12079 "trigger": "widget-base", 12080 "ua": "ie" 12081 }, 12082 "requires": [ 12083 "widget-base" 12084 ] 12085 }, 12086 "widget-buttons": { 12087 "requires": [ 12088 "button-plugin", 12089 "cssbutton", 12090 "widget-stdmod" 12091 ] 12092 }, 12093 "widget-child": { 12094 "requires": [ 12095 "base-build", 12096 "widget" 12097 ] 12098 }, 12099 "widget-htmlparser": { 12100 "requires": [ 12101 "widget-base" 12102 ] 12103 }, 12104 "widget-modality": { 12105 "requires": [ 12106 "base-build", 12107 "event-outside", 12108 "widget" 12109 ], 12110 "skinnable": true 12111 }, 12112 "widget-parent": { 12113 "requires": [ 12114 "arraylist", 12115 "base-build", 12116 "widget" 12117 ] 12118 }, 12119 "widget-position": { 12120 "requires": [ 12121 "base-build", 12122 "node-screen", 12123 "widget" 12124 ] 12125 }, 12126 "widget-position-align": { 12127 "requires": [ 12128 "widget-position" 12129 ] 12130 }, 12131 "widget-position-constrain": { 12132 "requires": [ 12133 "widget-position" 12134 ] 12135 }, 12136 "widget-skin": { 12137 "requires": [ 12138 "widget-base" 12139 ] 12140 }, 12141 "widget-stack": { 12142 "requires": [ 12143 "base-build", 12144 "widget" 12145 ], 12146 "skinnable": true 12147 }, 12148 "widget-stdmod": { 12149 "requires": [ 12150 "base-build", 12151 "widget" 12152 ] 12153 }, 12154 "widget-uievents": { 12155 "requires": [ 12156 "node-event-delegate", 12157 "widget-base" 12158 ] 12159 }, 12160 "yql": { 12161 "requires": [ 12162 "oop" 12163 ] 12164 }, 12165 "yql-jsonp": { 12166 "condition": { 12167 "name": "yql-jsonp", 12168 "test": function (Y) { 12169 /* Only load the JSONP module when not in nodejs or winjs 12170 TODO Make the winjs module a CORS module 12171 */ 12172 return (!Y.UA.nodejs && !Y.UA.winjs); 12173 }, 12174 "trigger": "yql" 12175 }, 12176 "requires": [ 12177 "yql", 12178 "jsonp", 12179 "jsonp-url" 12180 ] 12181 }, 12182 "yql-nodejs": { 12183 "condition": { 12184 "name": "yql-nodejs", 12185 "trigger": "yql", 12186 "ua": "nodejs" 12187 }, 12188 "requires": [ 12189 "yql" 12190 ] 12191 }, 12192 "yql-winjs": { 12193 "condition": { 12194 "name": "yql-winjs", 12195 "trigger": "yql", 12196 "ua": "winjs" 12197 }, 12198 "requires": [ 12199 "yql" 12200 ] 12201 }, 12202 "yui": {}, 12203 "yui-base": {}, 12204 "yui-later": { 12205 "requires": [ 12206 "yui-base" 12207 ] 12208 }, 12209 "yui-log": { 12210 "requires": [ 12211 "yui-base" 12212 ] 12213 }, 12214 "yui-throttle": { 12215 "requires": [ 12216 "yui-base" 12217 ] 12218 } 12219 }); 12220 YUI.Env[Y.version].md5 = '45357bb11eddf7fd0a89c0b756599df2'; 12221 12222 12223 }, '3.17.2', {"requires": ["loader-base"]}); 12224 YUI.add('yui', function (Y, NAME) {}, '3.17.2', { 12225 "use": [ 12226 "yui-base", 12227 "get", 12228 "features", 12229 "intl-base", 12230 "yui-log", 12231 "yui-later", 12232 "loader-base", 12233 "loader-rollup", 12234 "loader-yui3" 12235 ] 12236 });
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 |