[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/yui/yuiloader/ -> yuiloader-debug.js (source)

   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           * &nbsp;&nbsp;YAHOO.util.Get.script(
1628           * &nbsp;&nbsp;["http://yui.yahooapis.com/2.3.1/build/dragdrop/dragdrop-min.js",
1629           * &nbsp;&nbsp;&nbsp;"http://yui.yahooapis.com/2.3.1/build/animation/animation-min.js"], &#123;
1630           * &nbsp;&nbsp;&nbsp;&nbsp;onSuccess: function(o) &#123;
1631           * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new YAHOO.util.DDProxy("dd1"); // also new o.reference("dd1"); would work
1632           * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.log("won't cause error because YAHOO is the scope");
1633           * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.log(o.nodes.length === 2) // true
1634           * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// o.purge(); // optionally remove the script nodes immediately
1635           * &nbsp;&nbsp;&nbsp;&nbsp;&#125;,
1636           * &nbsp;&nbsp;&nbsp;&nbsp;onFailure: function(o) &#123;
1637           * &nbsp;&nbsp;&nbsp;&nbsp;&#125;,
1638           * &nbsp;&nbsp;&nbsp;&nbsp;data: "foo",
1639           * &nbsp;&nbsp;&nbsp;&nbsp;timeout: 10000, // 10 second timeout
1640           * &nbsp;&nbsp;&nbsp;&nbsp;scope: YAHOO,
1641           * &nbsp;&nbsp;&nbsp;&nbsp;// win: otherframe // target another window/frame
1642           * &nbsp;&nbsp;&nbsp;&nbsp;autopurge: true // allow the utility to choose when to remove the nodes
1643           * &nbsp;&nbsp;&#125;);
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: &#123; 
2332           *      'searchExp': "-min\\.js", 
2333           *      'replaceStr': "-debug.js"
2334           *  &#125;
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  })();


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7