| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 /* 2 Copyright (c) 2008, Yahoo! Inc. All rights reserved. 3 Code licensed under the BSD License: 4 http://developer.yahoo.net/yui/license.txt 5 version: 2.6.0 6 */ 7 /** 8 * The YAHOO object is the single global object used by YUI Library. It 9 * contains utility function for setting up namespaces, inheritance, and 10 * logging. YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces 11 * created automatically for and used by the library. 12 * @module yahoo 13 * @title YAHOO Global 14 */ 15 16 /** 17 * YAHOO_config is not included as part of the library. Instead it is an 18 * object that can be defined by the implementer immediately before 19 * including the YUI library. The properties included in this object 20 * will be used to configure global properties needed as soon as the 21 * library begins to load. 22 * @class YAHOO_config 23 * @static 24 */ 25 26 /** 27 * A reference to a function that will be executed every time a YAHOO module 28 * is loaded. As parameter, this function will receive the version 29 * information for the module. See <a href="YAHOO.env.html#getVersion"> 30 * YAHOO.env.getVersion</a> for the description of the version data structure. 31 * @property listener 32 * @type Function 33 * @static 34 * @default undefined 35 */ 36 37 /** 38 * Set to true if the library will be dynamically loaded after window.onload. 39 * Defaults to false 40 * @property injecting 41 * @type boolean 42 * @static 43 * @default undefined 44 */ 45 46 /** 47 * Instructs the yuiloader component to dynamically load yui components and 48 * their dependencies. See the yuiloader documentation for more information 49 * about dynamic loading 50 * @property load 51 * @static 52 * @default undefined 53 * @see yuiloader 54 */ 55 56 /** 57 * Forces the use of the supplied locale where applicable in the library 58 * @property locale 59 * @type string 60 * @static 61 * @default undefined 62 */ 63 64 if (typeof YAHOO == "undefined" || !YAHOO) { 65 /** 66 * The YAHOO global namespace object. If YAHOO is already defined, the 67 * existing YAHOO object will not be overwritten so that defined 68 * namespaces are preserved. 69 * @class YAHOO 70 * @static 71 */ 72 var YAHOO = {}; 73 } 74 75 /** 76 * Returns the namespace specified and creates it if it doesn't exist 77 * <pre> 78 * YAHOO.namespace("property.package"); 79 * YAHOO.namespace("YAHOO.property.package"); 80 * </pre> 81 * Either of the above would create YAHOO.property, then 82 * YAHOO.property.package 83 * 84 * Be careful when naming packages. Reserved words may work in some browsers 85 * and not others. For instance, the following will fail in Safari: 86 * <pre> 87 * YAHOO.namespace("really.long.nested.namespace"); 88 * </pre> 89 * This fails because "long" is a future reserved word in ECMAScript 90 * 91 * @method namespace 92 * @static 93 * @param {String*} arguments 1-n namespaces to create 94 * @return {Object} A reference to the last namespace object created 95 */ 96 YAHOO.namespace = function() { 97 var a=arguments, o=null, i, j, d; 98 for (i=0; i<a.length; i=i+1) { 99 d=a[i].split("."); 100 o=YAHOO; 101 102 // YAHOO is implied, so it is ignored if it is included 103 for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) { 104 o[d[j]]=o[d[j]] || {}; 105 o=o[d[j]]; 106 } 107 } 108 109 return o; 110 }; 111 112 /** 113 * Uses YAHOO.widget.Logger to output a log message, if the widget is 114 * available. 115 * 116 * @method log 117 * @static 118 * @param {String} msg The message to log. 119 * @param {String} cat The log category for the message. Default 120 * categories are "info", "warn", "error", time". 121 * Custom categories can be used as well. (opt) 122 * @param {String} src The source of the the message (opt) 123 * @return {Boolean} True if the log operation was successful. 124 */ 125 YAHOO.log = function(msg, cat, src) { 126 var l=YAHOO.widget.Logger; 127 if(l && l.log) { 128 return l.log(msg, cat, src); 129 } else { 130 return false; 131 } 132 }; 133 134 /** 135 * Registers a module with the YAHOO object 136 * @method register 137 * @static 138 * @param {String} name the name of the module (event, slider, etc) 139 * @param {Function} mainClass a reference to class in the module. This 140 * class will be tagged with the version info 141 * so that it will be possible to identify the 142 * version that is in use when multiple versions 143 * have loaded 144 * @param {Object} data metadata object for the module. Currently it 145 * is expected to contain a "version" property 146 * and a "build" property at minimum. 147 */ 148 YAHOO.register = function(name, mainClass, data) { 149 var mods = YAHOO.env.modules; 150 if (!mods[name]) { 151 mods[name] = { versions:[], builds:[] }; 152 } 153 var m=mods[name],v=data.version,b=data.build,ls=YAHOO.env.listeners; 154 m.name = name; 155 m.version = v; 156 m.build = b; 157 m.versions.push(v); 158 m.builds.push(b); 159 m.mainClass = mainClass; 160 // fire the module load listeners 161 for (var i=0;i<ls.length;i=i+1) { 162 ls[i](m); 163 } 164 // label the main class 165 if (mainClass) { 166 mainClass.VERSION = v; 167 mainClass.BUILD = b; 168 } else { 169 YAHOO.log("mainClass is undefined for module " + name, "warn"); 170 } 171 }; 172 173 /** 174 * YAHOO.env is used to keep track of what is known about the YUI library and 175 * the browsing environment 176 * @class YAHOO.env 177 * @static 178 */ 179 YAHOO.env = YAHOO.env || { 180 181 /** 182 * Keeps the version info for all YUI modules that have reported themselves 183 * @property modules 184 * @type Object[] 185 */ 186 modules: [], 187 188 /** 189 * List of functions that should be executed every time a YUI module 190 * reports itself. 191 * @property listeners 192 * @type Function[] 193 */ 194 listeners: [] 195 }; 196 197 /** 198 * Returns the version data for the specified module: 199 * <dl> 200 * <dt>name:</dt> <dd>The name of the module</dd> 201 * <dt>version:</dt> <dd>The version in use</dd> 202 * <dt>build:</dt> <dd>The build number in use</dd> 203 * <dt>versions:</dt> <dd>All versions that were registered</dd> 204 * <dt>builds:</dt> <dd>All builds that were registered.</dd> 205 * <dt>mainClass:</dt> <dd>An object that was was stamped with the 206 * current version and build. If 207 * mainClass.VERSION != version or mainClass.BUILD != build, 208 * multiple versions of pieces of the library have been 209 * loaded, potentially causing issues.</dd> 210 * </dl> 211 * 212 * @method getVersion 213 * @static 214 * @param {String} name the name of the module (event, slider, etc) 215 * @return {Object} The version info 216 */ 217 YAHOO.env.getVersion = function(name) { 218 return YAHOO.env.modules[name] || null; 219 }; 220 221 /** 222 * Do not fork for a browser if it can be avoided. Use feature detection when 223 * you can. Use the user agent as a last resort. YAHOO.env.ua stores a version 224 * number for the browser engine, 0 otherwise. This value may or may not map 225 * to the version number of the browser using the engine. The value is 226 * presented as a float so that it can easily be used for boolean evaluation 227 * as well as for looking for a particular range of versions. Because of this, 228 * some of the granularity of the version info may be lost (e.g., Gecko 1.8.0.9 229 * reports 1.8). 230 * @class YAHOO.env.ua 231 * @static 232 */ 233 YAHOO.env.ua = function() { 234 var o={ 235 236 /** 237 * Internet Explorer version number or 0. Example: 6 238 * @property ie 239 * @type float 240 */ 241 ie:0, 242 243 /** 244 * Opera version number or 0. Example: 9.2 245 * @property opera 246 * @type float 247 */ 248 opera:0, 249 250 /** 251 * Gecko engine revision number. Will evaluate to 1 if Gecko 252 * is detected but the revision could not be found. Other browsers 253 * will be 0. Example: 1.8 254 * <pre> 255 * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7 256 * Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8 257 * Firefox 2.0.0.3: 1.8.1.3 <-- Reports 1.8 258 * Firefox 3 alpha: 1.9a4 <-- Reports 1.9 259 * </pre> 260 * @property gecko 261 * @type float 262 */ 263 gecko:0, 264 265 /** 266 * AppleWebKit version. KHTML browsers that are not WebKit browsers 267 * will evaluate to 1, other browsers 0. Example: 418.9.1 268 * <pre> 269 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the 270 * latest available for Mac OSX 10.3. 271 * Safari 2.0.2: 416 <-- hasOwnProperty introduced 272 * Safari 2.0.4: 418 <-- preventDefault fixed 273 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run 274 * different versions of webkit 275 * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been 276 * updated, but not updated 277 * to the latest patch. 278 * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native SVG 279 * and many major issues fixed). 280 * 3.x yahoo.com, flickr:422 <-- Safari 3.x hacks the user agent 281 * string when hitting yahoo.com and 282 * flickr.com. 283 * Safari 3.0.4 (523.12):523.12 <-- First Tiger release - automatic update 284 * from 2.x via the 10.4.11 OS patch 285 * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event. 286 * yahoo.com user agent hack removed. 287 * 288 * </pre> 289 * http://developer.apple.com/internet/safari/uamatrix.html 290 * @property webkit 291 * @type float 292 */ 293 webkit: 0, 294 295 /** 296 * The mobile property will be set to a string containing any relevant 297 * user agent information when a modern mobile browser is detected. 298 * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series 299 * devices with the WebKit-based browser, and Opera Mini. 300 * @property mobile 301 * @type string 302 */ 303 mobile: null, 304 305 /** 306 * Adobe AIR version number or 0. Only populated if webkit is detected. 307 * Example: 1.0 308 * @property air 309 * @type float 310 */ 311 air: 0 312 313 }; 314 315 var ua=navigator.userAgent, m; 316 317 // Modern KHTML browsers should qualify as Safari X-Grade 318 if ((/KHTML/).test(ua)) { 319 o.webkit=1; 320 } 321 // Modern WebKit browsers are at least X-Grade 322 m=ua.match(/AppleWebKit\/([^\s]*)/); 323 if (m&&m[1]) { 324 o.webkit=parseFloat(m[1]); 325 326 // Mobile browser check 327 if (/ Mobile\//.test(ua)) { 328 o.mobile = "Apple"; // iPhone or iPod Touch 329 } else { 330 m=ua.match(/NokiaN[^\/]*/); 331 if (m) { 332 o.mobile = m[0]; // Nokia N-series, ex: NokiaN95 333 } 334 } 335 336 m=ua.match(/AdobeAIR\/([^\s]*)/); 337 if (m) { 338 o.air = m[0]; // Adobe AIR 1.0 or better 339 } 340 341 } 342 343 if (!o.webkit) { // not webkit 344 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) 345 m=ua.match(/Opera[\s\/]([^\s]*)/); 346 if (m&&m[1]) { 347 o.opera=parseFloat(m[1]); 348 m=ua.match(/Opera Mini[^;]*/); 349 if (m) { 350 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 351 } 352 } else { // not opera or webkit 353 m=ua.match(/MSIE\s([^;]*)/); 354 if (m&&m[1]) { 355 o.ie=parseFloat(m[1]); 356 } else { // not opera, webkit, or ie 357 m=ua.match(/Gecko\/([^\s]*)/); 358 if (m) { 359 o.gecko=1; // Gecko detected, look for revision 360 m=ua.match(/rv:([^\s\)]*)/); 361 if (m&&m[1]) { 362 o.gecko=parseFloat(m[1]); 363 } 364 } 365 } 366 } 367 } 368 369 return o; 370 }(); 371 372 /* 373 * Initializes the global by creating the default namespaces and applying 374 * any new configuration information that is detected. This is the setup 375 * for env. 376 * @method init 377 * @static 378 * @private 379 */ 380 (function() { 381 YAHOO.namespace("util", "widget", "example"); 382 if ("undefined" !== typeof YAHOO_config) { 383 var l=YAHOO_config.listener,ls=YAHOO.env.listeners,unique=true,i; 384 if (l) { 385 // if YAHOO is loaded multiple times we need to check to see if 386 // this is a new config object. If it is, add the new component 387 // load listener to the stack 388 for (i=0;i<ls.length;i=i+1) { 389 if (ls[i]==l) { 390 unique=false; 391 break; 392 } 393 } 394 if (unique) { 395 ls.push(l); 396 } 397 } 398 } 399 })(); 400 /** 401 * Provides the language utilites and extensions used by the library 402 * @class YAHOO.lang 403 */ 404 YAHOO.lang = YAHOO.lang || {}; 405 406 (function() { 407 408 var L = YAHOO.lang, 409 410 // ADD = ["toString", "valueOf", "hasOwnProperty"], 411 ADD = ["toString", "valueOf"], 412 413 OB = { 414 415 /** 416 * Determines whether or not the provided object is an array. 417 * Testing typeof/instanceof/constructor of arrays across frame 418 * boundaries isn't possible in Safari unless you have a reference 419 * to the other frame to test against its Array prototype. To 420 * handle this case, we test well-known array properties instead. 421 * properties. 422 * @method isArray 423 * @param {any} o The object being testing 424 * @return {boolean} the result 425 */ 426 isArray: function(o) { 427 if (o) { 428 return L.isNumber(o.length) && L.isFunction(o.splice); 429 } 430 return false; 431 }, 432 433 /** 434 * Determines whether or not the provided object is a boolean 435 * @method isBoolean 436 * @param {any} o The object being testing 437 * @return {boolean} the result 438 */ 439 isBoolean: function(o) { 440 return typeof o === 'boolean'; 441 }, 442 443 /** 444 * Determines whether or not the provided object is a function 445 * @method isFunction 446 * @param {any} o The object being testing 447 * @return {boolean} the result 448 */ 449 isFunction: function(o) { 450 return typeof o === 'function'; 451 }, 452 453 /** 454 * Determines whether or not the provided object is null 455 * @method isNull 456 * @param {any} o The object being testing 457 * @return {boolean} the result 458 */ 459 isNull: function(o) { 460 return o === null; 461 }, 462 463 /** 464 * Determines whether or not the provided object is a legal number 465 * @method isNumber 466 * @param {any} o The object being testing 467 * @return {boolean} the result 468 */ 469 isNumber: function(o) { 470 return typeof o === 'number' && isFinite(o); 471 }, 472 473 /** 474 * Determines whether or not the provided object is of type object 475 * or function 476 * @method isObject 477 * @param {any} o The object being testing 478 * @return {boolean} the result 479 */ 480 isObject: function(o) { 481 return (o && (typeof o === 'object' || L.isFunction(o))) || false; 482 }, 483 484 /** 485 * Determines whether or not the provided object is a string 486 * @method isString 487 * @param {any} o The object being testing 488 * @return {boolean} the result 489 */ 490 isString: function(o) { 491 return typeof o === 'string'; 492 }, 493 494 /** 495 * Determines whether or not the provided object is undefined 496 * @method isUndefined 497 * @param {any} o The object being testing 498 * @return {boolean} the result 499 */ 500 isUndefined: function(o) { 501 return typeof o === 'undefined'; 502 }, 503 504 505 /** 506 * IE will not enumerate native functions in a derived object even if the 507 * function was overridden. This is a workaround for specific functions 508 * we care about on the Object prototype. 509 * @property _IEEnumFix 510 * @param {Function} r the object to receive the augmentation 511 * @param {Function} s the object that supplies the properties to augment 512 * @static 513 * @private 514 */ 515 _IEEnumFix: (YAHOO.env.ua.ie) ? function(r, s) { 516 for (var i=0;i<ADD.length;i=i+1) { 517 var fname=ADD[i],f=s[fname]; 518 if (L.isFunction(f) && f!=Object.prototype[fname]) { 519 r[fname]=f; 520 } 521 } 522 } : function(){}, 523 524 /** 525 * Utility to set up the prototype, constructor and superclass properties to 526 * support an inheritance strategy that can chain constructors and methods. 527 * Static members will not be inherited. 528 * 529 * @method extend 530 * @static 531 * @param {Function} subc the object to modify 532 * @param {Function} superc the object to inherit 533 * @param {Object} overrides additional properties/methods to add to the 534 * subclass prototype. These will override the 535 * matching items obtained from the superclass 536 * if present. 537 */ 538 extend: function(subc, superc, overrides) { 539 if (!superc||!subc) { 540 throw new Error("extend failed, please check that " + 541 "all dependencies are included."); 542 } 543 var F = function() {}; 544 F.prototype=superc.prototype; 545 subc.prototype=new F(); 546 subc.prototype.constructor=subc; 547 subc.superclass=superc.prototype; 548 if (superc.prototype.constructor == Object.prototype.constructor) { 549 superc.prototype.constructor=superc; 550 } 551 552 if (overrides) { 553 for (var i in overrides) { 554 if (L.hasOwnProperty(overrides, i)) { 555 subc.prototype[i]=overrides[i]; 556 } 557 } 558 559 L._IEEnumFix(subc.prototype, overrides); 560 } 561 }, 562 563 /** 564 * Applies all properties in the supplier to the receiver if the 565 * receiver does not have these properties yet. Optionally, one or 566 * more methods/properties can be specified (as additional 567 * parameters). This option will overwrite the property if receiver 568 * has it already. If true is passed as the third parameter, all 569 * properties will be applied and _will_ overwrite properties in 570 * the receiver. 571 * 572 * @method augmentObject 573 * @static 574 * @since 2.3.0 575 * @param {Function} r the object to receive the augmentation 576 * @param {Function} s the object that supplies the properties to augment 577 * @param {String*|boolean} arguments zero or more properties methods 578 * to augment the receiver with. If none specified, everything 579 * in the supplier will be used unless it would 580 * overwrite an existing property in the receiver. If true 581 * is specified as the third parameter, all properties will 582 * be applied and will overwrite an existing property in 583 * the receiver 584 */ 585 augmentObject: function(r, s) { 586 if (!s||!r) { 587 throw new Error("Absorb failed, verify dependencies."); 588 } 589 var a=arguments, i, p, override=a[2]; 590 if (override && override!==true) { // only absorb the specified properties 591 for (i=2; i<a.length; i=i+1) { 592 r[a[i]] = s[a[i]]; 593 } 594 } else { // take everything, overwriting only if the third parameter is true 595 for (p in s) { 596 if (override || !(p in r)) { 597 r[p] = s[p]; 598 } 599 } 600 601 L._IEEnumFix(r, s); 602 } 603 }, 604 605 /** 606 * Same as YAHOO.lang.augmentObject, except it only applies prototype properties 607 * @see YAHOO.lang.augmentObject 608 * @method augmentProto 609 * @static 610 * @param {Function} r the object to receive the augmentation 611 * @param {Function} s the object that supplies the properties to augment 612 * @param {String*|boolean} arguments zero or more properties methods 613 * to augment the receiver with. If none specified, everything 614 * in the supplier will be used unless it would overwrite an existing 615 * property in the receiver. if true is specified as the third 616 * parameter, all properties will be applied and will overwrite an 617 * existing property in the receiver 618 */ 619 augmentProto: function(r, s) { 620 if (!s||!r) { 621 throw new Error("Augment failed, verify dependencies."); 622 } 623 //var a=[].concat(arguments); 624 var a=[r.prototype,s.prototype]; 625 for (var i=2;i<arguments.length;i=i+1) { 626 a.push(arguments[i]); 627 } 628 L.augmentObject.apply(this, a); 629 }, 630 631 632 /** 633 * Returns a simple string representation of the object or array. 634 * Other types of objects will be returned unprocessed. Arrays 635 * are expected to be indexed. Use object notation for 636 * associative arrays. 637 * @method dump 638 * @since 2.3.0 639 * @param o {Object} The object to dump 640 * @param d {int} How deep to recurse child objects, default 3 641 * @return {String} the dump result 642 */ 643 dump: function(o, d) { 644 var i,len,s=[],OBJ="{...}",FUN="f(){...}", 645 COMMA=', ', ARROW=' => '; 646 647 // Cast non-objects to string 648 // Skip dates because the std toString is what we want 649 // Skip HTMLElement-like objects because trying to dump 650 // an element will cause an unhandled exception in FF 2.x 651 if (!L.isObject(o)) { 652 return o + ""; 653 } else if (o instanceof Date || ("nodeType" in o && "tagName" in o)) { 654 return o; 655 } else if (L.isFunction(o)) { 656 return FUN; 657 } 658 659 // dig into child objects the depth specifed. Default 3 660 d = (L.isNumber(d)) ? d : 3; 661 662 // arrays [1, 2, 3] 663 if (L.isArray(o)) { 664 s.push("["); 665 for (i=0,len=o.length;i<len;i=i+1) { 666 if (L.isObject(o[i])) { 667 s.push((d > 0) ? L.dump(o[i], d-1) : OBJ); 668 } else { 669 s.push(o[i]); 670 } 671 s.push(COMMA); 672 } 673 if (s.length > 1) { 674 s.pop(); 675 } 676 s.push("]"); 677 // objects {k1 => v1, k2 => v2} 678 } else { 679 s.push("{"); 680 for (i in o) { 681 if (L.hasOwnProperty(o, i)) { 682 s.push(i + ARROW); 683 if (L.isObject(o[i])) { 684 s.push((d > 0) ? L.dump(o[i], d-1) : OBJ); 685 } else { 686 s.push(o[i]); 687 } 688 s.push(COMMA); 689 } 690 } 691 if (s.length > 1) { 692 s.pop(); 693 } 694 s.push("}"); 695 } 696 697 return s.join(""); 698 }, 699 700 /** 701 * Does variable substitution on a string. It scans through the string 702 * looking for expressions enclosed in { } braces. If an expression 703 * is found, it is used a key on the object. If there is a space in 704 * the key, the first word is used for the key and the rest is provided 705 * to an optional function to be used to programatically determine the 706 * value (the extra information might be used for this decision). If 707 * the value for the key in the object, or what is returned from the 708 * function has a string value, number value, or object value, it is 709 * substituted for the bracket expression and it repeats. If this 710 * value is an object, it uses the Object's toString() if this has 711 * been overridden, otherwise it does a shallow dump of the key/value 712 * pairs. 713 * @method substitute 714 * @since 2.3.0 715 * @param s {String} The string that will be modified. 716 * @param o {Object} An object containing the replacement values 717 * @param f {Function} An optional function that can be used to 718 * process each match. It receives the key, 719 * value, and any extra metadata included with 720 * the key inside of the braces. 721 * @return {String} the substituted string 722 */ 723 substitute: function (s, o, f) { 724 var i, j, k, key, v, meta, saved=[], token, 725 DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}'; 726 727 728 for (;;) { 729 i = s.lastIndexOf(LBRACE); 730 if (i < 0) { 731 break; 732 } 733 j = s.indexOf(RBRACE, i); 734 if (i + 1 >= j) { 735 break; 736 } 737 738 //Extract key and meta info 739 token = s.substring(i + 1, j); 740 key = token; 741 meta = null; 742 k = key.indexOf(SPACE); 743 if (k > -1) { 744 meta = key.substring(k + 1); 745 key = key.substring(0, k); 746 } 747 748 // lookup the value 749 v = o[key]; 750 751 // if a substitution function was provided, execute it 752 if (f) { 753 v = f(key, v, meta); 754 } 755 756 if (L.isObject(v)) { 757 if (L.isArray(v)) { 758 v = L.dump(v, parseInt(meta, 10)); 759 } else { 760 meta = meta || ""; 761 762 // look for the keyword 'dump', if found force obj dump 763 var dump = meta.indexOf(DUMP); 764 if (dump > -1) { 765 meta = meta.substring(4); 766 } 767 768 // use the toString if it is not the Object toString 769 // and the 'dump' meta info was not found 770 if (v.toString===Object.prototype.toString||dump>-1) { 771 v = L.dump(v, parseInt(meta, 10)); 772 } else { 773 v = v.toString(); 774 } 775 } 776 } else if (!L.isString(v) && !L.isNumber(v)) { 777 // This {block} has no replace string. Save it for later. 778 v = "~-" + saved.length + "-~"; 779 saved[saved.length] = token; 780 781 // break; 782 } 783 784 s = s.substring(0, i) + v + s.substring(j + 1); 785 786 787 } 788 789 // restore saved {block}s 790 for (i=saved.length-1; i>=0; i=i-1) { 791 s = s.replace(new RegExp("~-" + i + "-~"), "{" + saved[i] + "}", "g"); 792 } 793 794 return s; 795 }, 796 797 798 /** 799 * Returns a string without any leading or trailing whitespace. If 800 * the input is not a string, the input will be returned untouched. 801 * @method trim 802 * @since 2.3.0 803 * @param s {string} the string to trim 804 * @return {string} the trimmed string 805 */ 806 trim: function(s){ 807 try { 808 return s.replace(/^\s+|\s+$/g, ""); 809 } catch(e) { 810 return s; 811 } 812 }, 813 814 /** 815 * Returns a new object containing all of the properties of 816 * all the supplied objects. The properties from later objects 817 * will overwrite those in earlier objects. 818 * @method merge 819 * @since 2.3.0 820 * @param arguments {Object*} the objects to merge 821 * @return the new merged object 822 */ 823 merge: function() { 824 var o={}, a=arguments; 825 for (var i=0, l=a.length; i<l; i=i+1) { 826 L.augmentObject(o, a[i], true); 827 } 828 return o; 829 }, 830 831 /** 832 * Executes the supplied function in the context of the supplied 833 * object 'when' milliseconds later. Executes the function a 834 * single time unless periodic is set to true. 835 * @method later 836 * @since 2.4.0 837 * @param when {int} the number of milliseconds to wait until the fn 838 * is executed 839 * @param o the context object 840 * @param fn {Function|String} the function to execute or the name of 841 * the method in the 'o' object to execute 842 * @param data [Array] data that is provided to the function. This accepts 843 * either a single item or an array. If an array is provided, the 844 * function is executed with one parameter for each array item. If 845 * you need to pass a single array parameter, it needs to be wrapped in 846 * an array [myarray] 847 * @param periodic {boolean} if true, executes continuously at supplied 848 * interval until canceled 849 * @return a timer object. Call the cancel() method on this object to 850 * stop the timer. 851 */ 852 later: function(when, o, fn, data, periodic) { 853 when = when || 0; 854 o = o || {}; 855 var m=fn, d=data, f, r; 856 857 if (L.isString(fn)) { 858 m = o[fn]; 859 } 860 861 if (!m) { 862 throw new TypeError("method undefined"); 863 } 864 865 if (!L.isArray(d)) { 866 d = [data]; 867 } 868 869 f = function() { 870 m.apply(o, d); 871 }; 872 873 r = (periodic) ? setInterval(f, when) : setTimeout(f, when); 874 875 return { 876 interval: periodic, 877 cancel: function() { 878 if (this.interval) { 879 clearInterval(r); 880 } else { 881 clearTimeout(r); 882 } 883 } 884 }; 885 }, 886 887 /** 888 * A convenience method for detecting a legitimate non-null value. 889 * Returns false for null/undefined/NaN, true for other values, 890 * including 0/false/'' 891 * @method isValue 892 * @since 2.3.0 893 * @param o {any} the item to test 894 * @return {boolean} true if it is not null/undefined/NaN || false 895 */ 896 isValue: function(o) { 897 // return (o || o === false || o === 0 || o === ''); // Infinity fails 898 return (L.isObject(o) || L.isString(o) || L.isNumber(o) || L.isBoolean(o)); 899 } 900 901 }; 902 903 /** 904 * Determines whether or not the property was added 905 * to the object instance. Returns false if the property is not present 906 * in the object, or was inherited from the prototype. 907 * This abstraction is provided to enable hasOwnProperty for Safari 1.3.x. 908 * There is a discrepancy between YAHOO.lang.hasOwnProperty and 909 * Object.prototype.hasOwnProperty when the property is a primitive added to 910 * both the instance AND prototype with the same value: 911 * <pre> 912 * var A = function() {}; 913 * A.prototype.foo = 'foo'; 914 * var a = new A(); 915 * a.foo = 'foo'; 916 * alert(a.hasOwnProperty('foo')); // true 917 * alert(YAHOO.lang.hasOwnProperty(a, 'foo')); // false when using fallback 918 * </pre> 919 * @method hasOwnProperty 920 * @param {any} o The object being testing 921 * @param prop {string} the name of the property to test 922 * @return {boolean} the result 923 */ 924 L.hasOwnProperty = (Object.prototype.hasOwnProperty) ? 925 function(o, prop) { 926 return o && o.hasOwnProperty(prop); 927 } : function(o, prop) { 928 return !L.isUndefined(o[prop]) && 929 o.constructor.prototype[prop] !== o[prop]; 930 }; 931 932 // new lang wins 933 OB.augmentObject(L, OB, true); 934 935 /* 936 * An alias for <a href="YAHOO.lang.html">YAHOO.lang</a> 937 * @class YAHOO.util.Lang 938 */ 939 YAHOO.util.Lang = L; 940 941 /** 942 * Same as YAHOO.lang.augmentObject, except it only applies prototype 943 * properties. This is an alias for augmentProto. 944 * @see YAHOO.lang.augmentObject 945 * @method augment 946 * @static 947 * @param {Function} r the object to receive the augmentation 948 * @param {Function} s the object that supplies the properties to augment 949 * @param {String*|boolean} arguments zero or more properties methods to 950 * augment the receiver with. If none specified, everything 951 * in the supplier will be used unless it would 952 * overwrite an existing property in the receiver. if true 953 * is specified as the third parameter, all properties will 954 * be applied and will overwrite an existing property in 955 * the receiver 956 */ 957 L.augment = L.augmentProto; 958 959 /** 960 * An alias for <a href="YAHOO.lang.html#augment">YAHOO.lang.augment</a> 961 * @for YAHOO 962 * @method augment 963 * @static 964 * @param {Function} r the object to receive the augmentation 965 * @param {Function} s the object that supplies the properties to augment 966 * @param {String*} arguments zero or more properties methods to 967 * augment the receiver with. If none specified, everything 968 * in the supplier will be used unless it would 969 * overwrite an existing property in the receiver 970 */ 971 YAHOO.augment = L.augmentProto; 972 973 /** 974 * An alias for <a href="YAHOO.lang.html#extend">YAHOO.lang.extend</a> 975 * @method extend 976 * @static 977 * @param {Function} subc the object to modify 978 * @param {Function} superc the object to inherit 979 * @param {Object} overrides additional properties/methods to add to the 980 * subclass prototype. These will override the 981 * matching items obtained from the superclass if present. 982 */ 983 YAHOO.extend = L.extend; 984 985 })(); 986 YAHOO.register("yahoo", YAHOO, {version: "2.6.0", build: "1321"}); 987 /** 988 * Provides a mechanism to fetch remote resources and 989 * insert them into a document 990 * @module get 991 * @requires yahoo 992 */ 993 994 /** 995 * Fetches and inserts one or more script or link nodes into the document 996 * @namespace YAHOO.util 997 * @class YAHOO.util.Get 998 */ 999 YAHOO.util.Get = function() { 1000 1001 /** 1002 * hash of queues to manage multiple requests 1003 * @property queues 1004 * @private 1005 */ 1006 var queues={}, 1007 1008 /** 1009 * queue index used to generate transaction ids 1010 * @property qidx 1011 * @type int 1012 * @private 1013 */ 1014 qidx=0, 1015 1016 /** 1017 * node index used to generate unique node ids 1018 * @property nidx 1019 * @type int 1020 * @private 1021 */ 1022 nidx=0, 1023 1024 // ridx=0, 1025 1026 // sandboxFrame=null, 1027 1028 /** 1029 * interal property used to prevent multiple simultaneous purge 1030 * processes 1031 * @property purging 1032 * @type boolean 1033 * @private 1034 */ 1035 purging=false, 1036 1037 ua=YAHOO.env.ua, 1038 1039 lang=YAHOO.lang; 1040 1041 /** 1042 * Generates an HTML element, this is not appended to a document 1043 * @method _node 1044 * @param type {string} the type of element 1045 * @param attr {string} the attributes 1046 * @param win {Window} optional window to create the element in 1047 * @return {HTMLElement} the generated node 1048 * @private 1049 */ 1050 var _node = function(type, attr, win) { 1051 var w = win || window, d=w.document, n=d.createElement(type); 1052 1053 for (var i in attr) { 1054 if (attr[i] && YAHOO.lang.hasOwnProperty(attr, i)) { 1055 n.setAttribute(i, attr[i]); 1056 } 1057 } 1058 1059 return n; 1060 }; 1061 1062 /** 1063 * Generates a link node 1064 * @method _linkNode 1065 * @param url {string} the url for the css file 1066 * @param win {Window} optional window to create the node in 1067 * @return {HTMLElement} the generated node 1068 * @private 1069 */ 1070 var _linkNode = function(url, win, charset) { 1071 var c = charset || "utf-8"; 1072 return _node("link", { 1073 "id": "yui__dyn_" + (nidx++), 1074 "type": "text/css", 1075 "charset": c, 1076 "rel": "stylesheet", 1077 "href": url 1078 }, win); 1079 }; 1080 1081 /** 1082 * Generates a script node 1083 * @method _scriptNode 1084 * @param url {string} the url for the script file 1085 * @param win {Window} optional window to create the node in 1086 * @return {HTMLElement} the generated node 1087 * @private 1088 */ 1089 var _scriptNode = function(url, win, charset) { 1090 var c = charset || "utf-8"; 1091 return _node("script", { 1092 "id": "yui__dyn_" + (nidx++), 1093 "type": "text/javascript", 1094 "charset": c, 1095 "src": url 1096 }, win); 1097 }; 1098 1099 /** 1100 * Returns the data payload for callback functions 1101 * @method _returnData 1102 * @private 1103 */ 1104 var _returnData = function(q, msg) { 1105 return { 1106 tId: q.tId, 1107 win: q.win, 1108 data: q.data, 1109 nodes: q.nodes, 1110 msg: msg, 1111 purge: function() { 1112 _purge(this.tId); 1113 } 1114 }; 1115 }; 1116 1117 var _get = function(nId, tId) { 1118 var q = queues[tId], 1119 n = (lang.isString(nId)) ? q.win.document.getElementById(nId) : nId; 1120 if (!n) { 1121 _fail(tId, "target node not found: " + nId); 1122 } 1123 1124 return n; 1125 }; 1126 1127 /* 1128 * The request failed, execute fail handler with whatever 1129 * was accomplished. There isn't a failure case at the 1130 * moment unless you count aborted transactions 1131 * @method _fail 1132 * @param id {string} the id of the request 1133 * @private 1134 */ 1135 var _fail = function(id, msg) { 1136 var q = queues[id]; 1137 // execute failure callback 1138 if (q.onFailure) { 1139 var sc=q.scope || q.win; 1140 q.onFailure.call(sc, _returnData(q, msg)); 1141 } 1142 }; 1143 1144 /** 1145 * The request is complete, so executing the requester's callback 1146 * @method _finish 1147 * @param id {string} the id of the request 1148 * @private 1149 */ 1150 var _finish = function(id) { 1151 var q = queues[id]; 1152 q.finished = true; 1153 1154 if (q.aborted) { 1155 var msg = "transaction " + id + " was aborted"; 1156 _fail(id, msg); 1157 return; 1158 } 1159 1160 // execute success callback 1161 if (q.onSuccess) { 1162 var sc=q.scope || q.win; 1163 q.onSuccess.call(sc, _returnData(q)); 1164 } 1165 }; 1166 1167 /** 1168 * Timeout detected 1169 * @method _timeout 1170 * @param id {string} the id of the request 1171 * @private 1172 */ 1173 var _timeout = function(id) { 1174 var q = queues[id]; 1175 if (q.onTimeout) { 1176 var sc=q.context || q; 1177 q.onTimeout.call(sc, _returnData(q)); 1178 } 1179 }; 1180 1181 /** 1182 * Loads the next item for a given request 1183 * @method _next 1184 * @param id {string} the id of the request 1185 * @param loaded {string} the url that was just loaded, if any 1186 * @private 1187 */ 1188 var _next = function(id, loaded) { 1189 var q = queues[id]; 1190 1191 if (q.timer) { 1192 // Y.log('cancel timer'); 1193 q.timer.cancel(); 1194 } 1195 1196 if (q.aborted) { 1197 var msg = "transaction " + id + " was aborted"; 1198 _fail(id, msg); 1199 return; 1200 } 1201 1202 if (loaded) { 1203 q.url.shift(); 1204 if (q.varName) { 1205 q.varName.shift(); 1206 } 1207 } else { 1208 // This is the first pass: make sure the url is an array 1209 q.url = (lang.isString(q.url)) ? [q.url] : q.url; 1210 if (q.varName) { 1211 q.varName = (lang.isString(q.varName)) ? [q.varName] : q.varName; 1212 } 1213 } 1214 1215 var w=q.win, d=w.document, h=d.getElementsByTagName("head")[0], n; 1216 1217 if (q.url.length === 0) { 1218 // Safari 2.x workaround - There is no way to know when 1219 // a script is ready in versions of Safari prior to 3.x. 1220 // Adding an extra node reduces the problem, but doesn't 1221 // eliminate it completely because the browser executes 1222 // them asynchronously. 1223 if (q.type === "script" && ua.webkit && ua.webkit < 420 && 1224 !q.finalpass && !q.varName) { 1225 // Add another script node. This does not guarantee that the 1226 // scripts will execute in order, but it does appear to fix the 1227 // problem on fast connections more effectively than using an 1228 // arbitrary timeout. It is possible that the browser does 1229 // block subsequent script execution in this case for a limited 1230 // time. 1231 var extra = _scriptNode(null, q.win, q.charset); 1232 extra.innerHTML='YAHOO.util.Get._finalize("' + id + '");'; 1233 q.nodes.push(extra); h.appendChild(extra); 1234 1235 } else { 1236 _finish(id); 1237 } 1238 1239 return; 1240 } 1241 1242 1243 var url = q.url[0]; 1244 1245 // if the url is undefined, this is probably a trailing comma problem in IE 1246 if (!url) { 1247 q.url.shift(); 1248 return _next(id); 1249 } 1250 1251 1252 if (q.timeout) { 1253 // Y.log('create timer'); 1254 q.timer = lang.later(q.timeout, q, _timeout, id); 1255 } 1256 1257 if (q.type === "script") { 1258 n = _scriptNode(url, w, q.charset); 1259 } else { 1260 n = _linkNode(url, w, q.charset); 1261 } 1262 1263 // track this node's load progress 1264 _track(q.type, n, id, url, w, q.url.length); 1265 1266 // add the node to the queue so we can return it to the user supplied callback 1267 q.nodes.push(n); 1268 1269 // add it to the head or insert it before 'insertBefore' 1270 if (q.insertBefore) { 1271 var s = _get(q.insertBefore, id); 1272 if (s) { 1273 s.parentNode.insertBefore(n, s); 1274 } 1275 } else { 1276 h.appendChild(n); 1277 } 1278 1279 1280 // FireFox does not support the onload event for link nodes, so there is 1281 // no way to make the css requests synchronous. This means that the css 1282 // rules in multiple files could be applied out of order in this browser 1283 // if a later request returns before an earlier one. Safari too. 1284 if ((ua.webkit || ua.gecko) && q.type === "css") { 1285 _next(id, url); 1286 } 1287 }; 1288 1289 /** 1290 * Removes processed queues and corresponding nodes 1291 * @method _autoPurge 1292 * @private 1293 */ 1294 var _autoPurge = function() { 1295 1296 if (purging) { 1297 return; 1298 } 1299 1300 purging = true; 1301 for (var i in queues) { 1302 var q = queues[i]; 1303 if (q.autopurge && q.finished) { 1304 _purge(q.tId); 1305 delete queues[i]; 1306 } 1307 } 1308 1309 purging = false; 1310 }; 1311 1312 /** 1313 * Removes the nodes for the specified queue 1314 * @method _purge 1315 * @private 1316 */ 1317 var _purge = function(tId) { 1318 var q=queues[tId]; 1319 if (q) { 1320 var n=q.nodes, l=n.length, d=q.win.document, 1321 h=d.getElementsByTagName("head")[0]; 1322 1323 if (q.insertBefore) { 1324 var s = _get(q.insertBefore, tId); 1325 if (s) { 1326 h = s.parentNode; 1327 } 1328 } 1329 1330 for (var i=0; i<l; i=i+1) { 1331 h.removeChild(n[i]); 1332 } 1333 1334 q.nodes = []; 1335 } 1336 }; 1337 1338 /** 1339 * Saves the state for the request and begins loading 1340 * the requested urls 1341 * @method queue 1342 * @param type {string} the type of node to insert 1343 * @param url {string} the url to load 1344 * @param opts the hash of options for this request 1345 * @private 1346 */ 1347 var _queue = function(type, url, opts) { 1348 1349 var id = "q" + (qidx++); 1350 opts = opts || {}; 1351 1352 if (qidx % YAHOO.util.Get.PURGE_THRESH === 0) { 1353 _autoPurge(); 1354 } 1355 1356 queues[id] = lang.merge(opts, { 1357 tId: id, 1358 type: type, 1359 url: url, 1360 finished: false, 1361 aborted: false, 1362 nodes: [] 1363 }); 1364 1365 var q = queues[id]; 1366 q.win = q.win || window; 1367 q.scope = q.scope || q.win; 1368 q.autopurge = ("autopurge" in q) ? q.autopurge : 1369 (type === "script") ? true : false; 1370 1371 lang.later(0, q, _next, id); 1372 1373 return { 1374 tId: id 1375 }; 1376 }; 1377 1378 /** 1379 * Detects when a node has been loaded. In the case of 1380 * script nodes, this does not guarantee that contained 1381 * script is ready to use. 1382 * @method _track 1383 * @param type {string} the type of node to track 1384 * @param n {HTMLElement} the node to track 1385 * @param id {string} the id of the request 1386 * @param url {string} the url that is being loaded 1387 * @param win {Window} the targeted window 1388 * @param qlength the number of remaining items in the queue, 1389 * including this one 1390 * @param trackfn {Function} function to execute when finished 1391 * the default is _next 1392 * @private 1393 */ 1394 var _track = function(type, n, id, url, win, qlength, trackfn) { 1395 var f = trackfn || _next; 1396 1397 // IE supports the readystatechange event for script and css nodes 1398 if (ua.ie) { 1399 n.onreadystatechange = function() { 1400 var rs = this.readyState; 1401 if ("loaded" === rs || "complete" === rs) { 1402 n.onreadystatechange = null; 1403 f(id, url); 1404 } 1405 }; 1406 1407 // webkit prior to 3.x is problemmatic 1408 } else if (ua.webkit) { 1409 1410 if (type === "script") { 1411 1412 // Safari 3.x supports the load event for script nodes (DOM2) 1413 if (ua.webkit >= 420) { 1414 1415 n.addEventListener("load", function() { 1416 f(id, url); 1417 }); 1418 1419 // Nothing can be done with Safari < 3.x except to pause and hope 1420 // for the best, particularly after last script is inserted. The 1421 // scripts will always execute in the order they arrive, not 1422 // necessarily the order in which they were inserted. To support 1423 // script nodes with complete reliability in these browsers, script 1424 // nodes either need to invoke a function in the window once they 1425 // are loaded or the implementer needs to provide a well-known 1426 // property that the utility can poll for. 1427 } else { 1428 // Poll for the existence of the named variable, if it 1429 // was supplied. 1430 var q = queues[id]; 1431 if (q.varName) { 1432 var freq=YAHOO.util.Get.POLL_FREQ; 1433 q.maxattempts = YAHOO.util.Get.TIMEOUT/freq; 1434 q.attempts = 0; 1435 q._cache = q.varName[0].split("."); 1436 q.timer = lang.later(freq, q, function(o) { 1437 var a=this._cache, l=a.length, w=this.win, i; 1438 for (i=0; i<l; i=i+1) { 1439 w = w[a[i]]; 1440 if (!w) { 1441 // if we have exausted our attempts, give up 1442 this.attempts++; 1443 if (this.attempts++ > this.maxattempts) { 1444 var msg = "Over retry limit, giving up"; 1445 q.timer.cancel(); 1446 _fail(id, msg); 1447 } else { 1448 } 1449 return; 1450 } 1451 } 1452 1453 1454 q.timer.cancel(); 1455 f(id, url); 1456 1457 }, null, true); 1458 } else { 1459 lang.later(YAHOO.util.Get.POLL_FREQ, null, f, [id, url]); 1460 } 1461 } 1462 } 1463 1464 // FireFox and Opera support onload (but not DOM2 in FF) handlers for 1465 // script nodes. Opera, but not FF, supports the onload event for link 1466 // nodes. 1467 } else { 1468 n.onload = function() { 1469 f(id, url); 1470 }; 1471 } 1472 }; 1473 1474 return { 1475 1476 /** 1477 * The default poll freqency in ms, when needed 1478 * @property POLL_FREQ 1479 * @static 1480 * @type int 1481 * @default 10 1482 */ 1483 POLL_FREQ: 10, 1484 1485 /** 1486 * The number of request required before an automatic purge. 1487 * property PURGE_THRESH 1488 * @static 1489 * @type int 1490 * @default 20 1491 */ 1492 PURGE_THRESH: 20, 1493 1494 /** 1495 * The length time to poll for varName when loading a script in 1496 * Safari 2.x before the transaction fails. 1497 * property TIMEOUT 1498 * @static 1499 * @type int 1500 * @default 2000 1501 */ 1502 TIMEOUT: 2000, 1503 1504 /** 1505 * Called by the the helper for detecting script load in Safari 1506 * @method _finalize 1507 * @param id {string} the transaction id 1508 * @private 1509 */ 1510 _finalize: function(id) { 1511 lang.later(0, null, _finish, id); 1512 }, 1513 1514 /** 1515 * Abort a transaction 1516 * @method abort 1517 * @param {string|object} either the tId or the object returned from 1518 * script() or css() 1519 */ 1520 abort: function(o) { 1521 var id = (lang.isString(o)) ? o : o.tId; 1522 var q = queues[id]; 1523 if (q) { 1524 q.aborted = true; 1525 } 1526 }, 1527 1528 /** 1529 * Fetches and inserts one or more script nodes into the head 1530 * of the current document or the document in a specified window. 1531 * 1532 * @method script 1533 * @static 1534 * @param url {string|string[]} the url or urls to the script(s) 1535 * @param opts {object} Options: 1536 * <dl> 1537 * <dt>onSuccess</dt> 1538 * <dd> 1539 * callback to execute when the script(s) are finished loading 1540 * The callback receives an object back with the following 1541 * data: 1542 * <dl> 1543 * <dt>win</dt> 1544 * <dd>the window the script(s) were inserted into</dd> 1545 * <dt>data</dt> 1546 * <dd>the data object passed in when the request was made</dd> 1547 * <dt>nodes</dt> 1548 * <dd>An array containing references to the nodes that were 1549 * inserted</dd> 1550 * <dt>purge</dt> 1551 * <dd>A function that, when executed, will remove the nodes 1552 * that were inserted</dd> 1553 * <dt> 1554 * </dl> 1555 * </dd> 1556 * <dt>onFailure</dt> 1557 * <dd> 1558 * callback to execute when the script load operation fails 1559 * The callback receives an object back with the following 1560 * data: 1561 * <dl> 1562 * <dt>win</dt> 1563 * <dd>the window the script(s) were inserted into</dd> 1564 * <dt>data</dt> 1565 * <dd>the data object passed in when the request was made</dd> 1566 * <dt>nodes</dt> 1567 * <dd>An array containing references to the nodes that were 1568 * inserted successfully</dd> 1569 * <dt>purge</dt> 1570 * <dd>A function that, when executed, will remove any nodes 1571 * that were inserted</dd> 1572 * <dt> 1573 * </dl> 1574 * </dd> 1575 * <dt>onTimeout</dt> 1576 * <dd> 1577 * callback to execute when a timeout occurs. 1578 * The callback receives an object back with the following 1579 * data: 1580 * <dl> 1581 * <dt>win</dt> 1582 * <dd>the window the script(s) were inserted into</dd> 1583 * <dt>data</dt> 1584 * <dd>the data object passed in when the request was made</dd> 1585 * <dt>nodes</dt> 1586 * <dd>An array containing references to the nodes that were 1587 * inserted</dd> 1588 * <dt>purge</dt> 1589 * <dd>A function that, when executed, will remove the nodes 1590 * that were inserted</dd> 1591 * <dt> 1592 * </dl> 1593 * </dd> 1594 * <dt>scope</dt> 1595 * <dd>the execution context for the callbacks</dd> 1596 * <dt>win</dt> 1597 * <dd>a window other than the one the utility occupies</dd> 1598 * <dt>autopurge</dt> 1599 * <dd> 1600 * setting to true will let the utilities cleanup routine purge 1601 * the script once loaded 1602 * </dd> 1603 * <dt>data</dt> 1604 * <dd> 1605 * data that is supplied to the callback when the script(s) are 1606 * loaded. 1607 * </dd> 1608 * <dt>varName</dt> 1609 * <dd> 1610 * variable that should be available when a script is finished 1611 * loading. Used to help Safari 2.x and below with script load 1612 * detection. The type of this property should match what was 1613 * passed into the url parameter: if loading a single url, a 1614 * string can be supplied. If loading multiple scripts, you 1615 * must supply an array that contains the variable name for 1616 * each script. 1617 * </dd> 1618 * <dt>insertBefore</dt> 1619 * <dd>node or node id that will become the new node's nextSibling</dd> 1620 * </dl> 1621 * <dt>charset</dt> 1622 * <dd>Node charset, default utf-8</dd> 1623 * <dt>timeout</dt> 1624 * <dd>Number of milliseconds to wait before aborting and firing the timeout event</dd> 1625 * <pre> 1626 * // assumes yahoo, dom, and event are already on the page 1627 * YAHOO.util.Get.script( 1628 * ["http://yui.yahooapis.com/2.3.1/build/dragdrop/dragdrop-min.js", 1629 * "http://yui.yahooapis.com/2.3.1/build/animation/animation-min.js"], { 1630 * onSuccess: function(o) { 1631 * new YAHOO.util.DDProxy("dd1"); // also new o.reference("dd1"); would work 1632 * this.log("won't cause error because YAHOO is the scope"); 1633 * this.log(o.nodes.length === 2) // true 1634 * // o.purge(); // optionally remove the script nodes immediately 1635 * }, 1636 * onFailure: function(o) { 1637 * }, 1638 * data: "foo", 1639 * timeout: 10000, // 10 second timeout 1640 * scope: YAHOO, 1641 * // win: otherframe // target another window/frame 1642 * autopurge: true // allow the utility to choose when to remove the nodes 1643 * }); 1644 * </pre> 1645 * @return {tId: string} an object containing info about the transaction 1646 */ 1647 script: function(url, opts) { return _queue("script", url, opts); }, 1648 1649 /** 1650 * Fetches and inserts one or more css link nodes into the 1651 * head of the current document or the document in a specified 1652 * window. 1653 * @method css 1654 * @static 1655 * @param url {string} the url or urls to the css file(s) 1656 * @param opts Options: 1657 * <dl> 1658 * <dt>onSuccess</dt> 1659 * <dd> 1660 * callback to execute when the css file(s) are finished loading 1661 * The callback receives an object back with the following 1662 * data: 1663 * <dl>win</dl> 1664 * <dd>the window the link nodes(s) were inserted into</dd> 1665 * <dt>data</dt> 1666 * <dd>the data object passed in when the request was made</dd> 1667 * <dt>nodes</dt> 1668 * <dd>An array containing references to the nodes that were 1669 * inserted</dd> 1670 * <dt>purge</dt> 1671 * <dd>A function that, when executed, will remove the nodes 1672 * that were inserted</dd> 1673 * <dt> 1674 * </dl> 1675 * </dd> 1676 * <dt>scope</dt> 1677 * <dd>the execution context for the callbacks</dd> 1678 * <dt>win</dt> 1679 * <dd>a window other than the one the utility occupies</dd> 1680 * <dt>data</dt> 1681 * <dd> 1682 * data that is supplied to the callbacks when the nodes(s) are 1683 * loaded. 1684 * </dd> 1685 * <dt>insertBefore</dt> 1686 * <dd>node or node id that will become the new node's nextSibling</dd> 1687 * <dt>charset</dt> 1688 * <dd>Node charset, default utf-8</dd> 1689 * </dl> 1690 * <pre> 1691 * YAHOO.util.Get.css("http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css"); 1692 * </pre> 1693 * <pre> 1694 * YAHOO.util.Get.css(["http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css", 1695 * </pre> 1696 * @return {tId: string} an object containing info about the transaction 1697 */ 1698 css: function(url, opts) { 1699 return _queue("css", url, opts); 1700 } 1701 }; 1702 }(); 1703 1704 YAHOO.register("get", YAHOO.util.Get, {version: "2.6.0", build: "1321"}); 1705 /** 1706 * Provides dynamic loading for the YUI library. It includes the dependency 1707 * info for the library, and will automatically pull in dependencies for 1708 * the modules requested. It supports rollup files (such as utilities.js 1709 * and yahoo-dom-event.js), and will automatically use these when 1710 * appropriate in order to minimize the number of http connections 1711 * required to load all of the dependencies. 1712 * 1713 * @module yuiloader 1714 * @namespace YAHOO.util 1715 */ 1716 1717 /** 1718 * YUILoader provides dynamic loading for YUI. 1719 * @class YAHOO.util.YUILoader 1720 * @todo 1721 * version management, automatic sandboxing 1722 */ 1723 (function() { 1724 1725 var Y=YAHOO, util=Y.util, lang=Y.lang, env=Y.env, 1726 PROV = "_provides", SUPER = "_supersedes", 1727 REQ = "expanded", AFTER = "_after"; 1728 1729 var YUI = { 1730 1731 dupsAllowed: {'yahoo': true, 'get': true}, 1732 1733 /* 1734 * The library metadata for the current release The is the default 1735 * value for YAHOO.util.YUILoader.moduleInfo 1736 * @property YUIInfo 1737 * @static 1738 */ 1739 info: { 1740 1741 // 'root': '2.5.2/build/', 1742 // 'base': 'http://yui.yahooapis.com/2.5.2/build/', 1743 1744 'root': '2.6.0/build/', 1745 'base': 'http://yui.yahooapis.com/2.6.0/build/', 1746 1747 'comboBase': 'http://yui.yahooapis.com/combo?', 1748 1749 'skin': { 1750 'defaultSkin': 'sam', 1751 'base': 'assets/skins/', 1752 'path': 'skin.css', 1753 'after': ['reset', 'fonts', 'grids', 'base'], 1754 'rollup': 3 1755 }, 1756 1757 dupsAllowed: ['yahoo', 'get'], 1758 1759 'moduleInfo': { 1760 1761 'animation': { 1762 'type': 'js', 1763 'path': 'animation/animation-min.js', 1764 'requires': ['dom', 'event'] 1765 }, 1766 1767 'autocomplete': { 1768 'type': 'js', 1769 'path': 'autocomplete/autocomplete-min.js', 1770 'requires': ['dom', 'event', 'datasource'], 1771 'optional': ['connection', 'animation'], 1772 'skinnable': true 1773 }, 1774 1775 'base': { 1776 'type': 'css', 1777 'path': 'base/base-min.css', 1778 'after': ['reset', 'fonts', 'grids'] 1779 }, 1780 1781 'button': { 1782 'type': 'js', 1783 'path': 'button/button-min.js', 1784 'requires': ['element'], 1785 'optional': ['menu'], 1786 'skinnable': true 1787 }, 1788 1789 'calendar': { 1790 'type': 'js', 1791 'path': 'calendar/calendar-min.js', 1792 'requires': ['event', 'dom'], 1793 'skinnable': true 1794 }, 1795 1796 'carousel': { 1797 'type': 'js', 1798 'path': 'carousel/carousel-beta-min.js', 1799 'requires': ['element'], 1800 'optional': ['animation'], 1801 'skinnable': true 1802 }, 1803 1804 'charts': { 1805 'type': 'js', 1806 'path': 'charts/charts-experimental-min.js', 1807 'requires': ['element', 'json', 'datasource'] 1808 }, 1809 1810 'colorpicker': { 1811 'type': 'js', 1812 'path': 'colorpicker/colorpicker-min.js', 1813 'requires': ['slider', 'element'], 1814 'optional': ['animation'], 1815 'skinnable': true 1816 }, 1817 1818 'connection': { 1819 'type': 'js', 1820 'path': 'connection/connection-min.js', 1821 'requires': ['event'] 1822 }, 1823 1824 'container': { 1825 'type': 'js', 1826 'path': 'container/container-min.js', 1827 'requires': ['dom', 'event'], 1828 // button is also optional, but this creates a circular 1829 // dependency when loadOptional is specified. button 1830 // optionally includes menu, menu requires container. 1831 'optional': ['dragdrop', 'animation', 'connection'], 1832 'supersedes': ['containercore'], 1833 'skinnable': true 1834 }, 1835 1836 'containercore': { 1837 'type': 'js', 1838 'path': 'container/container_core-min.js', 1839 'requires': ['dom', 'event'], 1840 'pkg': 'container' 1841 }, 1842 1843 'cookie': { 1844 'type': 'js', 1845 'path': 'cookie/cookie-min.js', 1846 'requires': ['yahoo'] 1847 }, 1848 1849 'datasource': { 1850 'type': 'js', 1851 'path': 'datasource/datasource-min.js', 1852 'requires': ['event'], 1853 'optional': ['connection'] 1854 }, 1855 1856 'datatable': { 1857 'type': 'js', 1858 'path': 'datatable/datatable-min.js', 1859 'requires': ['element', 'datasource'], 1860 'optional': ['calendar', 'dragdrop', 'paginator'], 1861 'skinnable': true 1862 }, 1863 1864 'dom': { 1865 'type': 'js', 1866 'path': 'dom/dom-min.js', 1867 'requires': ['yahoo'] 1868 }, 1869 1870 'dragdrop': { 1871 'type': 'js', 1872 'path': 'dragdrop/dragdrop-min.js', 1873 'requires': ['dom', 'event'] 1874 }, 1875 1876 'editor': { 1877 'type': 'js', 1878 'path': 'editor/editor-min.js', 1879 'requires': ['menu', 'element', 'button'], 1880 'optional': ['animation', 'dragdrop'], 1881 'supersedes': ['simpleeditor'], 1882 'skinnable': true 1883 }, 1884 1885 'element': { 1886 'type': 'js', 1887 'path': 'element/element-beta-min.js', 1888 'requires': ['dom', 'event'] 1889 }, 1890 1891 'event': { 1892 'type': 'js', 1893 'path': 'event/event-min.js', 1894 'requires': ['yahoo'] 1895 }, 1896 1897 'fonts': { 1898 'type': 'css', 1899 'path': 'fonts/fonts-min.css' 1900 }, 1901 1902 'get': { 1903 'type': 'js', 1904 'path': 'get/get-min.js', 1905 'requires': ['yahoo'] 1906 }, 1907 1908 'grids': { 1909 'type': 'css', 1910 'path': 'grids/grids-min.css', 1911 'requires': ['fonts'], 1912 'optional': ['reset'] 1913 }, 1914 1915 'history': { 1916 'type': 'js', 1917 'path': 'history/history-min.js', 1918 'requires': ['event'] 1919 }, 1920 1921 'imagecropper': { 1922 'type': 'js', 1923 'path': 'imagecropper/imagecropper-beta-min.js', 1924 'requires': ['dom', 'event', 'dragdrop', 'element', 'resize'], 1925 'skinnable': true 1926 }, 1927 1928 'imageloader': { 1929 'type': 'js', 1930 'path': 'imageloader/imageloader-min.js', 1931 'requires': ['event', 'dom'] 1932 }, 1933 1934 'json': { 1935 'type': 'js', 1936 'path': 'json/json-min.js', 1937 'requires': ['yahoo'] 1938 }, 1939 1940 'layout': { 1941 'type': 'js', 1942 'path': 'layout/layout-min.js', 1943 'requires': ['dom', 'event', 'element'], 1944 'optional': ['animation', 'dragdrop', 'resize', 'selector'], 1945 'skinnable': true 1946 }, 1947 1948 'logger': { 1949 'type': 'js', 1950 'path': 'logger/logger-min.js', 1951 'requires': ['event', 'dom'], 1952 'optional': ['dragdrop'], 1953 'skinnable': true 1954 }, 1955 1956 'menu': { 1957 'type': 'js', 1958 'path': 'menu/menu-min.js', 1959 'requires': ['containercore'], 1960 'skinnable': true 1961 }, 1962 1963 'paginator': { 1964 'type': 'js', 1965 'path': 'paginator/paginator-min.js', 1966 'requires': ['element'], 1967 'skinnable': true 1968 }, 1969 1970 'profiler': { 1971 'type': 'js', 1972 'path': 'profiler/profiler-min.js', 1973 'requires': ['yahoo'] 1974 }, 1975 1976 1977 'profilerviewer': { 1978 'type': 'js', 1979 'path': 'profilerviewer/profilerviewer-beta-min.js', 1980 'requires': ['profiler', 'yuiloader', 'element'], 1981 'skinnable': true 1982 }, 1983 1984 'reset': { 1985 'type': 'css', 1986 'path': 'reset/reset-min.css' 1987 }, 1988 1989 'reset-fonts-grids': { 1990 'type': 'css', 1991 'path': 'reset-fonts-grids/reset-fonts-grids.css', 1992 'supersedes': ['reset', 'fonts', 'grids', 'reset-fonts'], 1993 'rollup': 4 1994 }, 1995 1996 'reset-fonts': { 1997 'type': 'css', 1998 'path': 'reset-fonts/reset-fonts.css', 1999 'supersedes': ['reset', 'fonts'], 2000 'rollup': 2 2001 }, 2002 2003 'resize': { 2004 'type': 'js', 2005 'path': 'resize/resize-min.js', 2006 'requires': ['dom', 'event', 'dragdrop', 'element'], 2007 'optional': ['animation'], 2008 'skinnable': true 2009 }, 2010 2011 'selector': { 2012 'type': 'js', 2013 'path': 'selector/selector-beta-min.js', 2014 'requires': ['yahoo', 'dom'] 2015 }, 2016 2017 'simpleeditor': { 2018 'type': 'js', 2019 'path': 'editor/simpleeditor-min.js', 2020 'requires': ['element'], 2021 'optional': ['containercore', 'menu', 'button', 'animation', 'dragdrop'], 2022 'skinnable': true, 2023 'pkg': 'editor' 2024 }, 2025 2026 'slider': { 2027 'type': 'js', 2028 'path': 'slider/slider-min.js', 2029 'requires': ['dragdrop'], 2030 'optional': ['animation'], 2031 'skinnable': true 2032 }, 2033 2034 'tabview': { 2035 'type': 'js', 2036 'path': 'tabview/tabview-min.js', 2037 'requires': ['element'], 2038 'optional': ['connection'], 2039 'skinnable': true 2040 }, 2041 2042 'treeview': { 2043 'type': 'js', 2044 'path': 'treeview/treeview-min.js', 2045 'requires': ['event', 'dom'], 2046 'skinnable': true 2047 }, 2048 2049 'uploader': { 2050 'type': 'js', 2051 'path': 'uploader/uploader-experimental.js', 2052 'requires': ['element'] 2053 }, 2054 2055 'utilities': { 2056 'type': 'js', 2057 'path': 'utilities/utilities.js', 2058 'supersedes': ['yahoo', 'event', 'dragdrop', 'animation', 'dom', 'connection', 'element', 'yahoo-dom-event', 'get', 'yuiloader', 'yuiloader-dom-event'], 2059 'rollup': 8 2060 }, 2061 2062 'yahoo': { 2063 'type': 'js', 2064 'path': 'yahoo/yahoo-min.js' 2065 }, 2066 2067 'yahoo-dom-event': { 2068 'type': 'js', 2069 'path': 'yahoo-dom-event/yahoo-dom-event.js', 2070 'supersedes': ['yahoo', 'event', 'dom'], 2071 'rollup': 3 2072 }, 2073 2074 'yuiloader': { 2075 'type': 'js', 2076 'path': 'yuiloader/yuiloader-min.js', 2077 'supersedes': ['yahoo', 'get'] 2078 }, 2079 2080 'yuiloader-dom-event': { 2081 'type': 'js', 2082 'path': 'yuiloader-dom-event/yuiloader-dom-event.js', 2083 'supersedes': ['yahoo', 'dom', 'event', 'get', 'yuiloader', 'yahoo-dom-event'], 2084 'rollup': 5 2085 }, 2086 2087 'yuitest': { 2088 'type': 'js', 2089 'path': 'yuitest/yuitest-min.js', 2090 'requires': ['logger'], 2091 'skinnable': true 2092 } 2093 } 2094 } 2095 , 2096 2097 ObjectUtil: { 2098 appendArray: function(o, a) { 2099 if (a) { 2100 for (var i=0; i<a.length; i=i+1) { 2101 o[a[i]] = true; 2102 } 2103 } 2104 }, 2105 2106 keys: function(o, ordered) { 2107 var a=[], i; 2108 for (i in o) { 2109 if (lang.hasOwnProperty(o, i)) { 2110 a.push(i); 2111 } 2112 } 2113 2114 return a; 2115 } 2116 }, 2117 2118 ArrayUtil: { 2119 2120 appendArray: function(a1, a2) { 2121 Array.prototype.push.apply(a1, a2); 2122 /* 2123 for (var i=0; i<a2.length; i=i+1) { 2124 a1.push(a2[i]); 2125 } 2126 */ 2127 }, 2128 2129 indexOf: function(a, val) { 2130 for (var i=0; i<a.length; i=i+1) { 2131 if (a[i] === val) { 2132 return i; 2133 } 2134 } 2135 2136 return -1; 2137 }, 2138 2139 toObject: function(a) { 2140 var o = {}; 2141 for (var i=0; i<a.length; i=i+1) { 2142 o[a[i]] = true; 2143 } 2144 2145 return o; 2146 }, 2147 2148 /* 2149 * Returns a unique array. Does not maintain order, which is fine 2150 * for this application, and performs better than it would if it 2151 * did. 2152 */ 2153 uniq: function(a) { 2154 return YUI.ObjectUtil.keys(YUI.ArrayUtil.toObject(a)); 2155 } 2156 } 2157 }; 2158 2159 YAHOO.util.YUILoader = function(o) { 2160 2161 /** 2162 * Internal callback to handle multiple internal insert() calls 2163 * so that css is inserted prior to js 2164 * @property _internalCallback 2165 * @private 2166 */ 2167 this._internalCallback = null; 2168 2169 /** 2170 * Use the YAHOO environment listener to detect script load. This 2171 * is only switched on for Safari 2.x and below. 2172 * @property _useYahooListener 2173 * @private 2174 */ 2175 this._useYahooListener = false; 2176 2177 /** 2178 * Callback that will be executed when the loader is finished 2179 * with an insert 2180 * @method onSuccess 2181 * @type function 2182 */ 2183 this.onSuccess = null; 2184 2185 /** 2186 * Callback that will be executed if there is a failure 2187 * @method onFailure 2188 * @type function 2189 */ 2190 this.onFailure = Y.log; 2191 2192 /** 2193 * Callback that will be executed each time a new module is loaded 2194 * @method onProgress 2195 * @type function 2196 */ 2197 this.onProgress = null; 2198 2199 /** 2200 * Callback that will be executed if a timeout occurs 2201 * @method onTimeout 2202 * @type function 2203 */ 2204 this.onTimeout = null; 2205 2206 /** 2207 * The execution scope for all callbacks 2208 * @property scope 2209 * @default this 2210 */ 2211 this.scope = this; 2212 2213 /** 2214 * Data that is passed to all callbacks 2215 * @property data 2216 */ 2217 this.data = null; 2218 2219 /** 2220 * Node reference or id where new nodes should be inserted before 2221 * @property insertBefore 2222 * @type string|HTMLElement 2223 */ 2224 this.insertBefore = null; 2225 2226 /** 2227 * The charset attribute for inserted nodes 2228 * @property charset 2229 * @type string 2230 * @default utf-8 2231 */ 2232 this.charset = null; 2233 2234 /** 2235 * The name of the variable in a sandbox or script node 2236 * (for external script support in Safari 2.x and earlier) 2237 * to reference when the load is complete. If this variable 2238 * is not available in the specified scripts, the operation will 2239 * fail. 2240 * @property varName 2241 * @type string 2242 */ 2243 this.varName = null; 2244 2245 /** 2246 * The base directory. 2247 * @property base 2248 * @type string 2249 * @default http://yui.yahooapis.com/[YUI VERSION]/build/ 2250 */ 2251 this.base = YUI.info.base; 2252 2253 /** 2254 * Base path for the combo service 2255 * @property comboBase 2256 * @type string 2257 * @default http://yui.yahooapis.com/combo? 2258 */ 2259 this.comboBase = YUI.info.comboBase; 2260 2261 /** 2262 * If configured, YUI will use the the combo handler on the 2263 * Yahoo! CDN to pontentially reduce the number of http requests 2264 * required. 2265 * @property combine 2266 * @type boolean 2267 * @default false 2268 */ 2269 // this.combine = (o && !('base' in o)); 2270 this.combine = false; 2271 2272 2273 /** 2274 * Root path to prepend to module path for the combo 2275 * service 2276 * @property root 2277 * @type string 2278 * @default [YUI VERSION]/build/ 2279 */ 2280 this.root = YUI.info.root; 2281 2282 /** 2283 * Timeout value in milliseconds. If set, this value will be used by 2284 * the get utility. the timeout event will fire if 2285 * a timeout occurs. 2286 * @property timeout 2287 * @type int 2288 */ 2289 this.timeout = 0; 2290 2291 /** 2292 * A list of modules that should not be loaded, even if 2293 * they turn up in the dependency tree 2294 * @property ignore 2295 * @type string[] 2296 */ 2297 this.ignore = null; 2298 2299 /** 2300 * A list of modules that should always be loaded, even 2301 * if they have already been inserted into the page. 2302 * @property force 2303 * @type string[] 2304 */ 2305 this.force = null; 2306 2307 /** 2308 * Should we allow rollups 2309 * @property allowRollup 2310 * @type boolean 2311 * @default true 2312 */ 2313 this.allowRollup = true; 2314 2315 /** 2316 * A filter to apply to result urls. This filter will modify the default 2317 * path for all modules. The default path for the YUI library is the 2318 * minified version of the files (e.g., event-min.js). The filter property 2319 * can be a predefined filter or a custom filter. The valid predefined 2320 * filters are: 2321 * <dl> 2322 * <dt>DEBUG</dt> 2323 * <dd>Selects the debug versions of the library (e.g., event-debug.js). 2324 * This option will automatically include the logger widget</dd> 2325 * <dt>RAW</dt> 2326 * <dd>Selects the non-minified version of the library (e.g., event.js). 2327 * </dl> 2328 * You can also define a custom filter, which must be an object literal 2329 * containing a search expression and a replace string: 2330 * <pre> 2331 * myFilter: { 2332 * 'searchExp': "-min\\.js", 2333 * 'replaceStr': "-debug.js" 2334 * } 2335 * </pre> 2336 * @property filter 2337 * @type string|{searchExp: string, replaceStr: string} 2338 */ 2339 this.filter = null; 2340 2341 /** 2342 * The list of requested modules 2343 * @property required 2344 * @type {string: boolean} 2345 */ 2346 this.required = {}; 2347 2348 /** 2349 * The library metadata 2350 * @property moduleInfo 2351 */ 2352 this.moduleInfo = lang.merge(YUI.info.moduleInfo); 2353 2354 /** 2355 * List of rollup files found in the library metadata 2356 * @property rollups 2357 */ 2358 this.rollups = null; 2359 2360 /** 2361 * Whether or not to load optional dependencies for 2362 * the requested modules 2363 * @property loadOptional 2364 * @type boolean 2365 * @default false 2366 */ 2367 this.loadOptional = false; 2368 2369 /** 2370 * All of the derived dependencies in sorted order, which 2371 * will be populated when either calculate() or insert() 2372 * is called 2373 * @property sorted 2374 * @type string[] 2375 */ 2376 this.sorted = []; 2377 2378 /** 2379 * Set when beginning to compute the dependency tree. 2380 * Composed of what YAHOO reports to be loaded combined 2381 * with what has been loaded by the tool 2382 * @propery loaded 2383 * @type {string: boolean} 2384 */ 2385 this.loaded = {}; 2386 2387 /** 2388 * Flag to indicate the dependency tree needs to be recomputed 2389 * if insert is called again. 2390 * @property dirty 2391 * @type boolean 2392 * @default true 2393 */ 2394 this.dirty = true; 2395 2396 /** 2397 * List of modules inserted by the utility 2398 * @property inserted 2399 * @type {string: boolean} 2400 */ 2401 this.inserted = {}; 2402 2403 /** 2404 * Provides the information used to skin the skinnable components. 2405 * The following skin definition would result in 'skin1' and 'skin2' 2406 * being loaded for calendar (if calendar was requested), and 2407 * 'sam' for all other skinnable components: 2408 * 2409 * <code> 2410 * skin: { 2411 * 2412 * // The default skin, which is automatically applied if not 2413 * // overriden by a component-specific skin definition. 2414 * // Change this in to apply a different skin globally 2415 * defaultSkin: 'sam', 2416 * 2417 * // This is combined with the loader base property to get 2418 * // the default root directory for a skin. ex: 2419 * // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/ 2420 * base: 'assets/skins/', 2421 * 2422 * // The name of the rollup css file for the skin 2423 * path: 'skin.css', 2424 * 2425 * // The number of skinnable components requested that are 2426 * // required before using the rollup file rather than the 2427 * // individual component css files 2428 * rollup: 3, 2429 * 2430 * // Any component-specific overrides can be specified here, 2431 * // making it possible to load different skins for different 2432 * // components. It is possible to load more than one skin 2433 * // for a given component as well. 2434 * overrides: { 2435 * calendar: ['skin1', 'skin2'] 2436 * } 2437 * } 2438 * </code> 2439 * @property skin 2440 */ 2441 2442 var self = this; 2443 2444 env.listeners.push(function(m) { 2445 if (self._useYahooListener) { 2446 //Y.log("YAHOO listener: " + m.name); 2447 self.loadNext(m.name); 2448 } 2449 }); 2450 2451 this.skin = lang.merge(YUI.info.skin); 2452 2453 this._config(o); 2454 2455 }; 2456 2457 Y.util.YUILoader.prototype = { 2458 2459 FILTERS: { 2460 RAW: { 2461 'searchExp': "-min\\.js", 2462 'replaceStr': ".js" 2463 }, 2464 DEBUG: { 2465 'searchExp': "-min\\.js", 2466 'replaceStr': "-debug.js" 2467 } 2468 }, 2469 2470 SKIN_PREFIX: "skin-", 2471 2472 _config: function(o) { 2473 2474 // apply config values 2475 if (o) { 2476 for (var i in o) { 2477 if (lang.hasOwnProperty(o, i)) { 2478 if (i == "require") { 2479 this.require(o[i]); 2480 } else { 2481 this[i] = o[i]; 2482 } 2483 } 2484 } 2485 } 2486 2487 // fix filter 2488 var f = this.filter; 2489 2490 if (lang.isString(f)) { 2491 f = f.toUpperCase(); 2492 2493 // the logger must be available in order to use the debug 2494 // versions of the library 2495 if (f === "DEBUG") { 2496 this.require("logger"); 2497 } 2498 2499 // hack to handle a a bug where LogWriter is being instantiated 2500 // at load time, and the loader has no way to sort above it 2501 // at the moment. 2502 if (!Y.widget.LogWriter) { 2503 Y.widget.LogWriter = function() { 2504 return Y; 2505 }; 2506 } 2507 2508 this.filter = this.FILTERS[f]; 2509 } 2510 2511 }, 2512 2513 /** Add a new module to the component metadata. 2514 * <dl> 2515 * <dt>name:</dt> <dd>required, the component name</dd> 2516 * <dt>type:</dt> <dd>required, the component type (js or css)</dd> 2517 * <dt>path:</dt> <dd>required, the path to the script from "base"</dd> 2518 * <dt>requires:</dt> <dd>array of modules required by this component</dd> 2519 * <dt>optional:</dt> <dd>array of optional modules for this component</dd> 2520 * <dt>supersedes:</dt> <dd>array of the modules this component replaces</dd> 2521 * <dt>after:</dt> <dd>array of modules the components which, if present, should be sorted above this one</dd> 2522 * <dt>rollup:</dt> <dd>the number of superseded modules required for automatic rollup</dd> 2523 * <dt>fullpath:</dt> <dd>If fullpath is specified, this is used instead of the configured base + path</dd> 2524 * <dt>skinnable:</dt> <dd>flag to determine if skin assets should automatically be pulled in</dd> 2525 * </dl> 2526 * @method addModule 2527 * @param o An object containing the module data 2528 * @return {boolean} true if the module was added, false if 2529 * the object passed in did not provide all required attributes 2530 */ 2531 addModule: function(o) { 2532 2533 if (!o || !o.name || !o.type || (!o.path && !o.fullpath)) { 2534 return false; 2535 } 2536 2537 o.ext = ('ext' in o) ? o.ext : true; 2538 o.requires = o.requires || []; 2539 2540 this.moduleInfo[o.name] = o; 2541 this.dirty = true; 2542 2543 return true; 2544 }, 2545 2546 /** 2547 * Add a requirement for one or more module 2548 * @method require 2549 * @param what {string[] | string*} the modules to load 2550 */ 2551 require: function(what) { 2552 var a = (typeof what === "string") ? arguments : what; 2553 this.dirty = true; 2554 YUI.ObjectUtil.appendArray(this.required, a); 2555 }, 2556 2557 /** 2558 * Adds the skin def to the module info 2559 * @method _addSkin 2560 * @param skin {string} the name of the skin 2561 * @param mod {string} the name of the module 2562 * @return {string} the module name for the skin 2563 * @private 2564 */ 2565 _addSkin: function(skin, mod) { 2566 2567 // Add a module definition for the skin rollup css 2568 var name = this.formatSkin(skin), info = this.moduleInfo, 2569 sinf = this.skin, ext = info[mod] && info[mod].ext; 2570 2571 // Y.log('ext? ' + mod + ": " + ext); 2572 if (!info[name]) { 2573 // Y.log('adding skin ' + name); 2574 this.addModule({ 2575 'name': name, 2576 'type': 'css', 2577 'path': sinf.base + skin + '/' + sinf.path, 2578 //'supersedes': '*', 2579 'after': sinf.after, 2580 'rollup': sinf.rollup, 2581 'ext': ext 2582 }); 2583 } 2584 2585 // Add a module definition for the module-specific skin css 2586 if (mod) { 2587 name = this.formatSkin(skin, mod); 2588 if (!info[name]) { 2589 var mdef = info[mod], pkg = mdef.pkg || mod; 2590 // Y.log('adding skin ' + name); 2591 this.addModule({ 2592 'name': name, 2593 'type': 'css', 2594 'after': sinf.after, 2595 'path': pkg + '/' + sinf.base + skin + '/' + mod + '.css', 2596 'ext': ext 2597 }); 2598 } 2599 } 2600 2601 return name; 2602 }, 2603 2604 /** 2605 * Returns an object containing properties for all modules required 2606 * in order to load the requested module 2607 * @method getRequires 2608 * @param mod The module definition from moduleInfo 2609 */ 2610 getRequires: function(mod) { 2611 if (!mod) { 2612 return []; 2613 } 2614 2615 if (!this.dirty && mod.expanded) { 2616 return mod.expanded; 2617 } 2618 2619 mod.requires=mod.requires || []; 2620 var i, d=[], r=mod.requires, o=mod.optional, info=this.moduleInfo, m; 2621 for (i=0; i<r.length; i=i+1) { 2622 d.push(r[i]); 2623 m = info[r[i]]; 2624 YUI.ArrayUtil.appendArray(d, this.getRequires(m)); 2625 2626 // add existing skins for skinnable modules as well. The only 2627 // way to do this is go through the list of required items (this 2628 // assumes that _skin is called before getRequires is called on 2629 // the module. 2630 // if (m.skinnable) { 2631 // var req=this.required, l=req.length; 2632 // for (var j=0; j<l; j=j+1) { 2633 // // YAHOO.log('checking ' + r[j]); 2634 // if (req[j].indexOf(r[j]) > -1) { 2635 // // YAHOO.log('adding ' + r[j]); 2636 // d.push(req[j]); 2637 // } 2638 // } 2639 // } 2640 } 2641 2642 if (o && this.loadOptional) { 2643 for (i=0; i<o.length; i=i+1) { 2644 d.push(o[i]); 2645 YUI.ArrayUtil.appendArray(d, this.getRequires(info[o[i]])); 2646 } 2647 } 2648 2649 mod.expanded = YUI.ArrayUtil.uniq(d); 2650 2651 return mod.expanded; 2652 }, 2653 2654 2655 /** 2656 * Returns an object literal of the modules the supplied module satisfies 2657 * @method getProvides 2658 * @param name{string} The name of the module 2659 * @param notMe {string} don't add this module name, only include superseded modules 2660 * @return what this module provides 2661 */ 2662 getProvides: function(name, notMe) { 2663 var addMe = !(notMe), ckey = (addMe) ? PROV : SUPER, 2664 m = this.moduleInfo[name], o = {}; 2665 2666 if (!m) { 2667 return o; 2668 } 2669 2670 if (m[ckey]) { 2671 // Y.log('cached: ' + name + ' ' + ckey + ' ' + lang.dump(this.moduleInfo[name][ckey], 0)); 2672 return m[ckey]; 2673 } 2674 2675 var s = m.supersedes, done={}, me = this; 2676 2677 // use worker to break cycles 2678 var add = function(mm) { 2679 if (!done[mm]) { 2680 // Y.log(name + ' provides worker trying: ' + mm); 2681 done[mm] = true; 2682 // we always want the return value normal behavior 2683 // (provides) for superseded modules. 2684 lang.augmentObject(o, me.getProvides(mm)); 2685 } 2686 2687 // else { 2688 // Y.log(name + ' provides worker skipping done: ' + mm); 2689 // } 2690 }; 2691 2692 // calculate superseded modules 2693 if (s) { 2694 for (var i=0; i<s.length; i=i+1) { 2695 add(s[i]); 2696 } 2697 } 2698 2699 // supersedes cache 2700 m[SUPER] = o; 2701 // provides cache 2702 m[PROV] = lang.merge(o); 2703 m[PROV][name] = true; 2704 2705 // Y.log(name + " supersedes " + lang.dump(m[SUPER], 0)); 2706 // Y.log(name + " provides " + lang.dump(m[PROV], 0)); 2707 2708 return m[ckey]; 2709 }, 2710 2711 2712 /** 2713 * Calculates the dependency tree, the result is stored in the sorted 2714 * property 2715 * @method calculate 2716 * @param o optional options object 2717 */ 2718 calculate: function(o) { 2719 if (o || this.dirty) { 2720 this._config(o); 2721 this._setup(); 2722 this._explode(); 2723 // this._skin(); // deprecated 2724 if (this.allowRollup) { 2725 this._rollup(); 2726 } 2727 this._reduce(); 2728 this._sort(); 2729 2730 // Y.log("after calculate: " + lang.dump(this.required)); 2731 2732 this.dirty = false; 2733 } 2734 }, 2735 2736 /** 2737 * Investigates the current YUI configuration on the page. By default, 2738 * modules already detected will not be loaded again unless a force 2739 * option is encountered. Called by calculate() 2740 * @method _setup 2741 * @private 2742 */ 2743 _setup: function() { 2744 2745 var info = this.moduleInfo, name, i, j; 2746 2747 // Create skin modules 2748 for (name in info) { 2749 2750 if (lang.hasOwnProperty(info, name)) { 2751 var m = info[name]; 2752 if (m && m.skinnable) { 2753 // Y.log("skinning: " + name); 2754 var o=this.skin.overrides, smod; 2755 if (o && o[name]) { 2756 for (i=0; i<o[name].length; i=i+1) { 2757 smod = this._addSkin(o[name][i], name); 2758 } 2759 } else { 2760 smod = this._addSkin(this.skin.defaultSkin, name); 2761 } 2762 2763 m.requires.push(smod); 2764 } 2765 } 2766 2767 } 2768 2769 var l = lang.merge(this.inserted); // shallow clone 2770 2771 if (!this._sandbox) { 2772 l = lang.merge(l, env.modules); 2773 } 2774 2775 // Y.log("Already loaded stuff: " + lang.dump(l, 0)); 2776 2777 // add the ignore list to the list of loaded packages 2778 if (this.ignore) { 2779 YUI.ObjectUtil.appendArray(l, this.ignore); 2780 } 2781 2782 // remove modules on the force list from the loaded list 2783 if (this.force) { 2784 for (i=0; i<this.force.length; i=i+1) { 2785 if (this.force[i] in l) { 2786 delete l[this.force[i]]; 2787 } 2788 } 2789 } 2790 2791 // expand the list to include superseded modules 2792 for (j in l) { 2793 // Y.log("expanding: " + j); 2794 if (lang.hasOwnProperty(l, j)) { 2795 lang.augmentObject(l, this.getProvides(j)); 2796 } 2797 } 2798 2799 // Y.log("loaded expanded: " + lang.dump(l, 0)); 2800 2801 this.loaded = l; 2802 2803 }, 2804 2805 2806 /** 2807 * Inspects the required modules list looking for additional 2808 * dependencies. Expands the required list to include all 2809 * required modules. Called by calculate() 2810 * @method _explode 2811 * @private 2812 */ 2813 _explode: function() { 2814 2815 var r=this.required, i, mod; 2816 2817 for (i in r) { 2818 if (lang.hasOwnProperty(r, i)) { 2819 mod = this.moduleInfo[i]; 2820 if (mod) { 2821 2822 var req = this.getRequires(mod); 2823 2824 if (req) { 2825 YUI.ObjectUtil.appendArray(r, req); 2826 } 2827 } 2828 } 2829 } 2830 }, 2831 2832 /** 2833 * Sets up the requirements for the skin assets if any of the 2834 * requested modules are skinnable 2835 * @method _skin 2836 * @private 2837 * @deprecated skin modules are generated for all skinnable 2838 * components during _setup(), and the components 2839 * are configured to require the skin. 2840 */ 2841 _skin: function() { 2842 2843 }, 2844 2845 /** 2846 * Returns the skin module name for the specified skin name. If a 2847 * module name is supplied, the returned skin module name is 2848 * specific to the module passed in. 2849 * @method formatSkin 2850 * @param skin {string} the name of the skin 2851 * @param mod {string} optional: the name of a module to skin 2852 * @return {string} the full skin module name 2853 */ 2854 formatSkin: function(skin, mod) { 2855 var s = this.SKIN_PREFIX + skin; 2856 if (mod) { 2857 s = s + "-" + mod; 2858 } 2859 2860 return s; 2861 }, 2862 2863 /** 2864 * Reverses <code>formatSkin</code>, providing the skin name and 2865 * module name if the string matches the pattern for skins. 2866 * @method parseSkin 2867 * @param mod {string} the module name to parse 2868 * @return {skin: string, module: string} the parsed skin name 2869 * and module name, or null if the supplied string does not match 2870 * the skin pattern 2871 */ 2872 parseSkin: function(mod) { 2873 2874 if (mod.indexOf(this.SKIN_PREFIX) === 0) { 2875 var a = mod.split("-"); 2876 return {skin: a[1], module: a[2]}; 2877 } 2878 2879 return null; 2880 }, 2881 2882 /** 2883 * Look for rollup packages to determine if all of the modules a 2884 * rollup supersedes are required. If so, include the rollup to 2885 * help reduce the total number of connections required. Called 2886 * by calculate() 2887 * @method _rollup 2888 * @private 2889 */ 2890 _rollup: function() { 2891 var i, j, m, s, rollups={}, r=this.required, roll, 2892 info = this.moduleInfo; 2893 2894 // find and cache rollup modules 2895 if (this.dirty || !this.rollups) { 2896 for (i in info) { 2897 if (lang.hasOwnProperty(info, i)) { 2898 m = info[i]; 2899 //if (m && m.rollup && m.supersedes) { 2900 if (m && m.rollup) { 2901 rollups[i] = m; 2902 } 2903 } 2904 } 2905 2906 this.rollups = rollups; 2907 } 2908 2909 // make as many passes as needed to pick up rollup rollups 2910 for (;;) { 2911 var rolled = false; 2912 2913 // go through the rollup candidates 2914 for (i in rollups) { 2915 2916 // there can be only one 2917 if (!r[i] && !this.loaded[i]) { 2918 m =info[i]; s = m.supersedes; roll=false; 2919 2920 if (!m.rollup) { 2921 continue; 2922 } 2923 2924 var skin = (m.ext) ? false : this.parseSkin(i), c = 0; 2925 2926 // Y.log('skin? ' + i + ": " + skin); 2927 if (skin) { 2928 for (j in r) { 2929 if (lang.hasOwnProperty(r, j)) { 2930 if (i !== j && this.parseSkin(j)) { 2931 c++; 2932 roll = (c >= m.rollup); 2933 if (roll) { 2934 // Y.log("skin rollup " + lang.dump(r)); 2935 break; 2936 } 2937 } 2938 } 2939 } 2940 2941 } else { 2942 2943 // check the threshold 2944 for (j=0;j<s.length;j=j+1) { 2945 2946 // if the superseded module is loaded, we can't load the rollup 2947 if (this.loaded[s[j]] && (!YUI.dupsAllowed[s[j]])) { 2948 roll = false; 2949 break; 2950 // increment the counter if this module is required. if we are 2951 // beyond the rollup threshold, we will use the rollup module 2952 } else if (r[s[j]]) { 2953 c++; 2954 roll = (c >= m.rollup); 2955 if (roll) { 2956 // Y.log("over thresh " + c + ", " + lang.dump(r)); 2957 break; 2958 } 2959 } 2960 } 2961 } 2962 2963 if (roll) { 2964 // Y.log("rollup: " + i + ", " + lang.dump(this, 1)); 2965 // add the rollup 2966 r[i] = true; 2967 rolled = true; 2968 2969 // expand the rollup's dependencies 2970 this.getRequires(m); 2971 } 2972 } 2973 } 2974 2975 // if we made it here w/o rolling up something, we are done 2976 if (!rolled) { 2977 break; 2978 } 2979 } 2980 }, 2981 2982 /** 2983 * Remove superceded modules and loaded modules. Called by 2984 * calculate() after we have the mega list of all dependencies 2985 * @method _reduce 2986 * @private 2987 */ 2988 _reduce: function() { 2989 2990 var i, j, s, m, r=this.required; 2991 for (i in r) { 2992 2993 // remove if already loaded 2994 if (i in this.loaded) { 2995 delete r[i]; 2996 2997 // remove anything this module supersedes 2998 } else { 2999 3000 var skinDef = this.parseSkin(i); 3001 3002 if (skinDef) { 3003 //YAHOO.log("skin found in reduce: " + skinDef.skin + ", " + skinDef.module); 3004 // the skin rollup will not have a module name 3005 if (!skinDef.module) { 3006 var skin_pre = this.SKIN_PREFIX + skinDef.skin; 3007 //YAHOO.log("skin_pre: " + skin_pre); 3008 for (j in r) { 3009 3010 if (lang.hasOwnProperty(r, j)) { 3011 m = this.moduleInfo[j]; 3012 var ext = m && m.ext; 3013 if (!ext && j !== i && j.indexOf(skin_pre) > -1) { 3014 // Y.log ("removing component skin: " + j); 3015 delete r[j]; 3016 } 3017 } 3018 } 3019 } 3020 } else { 3021 3022 m = this.moduleInfo[i]; 3023 s = m && m.supersedes; 3024 if (s) { 3025 for (j=0; j<s.length; j=j+1) { 3026 if (s[j] in r) { 3027 delete r[s[j]]; 3028 } 3029 } 3030 } 3031 } 3032 } 3033 } 3034 }, 3035 3036 _onFailure: function(msg) { 3037 YAHOO.log('Failure', 'info', 'loader'); 3038 3039 var f = this.onFailure; 3040 if (f) { 3041 f.call(this.scope, { 3042 msg: 'failure: ' + msg, 3043 data: this.data, 3044 success: false 3045 }); 3046 } 3047 }, 3048 3049 _onTimeout: function() { 3050 YAHOO.log('Timeout', 'info', 'loader'); 3051 var f = this.onTimeout; 3052 if (f) { 3053 f.call(this.scope, { 3054 msg: 'timeout', 3055 data: this.data, 3056 success: false 3057 }); 3058 } 3059 }, 3060 3061 /** 3062 * Sorts the dependency tree. The last step of calculate() 3063 * @method _sort 3064 * @private 3065 */ 3066 _sort: function() { 3067 // create an indexed list 3068 var s=[], info=this.moduleInfo, loaded=this.loaded, 3069 checkOptional=!this.loadOptional, me = this; 3070 3071 // returns true if b is not loaded, and is required 3072 // directly or by means of modules it supersedes. 3073 var requires = function(aa, bb) { 3074 3075 var mm=info[aa]; 3076 3077 if (loaded[bb] || !mm) { 3078 return false; 3079 } 3080 3081 var ii, 3082 rr = mm.expanded, 3083 after = mm.after, 3084 other = info[bb], 3085 optional = mm.optional; 3086 3087 3088 // check if this module requires the other directly 3089 if (rr && YUI.ArrayUtil.indexOf(rr, bb) > -1) { 3090 return true; 3091 } 3092 3093 // check if this module should be sorted after the other 3094 if (after && YUI.ArrayUtil.indexOf(after, bb) > -1) { 3095 return true; 3096 } 3097 3098 // if loadOptional is not specified, optional dependencies still 3099 // must be sorted correctly when present. 3100 if (checkOptional && optional && YUI.ArrayUtil.indexOf(optional, bb) > -1) { 3101 return true; 3102 } 3103 3104 // check if this module requires one the other supersedes 3105 var ss=info[bb] && info[bb].supersedes; 3106 if (ss) { 3107 for (ii=0; ii<ss.length; ii=ii+1) { 3108 if (requires(aa, ss[ii])) { 3109 return true; 3110 } 3111 } 3112 } 3113 3114 // var ss=me.getProvides(bb, true); 3115 // if (ss) { 3116 // for (ii in ss) { 3117 // if (requires(aa, ii)) { 3118 // return true; 3119 // } 3120 // } 3121 // } 3122 3123 // external css files should be sorted below yui css 3124 if (mm.ext && mm.type == 'css' && !other.ext && other.type == 'css') { 3125 return true; 3126 } 3127 3128 return false; 3129 }; 3130 3131 // get the required items out of the obj into an array so we 3132 // can sort 3133 for (var i in this.required) { 3134 if (lang.hasOwnProperty(this.required, i)) { 3135 s.push(i); 3136 } 3137 } 3138 3139 // pointer to the first unsorted item 3140 var p=0; 3141 3142 // keep going until we make a pass without moving anything 3143 for (;;) { 3144 3145 var l=s.length, a, b, j, k, moved=false; 3146 3147 // start the loop after items that are already sorted 3148 for (j=p; j<l; j=j+1) { 3149 3150 // check the next module on the list to see if its 3151 // dependencies have been met 3152 a = s[j]; 3153 3154 // check everything below current item and move if we 3155 // find a requirement for the current item 3156 for (k=j+1; k<l; k=k+1) { 3157 if (requires(a, s[k])) { 3158 3159 // extract the dependency so we can move it up 3160 b = s.splice(k, 1); 3161 3162 // insert the dependency above the item that 3163 // requires it 3164 s.splice(j, 0, b[0]); 3165 3166 moved = true; 3167 break; 3168 } 3169 } 3170 3171 // jump out of loop if we moved something 3172 if (moved) { 3173 break; 3174 // this item is sorted, move our pointer and keep going 3175 } else { 3176 p = p + 1; 3177 } 3178 } 3179 3180 // when we make it here and moved is false, we are 3181 // finished sorting 3182 if (!moved) { 3183 break; 3184 } 3185 3186 } 3187 3188 this.sorted = s; 3189 }, 3190 3191 toString: function() { 3192 var o = { 3193 type: "YUILoader", 3194 base: this.base, 3195 filter: this.filter, 3196 required: this.required, 3197 loaded: this.loaded, 3198 inserted: this.inserted 3199 }; 3200 3201 lang.dump(o, 1); 3202 }, 3203 3204 _combine: function() { 3205 3206 this._combining = []; 3207 3208 var self = this, 3209 s=this.sorted, 3210 len = s.length, 3211 js = this.comboBase, 3212 css = this.comboBase, 3213 target, 3214 startLen = js.length, 3215 i, m, type = this.loadType; 3216 3217 YAHOO.log('type ' + type); 3218 3219 for (i=0; i<len; i=i+1) { 3220 3221 m = this.moduleInfo[s[i]]; 3222 3223 if (m && !m.ext && (!type || type === m.type)) { 3224 3225 target = this.root + m.path; 3226 3227 // if (i < len-1) { 3228 target += '&'; 3229 // } 3230 3231 if (m.type == 'js') { 3232 js += target; 3233 } else { 3234 css += target; 3235 } 3236 3237 // YAHOO.log(target); 3238 this._combining.push(s[i]); 3239 } 3240 } 3241 3242 if (this._combining.length) { 3243 3244 YAHOO.log('Attempting to combine: ' + this._combining, "info", "loader"); 3245 3246 var callback=function(o) { 3247 // YAHOO.log('Combo complete: ' + o.data, "info", "loader"); 3248 // this._combineComplete = true; 3249 3250 var c=this._combining, len=c.length, i, m; 3251 for (i=0; i<len; i=i+1) { 3252 this.inserted[c[i]] = true; 3253 } 3254 3255 this.loadNext(o.data); 3256 }, 3257 3258 loadScript = function() { 3259 // YAHOO.log('combining js: ' + js); 3260 if (js.length > startLen) { 3261 YAHOO.util.Get.script(self._filter(js), { 3262 data: self._loading, 3263 onSuccess: callback, 3264 onFailure: self._onFailure, 3265 onTimeout: self._onTimeout, 3266 insertBefore: self.insertBefore, 3267 charset: self.charset, 3268 timeout: self.timeout, 3269 scope: self 3270 }); 3271 } 3272 }; 3273 3274 // load the css first 3275 // YAHOO.log('combining css: ' + css); 3276 if (css.length > startLen) { 3277 YAHOO.util.Get.css(this._filter(css), { 3278 data: this._loading, 3279 onSuccess: loadScript, 3280 onFailure: this._onFailure, 3281 onTimeout: this._onTimeout, 3282 insertBefore: this.insertBefore, 3283 charset: this.charset, 3284 timeout: this.timeout, 3285 scope: self 3286 }); 3287 } else { 3288 loadScript(); 3289 } 3290 3291 return; 3292 3293 } else { 3294 // this._combineComplete = true; 3295 this.loadNext(this._loading); 3296 } 3297 }, 3298 3299 /** 3300 * inserts the requested modules and their dependencies. 3301 * <code>type</code> can be "js" or "css". Both script and 3302 * css are inserted if type is not provided. 3303 * @method insert 3304 * @param o optional options object 3305 * @param type {string} the type of dependency to insert 3306 */ 3307 insert: function(o, type) { 3308 // if (o) { 3309 // Y.log("insert: " + lang.dump(o, 1) + ", " + type); 3310 // } else { 3311 // Y.log("insert: " + this.toString() + ", " + type); 3312 // } 3313 3314 // build the dependency list 3315 this.calculate(o); 3316 3317 3318 // set a flag to indicate the load has started 3319 this._loading = true; 3320 3321 // flag to indicate we are done with the combo service 3322 // and any additional files will need to be loaded 3323 // individually 3324 // this._combineComplete = false; 3325 3326 // keep the loadType (js, css or undefined) cached 3327 this.loadType = type; 3328 3329 if (this.combine) { 3330 return this._combine(); 3331 } 3332 3333 if (!type) { 3334 // Y.log("trying to load css first"); 3335 var self = this; 3336 this._internalCallback = function() { 3337 self._internalCallback = null; 3338 self.insert(null, "js"); 3339 }; 3340 this.insert(null, "css"); 3341 return; 3342 } 3343 3344 3345 // start the load 3346 this.loadNext(); 3347 3348 }, 3349 3350 /** 3351 * Interns the script for the requested modules. The callback is 3352 * provided a reference to the sandboxed YAHOO object. This only 3353 * applies to the script: css can not be sandboxed; css will be 3354 * loaded into the page normally if specified. 3355 * @method sandbox 3356 * @param callback {Function} the callback to exectued when the load is 3357 * complete. 3358 */ 3359 sandbox: function(o, type) { 3360 // if (o) { 3361 // YAHOO.log("sandbox: " + lang.dump(o, 1) + ", " + type); 3362 // } else { 3363 // YAHOO.log("sandbox: " + this.toString() + ", " + type); 3364 // } 3365 3366 this._config(o); 3367 3368 if (!this.onSuccess) { 3369 throw new Error("You must supply an onSuccess handler for your sandbox"); 3370 } 3371 3372 this._sandbox = true; 3373 3374 var self = this; 3375 3376 // take care of any css first (this can't be sandboxed) 3377 if (!type || type !== "js") { 3378 this._internalCallback = function() { 3379 self._internalCallback = null; 3380 self.sandbox(null, "js"); 3381 }; 3382 this.insert(null, "css"); 3383 return; 3384 } 3385 3386 // get the connection manager if not on the page 3387 if (!util.Connect) { 3388 // get a new loader instance to load connection. 3389 var ld = new YAHOO.util.YUILoader(); 3390 ld.insert({ 3391 base: this.base, 3392 filter: this.filter, 3393 require: "connection", 3394 insertBefore: this.insertBefore, 3395 charset: this.charset, 3396 onSuccess: function() { 3397 this.sandbox(null, "js"); 3398 }, 3399 scope: this 3400 }, "js"); 3401 return; 3402 } 3403 3404 this._scriptText = []; 3405 this._loadCount = 0; 3406 this._stopCount = this.sorted.length; 3407 this._xhr = []; 3408 3409 this.calculate(); 3410 3411 var s=this.sorted, l=s.length, i, m, url; 3412 3413 for (i=0; i<l; i=i+1) { 3414 m = this.moduleInfo[s[i]]; 3415 3416 // undefined modules cause a failure 3417 if (!m) { 3418 this._onFailure("undefined module " + m); 3419 for (var j=0;j<this._xhr.length;j=j+1) { 3420 this._xhr[j].abort(); 3421 } 3422 return; 3423 } 3424 3425 // css files should be done 3426 if (m.type !== "js") { 3427 this._loadCount++; 3428 continue; 3429 } 3430 3431 url = m.fullpath; 3432 url = (url) ? this._filter(url) : this._url(m.path); 3433 3434 // YAHOO.log("xhr request: " + url + ", " + i); 3435 3436 var xhrData = { 3437 3438 success: function(o) { 3439 3440 var idx=o.argument[0], name=o.argument[2]; 3441 3442 // store the response in the position it was requested 3443 this._scriptText[idx] = o.responseText; 3444 3445 // YAHOO.log("received: " + o.responseText.substr(0, 100) + ", " + idx); 3446 3447 if (this.onProgress) { 3448 this.onProgress.call(this.scope, { 3449 name: name, 3450 scriptText: o.responseText, 3451 xhrResponse: o, 3452 data: this.data 3453 }); 3454 } 3455 3456 // only generate the sandbox once everything is loaded 3457 this._loadCount++; 3458 3459 if (this._loadCount >= this._stopCount) { 3460 3461 // the variable to find 3462 var v = this.varName || "YAHOO"; 3463 3464 // wrap the contents of the requested modules in an anonymous function 3465 var t = "(function() {\n"; 3466 3467 // return the locally scoped reference. 3468 var b = "\nreturn " + v + ";\n})();"; 3469 3470 var ref = eval(t + this._scriptText.join("\n") + b); 3471 3472 this._pushEvents(ref); 3473 3474 if (ref) { 3475 this.onSuccess.call(this.scope, { 3476 reference: ref, 3477 data: this.data 3478 }); 3479 } else { 3480 this._onFailure.call(this.varName + " reference failure"); 3481 } 3482 } 3483 }, 3484 3485 failure: function(o) { 3486 this.onFailure.call(this.scope, { 3487 msg: "XHR failure", 3488 xhrResponse: o, 3489 data: this.data 3490 }); 3491 }, 3492 3493 scope: this, 3494 3495 // module index, module name, sandbox name 3496 argument: [i, url, s[i]] 3497 3498 }; 3499 3500 this._xhr.push(util.Connect.asyncRequest('GET', url, xhrData)); 3501 } 3502 }, 3503 3504 /** 3505 * Executed every time a module is loaded, and if we are in a load 3506 * cycle, we attempt to load the next script. Public so that it 3507 * is possible to call this if using a method other than 3508 * YAHOO.register to determine when scripts are fully loaded 3509 * @method loadNext 3510 * @param mname {string} optional the name of the module that has 3511 * been loaded (which is usually why it is time to load the next 3512 * one) 3513 */ 3514 loadNext: function(mname) { 3515 3516 // It is possible that this function is executed due to something 3517 // else one the page loading a YUI module. Only react when we 3518 // are actively loading something 3519 if (!this._loading) { 3520 return; 3521 } 3522 3523 3524 if (mname) { 3525 3526 // if the module that was just loaded isn't what we were expecting, 3527 // continue to wait 3528 if (mname !== this._loading) { 3529 return; 3530 } 3531 3532 // YAHOO.log("loadNext executing, just loaded " + mname); 3533 3534 // The global handler that is called when each module is loaded 3535 // will pass that module name to this function. Storing this 3536 // data to avoid loading the same module multiple times 3537 this.inserted[mname] = true; 3538 3539 if (this.onProgress) { 3540 this.onProgress.call(this.scope, { 3541 name: mname, 3542 data: this.data 3543 }); 3544 } 3545 //var o = this.getProvides(mname); 3546 //this.inserted = lang.merge(this.inserted, o); 3547 } 3548 3549 var s=this.sorted, len=s.length, i, m; 3550 3551 for (i=0; i<len; i=i+1) { 3552 3553 // This.inserted keeps track of what the loader has loaded 3554 if (s[i] in this.inserted) { 3555 // YAHOO.log(s[i] + " alread loaded "); 3556 continue; 3557 } 3558 3559 // Because rollups will cause multiple load notifications 3560 // from YAHOO, loadNext may be called multiple times for 3561 // the same module when loading a rollup. We can safely 3562 // skip the subsequent requests 3563 if (s[i] === this._loading) { 3564 // YAHOO.log("still loading " + s[i] + ", waiting"); 3565 return; 3566 } 3567 3568 // log("inserting " + s[i]); 3569 m = this.moduleInfo[s[i]]; 3570 3571 if (!m) { 3572 this.onFailure.call(this.scope, { 3573 msg: "undefined module " + m, 3574 data: this.data 3575 }); 3576 return; 3577 } 3578 3579 // The load type is stored to offer the possibility to load 3580 // the css separately from the script. 3581 if (!this.loadType || this.loadType === m.type) { 3582 this._loading = s[i]; 3583 //YAHOO.log("attempting to load " + s[i] + ", " + this.base); 3584 3585 var fn=(m.type === "css") ? util.Get.css : util.Get.script, 3586 url = m.fullpath, 3587 self=this, 3588 c=function(o) { 3589 self.loadNext(o.data); 3590 }; 3591 3592 url = (url) ? this._filter(url) : this._url(m.path); 3593 3594 // safari 2.x or lower, script, and part of YUI 3595 if (env.ua.webkit && env.ua.webkit < 420 && m.type === "js" && 3596 !m.varName) { 3597 //YUI.info.moduleInfo[s[i]]) { 3598 //YAHOO.log("using YAHOO env " + s[i] + ", " + m.varName); 3599 c = null; 3600 this._useYahooListener = true; 3601 } 3602 3603 fn(url, { 3604 data: s[i], 3605 onSuccess: c, 3606 onFailure: this._onFailure, 3607 onTimeout: this._onTimeout, 3608 insertBefore: this.insertBefore, 3609 charset: this.charset, 3610 timeout: this.timeout, 3611 varName: m.varName, 3612 scope: self 3613 }); 3614 3615 return; 3616 } 3617 } 3618 3619 // we are finished 3620 this._loading = null; 3621 3622 // internal callback for loading css first 3623 if (this._internalCallback) { 3624 var f = this._internalCallback; 3625 this._internalCallback = null; 3626 f.call(this); 3627 } else if (this.onSuccess) { 3628 this._pushEvents(); 3629 this.onSuccess.call(this.scope, { 3630 data: this.data 3631 }); 3632 } 3633 3634 }, 3635 3636 /** 3637 * In IE, the onAvailable/onDOMReady events need help when Event is 3638 * loaded dynamically 3639 * @method _pushEvents 3640 * @param {Function} optional function reference 3641 * @private 3642 */ 3643 _pushEvents: function(ref) { 3644 var r = ref || YAHOO; 3645 if (r.util && r.util.Event) { 3646 r.util.Event._load(); 3647 } 3648 }, 3649 3650 /** 3651 * Applies filter 3652 * method _filter 3653 * @return {string} the filtered string 3654 * @private 3655 */ 3656 _filter: function(str) { 3657 var f = this.filter; 3658 return (f) ? str.replace(new RegExp(f.searchExp), f.replaceStr) : str; 3659 }, 3660 3661 /** 3662 * Generates the full url for a module 3663 * method _url 3664 * @param path {string} the path fragment 3665 * @return {string} the full url 3666 * @private 3667 */ 3668 _url: function(path) { 3669 3670 var u = this.base || "", f=this.filter; 3671 u = u + path; 3672 return this._filter(u); 3673 } 3674 3675 }; 3676 3677 })();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |