[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/2in3/2.9.0/build/yui2-event/ -> yui2-event.js (source)

   1  YUI.add('yui2-event', function(Y) {
   2      var YAHOO    = Y.YUI2;
   3      /*
   4  Copyright (c) 2011, Yahoo! Inc. All rights reserved.
   5  Code licensed under the BSD License:
   6  http://developer.yahoo.com/yui/license.html
   7  version: 2.9.0
   8  */
   9  
  10  /**
  11   * The CustomEvent class lets you define events for your application
  12   * that can be subscribed to by one or more independent component.
  13   *
  14   * @param {String}  type The type of event, which is passed to the callback
  15   *                  when the event fires
  16   * @param {Object}  context The context the event will fire from.  "this" will
  17   *                  refer to this object in the callback.  Default value:
  18   *                  the window object.  The listener can override this.
  19   * @param {boolean} silent pass true to prevent the event from writing to
  20   *                  the debugsystem
  21   * @param {int}     signature the signature that the custom event subscriber
  22   *                  will receive. YAHOO.util.CustomEvent.LIST or
  23   *                  YAHOO.util.CustomEvent.FLAT.  The default is
  24   *                  YAHOO.util.CustomEvent.LIST.
  25   * @param fireOnce {boolean} If configured to fire once, the custom event
  26   * will only notify subscribers a single time regardless of how many times
  27   * the event is fired.  In addition, new subscribers will be notified
  28   * immediately if the event has already been fired.
  29   * @namespace YAHOO.util
  30   * @class CustomEvent
  31   * @constructor
  32   */
  33  YAHOO.util.CustomEvent = function(type, context, silent, signature, fireOnce) {
  34  
  35      /**
  36       * The type of event, returned to subscribers when the event fires
  37       * @property type
  38       * @type string
  39       */
  40      this.type = type;
  41  
  42      /**
  43       * The context the event will fire from by default. Defaults to the window obj.
  44       * @property scope
  45       * @type object
  46       */
  47      this.scope = context || window;
  48  
  49      /**
  50       * By default all custom events are logged in the debug build. Set silent to true
  51       * to disable debug output for this event.
  52       * @property silent
  53       * @type boolean
  54       */
  55      this.silent = silent;
  56  
  57      /**
  58       * If configured to fire once, the custom event will only notify subscribers
  59       * a single time regardless of how many times the event is fired.  In addition,
  60       * new subscribers will be notified immediately if the event has already been
  61       * fired.
  62       * @property fireOnce
  63       * @type boolean
  64       * @default false
  65       */
  66      this.fireOnce = fireOnce;
  67  
  68      /**
  69       * Indicates whether or not this event has ever been fired.
  70       * @property fired
  71       * @type boolean
  72       * @default false
  73       */
  74      this.fired = false;
  75  
  76      /**
  77       * For fireOnce events the arguments the event was fired with are stored
  78       * so that new subscribers get the proper payload.
  79       * @property firedWith
  80       * @type Array
  81       */
  82      this.firedWith = null;
  83  
  84      /**
  85       * Custom events support two styles of arguments provided to the event
  86       * subscribers.
  87       * <ul>
  88       * <li>YAHOO.util.CustomEvent.LIST:
  89       *   <ul>
  90       *   <li>param1: event name</li>
  91       *   <li>param2: array of arguments sent to fire</li>
  92       *   <li>param3: <optional> a custom object supplied by the subscriber</li>
  93       *   </ul>
  94       * </li>
  95       * <li>YAHOO.util.CustomEvent.FLAT
  96       *   <ul>
  97       *   <li>param1: the first argument passed to fire.  If you need to
  98       *           pass multiple parameters, use and array or object literal</li>
  99       *   <li>param2: <optional> a custom object supplied by the subscriber</li>
 100       *   </ul>
 101       * </li>
 102       * </ul>
 103       *   @property signature
 104       *   @type int
 105       */
 106      this.signature = signature || YAHOO.util.CustomEvent.LIST;
 107  
 108      /**
 109       * The subscribers to this event
 110       * @property subscribers
 111       * @type Subscriber[]
 112       */
 113      this.subscribers = [];
 114  
 115      if (!this.silent) {
 116      }
 117  
 118      var onsubscribeType = "_YUICEOnSubscribe";
 119  
 120      // Only add subscribe events for events that are not generated by
 121      // CustomEvent
 122      if (type !== onsubscribeType) {
 123  
 124          /**
 125           * Custom events provide a custom event that fires whenever there is
 126           * a new subscriber to the event.  This provides an opportunity to
 127           * handle the case where there is a non-repeating event that has
 128           * already fired has a new subscriber.
 129           *
 130           * @event subscribeEvent
 131           * @type YAHOO.util.CustomEvent
 132           * @param fn {Function} The function to execute
 133           * @param obj <Object> An object to be passed along when the event fires.
 134           * Defaults to the custom event.
 135           * @param override <boolean|Object> If true, the obj passed in becomes the
 136           * execution context of the listener. If an object, that object becomes
 137           * the execution context. Defaults to the custom event.
 138           */
 139          this.subscribeEvent =
 140                  new YAHOO.util.CustomEvent(onsubscribeType, this, true);
 141  
 142      }
 143  
 144  
 145      /**
 146       * In order to make it possible to execute the rest of the subscriber
 147       * stack when one thows an exception, the subscribers exceptions are
 148       * caught.  The most recent exception is stored in this property
 149       * @property lastError
 150       * @type Error
 151       */
 152      this.lastError = null;
 153  };
 154  
 155  /**
 156   * Subscriber listener sigature constant.  The LIST type returns three
 157   * parameters: the event type, the array of args passed to fire, and
 158   * the optional custom object
 159   * @property YAHOO.util.CustomEvent.LIST
 160   * @static
 161   * @type int
 162   */
 163  YAHOO.util.CustomEvent.LIST = 0;
 164  
 165  /**
 166   * Subscriber listener sigature constant.  The FLAT type returns two
 167   * parameters: the first argument passed to fire and the optional
 168   * custom object
 169   * @property YAHOO.util.CustomEvent.FLAT
 170   * @static
 171   * @type int
 172   */
 173  YAHOO.util.CustomEvent.FLAT = 1;
 174  
 175  YAHOO.util.CustomEvent.prototype = {
 176  
 177      /**
 178       * Subscribes the caller to this event
 179       * @method subscribe
 180       * @param {Function} fn        The function to execute
 181       * @param {Object}   obj       An object to be passed along when the event
 182       * fires.
 183       * @param {boolean|Object} overrideContext If true, the obj passed in
 184       * becomes the execution.
 185       * context of the listener. If an object, that object becomes the execution
 186       * context.
 187       */
 188      subscribe: function(fn, obj, overrideContext) {
 189  
 190          if (!fn) {
 191  throw new Error("Invalid callback for subscriber to '" + this.type + "'");
 192          }
 193  
 194          if (this.subscribeEvent) {
 195              this.subscribeEvent.fire(fn, obj, overrideContext);
 196          }
 197  
 198          var s = new YAHOO.util.Subscriber(fn, obj, overrideContext);
 199  
 200          if (this.fireOnce && this.fired) {
 201              this.notify(s, this.firedWith);
 202          } else {
 203              this.subscribers.push(s);
 204          }
 205      },
 206  
 207      /**
 208       * Unsubscribes subscribers.
 209       * @method unsubscribe
 210       * @param {Function} fn  The subscribed function to remove, if not supplied
 211       *                       all will be removed
 212       * @param {Object}   obj  The custom object passed to subscribe.  This is
 213       *                        optional, but if supplied will be used to
 214       *                        disambiguate multiple listeners that are the same
 215       *                        (e.g., you subscribe many object using a function
 216       *                        that lives on the prototype)
 217       * @return {boolean} True if the subscriber was found and detached.
 218       */
 219      unsubscribe: function(fn, obj) {
 220  
 221          if (!fn) {
 222              return this.unsubscribeAll();
 223          }
 224  
 225          var found = false;
 226          for (var i=0, len=this.subscribers.length; i<len; ++i) {
 227              var s = this.subscribers[i];
 228              if (s && s.contains(fn, obj)) {
 229                  this._delete(i);
 230                  found = true;
 231              }
 232          }
 233  
 234          return found;
 235      },
 236  
 237      /**
 238       * Notifies the subscribers.  The callback functions will be executed
 239       * from the context specified when the event was created, and with the
 240       * following parameters:
 241       *   <ul>
 242       *   <li>The type of event</li>
 243       *   <li>All of the arguments fire() was executed with as an array</li>
 244       *   <li>The custom object (if any) that was passed into the subscribe()
 245       *       method</li>
 246       *   </ul>
 247       * @method fire
 248       * @param {Object*} arguments an arbitrary set of parameters to pass to
 249       *                            the handler.
 250       * @return {boolean} false if one of the subscribers returned false,
 251       *                   true otherwise
 252       */
 253      fire: function() {
 254  
 255          this.lastError = null;
 256  
 257          var errors = [],
 258              len=this.subscribers.length;
 259  
 260  
 261          var args=[].slice.call(arguments, 0), ret=true, i, rebuild=false;
 262  
 263          if (this.fireOnce) {
 264              if (this.fired) {
 265                  return true;
 266              } else {
 267                  this.firedWith = args;
 268              }
 269          }
 270  
 271          this.fired = true;
 272  
 273          if (!len && this.silent) {
 274              return true;
 275          }
 276  
 277          if (!this.silent) {
 278          }
 279  
 280          // make a copy of the subscribers so that there are
 281          // no index problems if one subscriber removes another.
 282          var subs = this.subscribers.slice();
 283  
 284          for (i=0; i<len; ++i) {
 285              var s = subs[i];
 286              if (!s || !s.fn) {
 287                  rebuild=true;
 288              } else {
 289  
 290                  ret = this.notify(s, args);
 291  
 292                  if (false === ret) {
 293                      if (!this.silent) {
 294                      }
 295  
 296                      break;
 297                  }
 298              }
 299          }
 300  
 301          return (ret !== false);
 302      },
 303  
 304      notify: function(s, args) {
 305  
 306          var ret, param=null, scope = s.getScope(this.scope),
 307                   throwErrors = YAHOO.util.Event.throwErrors;
 308  
 309          if (!this.silent) {
 310          }
 311  
 312          if (this.signature == YAHOO.util.CustomEvent.FLAT) {
 313  
 314              if (args.length > 0) {
 315                  param = args[0];
 316              }
 317  
 318              try {
 319                  ret = s.fn.call(scope, param, s.obj);
 320              } catch(e) {
 321                  this.lastError = e;
 322                  // errors.push(e);
 323                  if (throwErrors) {
 324                      throw e;
 325                  }
 326              }
 327          } else {
 328              try {
 329                  ret = s.fn.call(scope, this.type, args, s.obj);
 330              } catch(ex) {
 331                  this.lastError = ex;
 332                  if (throwErrors) {
 333                      throw ex;
 334                  }
 335              }
 336          }
 337  
 338          return ret;
 339      },
 340  
 341      /**
 342       * Removes all listeners
 343       * @method unsubscribeAll
 344       * @return {int} The number of listeners unsubscribed
 345       */
 346      unsubscribeAll: function() {
 347          var l = this.subscribers.length, i;
 348          for (i=l-1; i>-1; i--) {
 349              this._delete(i);
 350          }
 351  
 352          this.subscribers=[];
 353  
 354          return l;
 355      },
 356  
 357      /**
 358       * @method _delete
 359       * @private
 360       */
 361      _delete: function(index) {
 362          var s = this.subscribers[index];
 363          if (s) {
 364              delete s.fn;
 365              delete s.obj;
 366          }
 367  
 368          // this.subscribers[index]=null;
 369          this.subscribers.splice(index, 1);
 370      },
 371  
 372      /**
 373       * @method toString
 374       */
 375      toString: function() {
 376           return "CustomEvent: " + "'" + this.type  + "', " +
 377               "context: " + this.scope;
 378  
 379      }
 380  };
 381  
 382  /////////////////////////////////////////////////////////////////////
 383  
 384  /**
 385   * Stores the subscriber information to be used when the event fires.
 386   * @param {Function} fn       The function to execute
 387   * @param {Object}   obj      An object to be passed along when the event fires
 388   * @param {boolean}  overrideContext If true, the obj passed in becomes the execution
 389   *                            context of the listener
 390   * @class Subscriber
 391   * @constructor
 392   */
 393  YAHOO.util.Subscriber = function(fn, obj, overrideContext) {
 394  
 395      /**
 396       * The callback that will be execute when the event fires
 397       * @property fn
 398       * @type function
 399       */
 400      this.fn = fn;
 401  
 402      /**
 403       * An optional custom object that will passed to the callback when
 404       * the event fires
 405       * @property obj
 406       * @type object
 407       */
 408      this.obj = YAHOO.lang.isUndefined(obj) ? null : obj;
 409  
 410      /**
 411       * The default execution context for the event listener is defined when the
 412       * event is created (usually the object which contains the event).
 413       * By setting overrideContext to true, the execution context becomes the custom
 414       * object passed in by the subscriber.  If overrideContext is an object, that
 415       * object becomes the context.
 416       * @property overrideContext
 417       * @type boolean|object
 418       */
 419      this.overrideContext = overrideContext;
 420  
 421  };
 422  
 423  /**
 424   * Returns the execution context for this listener.  If overrideContext was set to true
 425   * the custom obj will be the context.  If overrideContext is an object, that is the
 426   * context, otherwise the default context will be used.
 427   * @method getScope
 428   * @param {Object} defaultScope the context to use if this listener does not
 429   *                              override it.
 430   */
 431  YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) {
 432      if (this.overrideContext) {
 433          if (this.overrideContext === true) {
 434              return this.obj;
 435          } else {
 436              return this.overrideContext;
 437          }
 438      }
 439      return defaultScope;
 440  };
 441  
 442  /**
 443   * Returns true if the fn and obj match this objects properties.
 444   * Used by the unsubscribe method to match the right subscriber.
 445   *
 446   * @method contains
 447   * @param {Function} fn the function to execute
 448   * @param {Object} obj an object to be passed along when the event fires
 449   * @return {boolean} true if the supplied arguments match this
 450   *                   subscriber's signature.
 451   */
 452  YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {
 453      if (obj) {
 454          return (this.fn == fn && this.obj == obj);
 455      } else {
 456          return (this.fn == fn);
 457      }
 458  };
 459  
 460  /**
 461   * @method toString
 462   */
 463  YAHOO.util.Subscriber.prototype.toString = function() {
 464      return "Subscriber { obj: " + this.obj  +
 465             ", overrideContext: " +  (this.overrideContext || "no") + " }";
 466  };
 467  
 468  /**
 469   * The Event Utility provides utilities for managing DOM Events and tools
 470   * for building event systems
 471   *
 472   * @module event
 473   * @title Event Utility
 474   * @namespace YAHOO.util
 475   * @requires yahoo
 476   */
 477  
 478  // The first instance of Event will win if it is loaded more than once.
 479  // @TODO this needs to be changed so that only the state data that needs to
 480  // be preserved is kept, while methods are overwritten/added as needed.
 481  // This means that the module pattern can't be used.
 482  if (!YAHOO.util.Event) {
 483  
 484  /**
 485   * The event utility provides functions to add and remove event listeners,
 486   * event cleansing.  It also tries to automatically remove listeners it
 487   * registers during the unload event.
 488   *
 489   * @class Event
 490   * @static
 491   */
 492      YAHOO.util.Event = function() {
 493  
 494          /**
 495           * True after the onload event has fired
 496           * @property loadComplete
 497           * @type boolean
 498           * @static
 499           * @private
 500           */
 501          var loadComplete =  false,
 502  
 503          /**
 504           * Cache of wrapped listeners
 505           * @property listeners
 506           * @type array
 507           * @static
 508           * @private
 509           */
 510          listeners = [],
 511  
 512  
 513          /**
 514           * User-defined unload function that will be fired before all events
 515           * are detached
 516           * @property unloadListeners
 517           * @type array
 518           * @static
 519           * @private
 520           */
 521          unloadListeners = [],
 522  
 523          /**
 524           * The number of times to poll after window.onload.  This number is
 525           * increased if additional late-bound handlers are requested after
 526           * the page load.
 527           * @property retryCount
 528           * @static
 529           * @private
 530           */
 531          retryCount = 0,
 532  
 533          /**
 534           * onAvailable listeners
 535           * @property onAvailStack
 536           * @static
 537           * @private
 538           */
 539          onAvailStack = [],
 540  
 541          /**
 542           * Counter for auto id generation
 543           * @property counter
 544           * @static
 545           * @private
 546           */
 547          counter = 0,
 548  
 549          /**
 550           * Normalized keycodes for webkit/safari
 551           * @property webkitKeymap
 552           * @type {int: int}
 553           * @private
 554           * @static
 555           * @final
 556           */
 557           webkitKeymap = {
 558              63232: 38, // up
 559              63233: 40, // down
 560              63234: 37, // left
 561              63235: 39, // right
 562              63276: 33, // page up
 563              63277: 34, // page down
 564              25: 9      // SHIFT-TAB (Safari provides a different key code in
 565                         // this case, even though the shiftKey modifier is set)
 566          },
 567  
 568          isIE = YAHOO.env.ua.ie,
 569  
 570          // String constants used by the addFocusListener and removeFocusListener methods
 571  
 572          FOCUSIN = "focusin",
 573          FOCUSOUT = "focusout";
 574  
 575          return {
 576  
 577              /**
 578               * The number of times we should look for elements that are not
 579               * in the DOM at the time the event is requested after the document
 580               * has been loaded.  The default is 500@amp;40 ms, so it will poll
 581               * for 20 seconds or until all outstanding handlers are bound
 582               * (whichever comes first).
 583               * @property POLL_RETRYS
 584               * @type int
 585               * @static
 586               * @final
 587               */
 588              POLL_RETRYS: 500,
 589  
 590              /**
 591               * The poll interval in milliseconds
 592               * @property POLL_INTERVAL
 593               * @type int
 594               * @static
 595               * @final
 596               */
 597              POLL_INTERVAL: 40,
 598  
 599              /**
 600               * Element to bind, int constant
 601               * @property EL
 602               * @type int
 603               * @static
 604               * @final
 605               */
 606              EL: 0,
 607  
 608              /**
 609               * Type of event, int constant
 610               * @property TYPE
 611               * @type int
 612               * @static
 613               * @final
 614               */
 615              TYPE: 1,
 616  
 617              /**
 618               * Function to execute, int constant
 619               * @property FN
 620               * @type int
 621               * @static
 622               * @final
 623               */
 624              FN: 2,
 625  
 626              /**
 627               * Function wrapped for context correction and cleanup, int constant
 628               * @property WFN
 629               * @type int
 630               * @static
 631               * @final
 632               */
 633              WFN: 3,
 634  
 635              /**
 636               * Object passed in by the user that will be returned as a
 637               * parameter to the callback, int constant.  Specific to
 638               * unload listeners
 639               * @property OBJ
 640               * @type int
 641               * @static
 642               * @final
 643               */
 644              UNLOAD_OBJ: 3,
 645  
 646              /**
 647               * Adjusted context, either the element we are registering the event
 648               * on or the custom object passed in by the listener, int constant
 649               * @property ADJ_SCOPE
 650               * @type int
 651               * @static
 652               * @final
 653               */
 654              ADJ_SCOPE: 4,
 655  
 656              /**
 657               * The original obj passed into addListener
 658               * @property OBJ
 659               * @type int
 660               * @static
 661               * @final
 662               */
 663              OBJ: 5,
 664  
 665              /**
 666               * The original context parameter passed into addListener
 667               * @property OVERRIDE
 668               * @type int
 669               * @static
 670               * @final
 671               */
 672              OVERRIDE: 6,
 673  
 674              /**
 675               * The original capture parameter passed into addListener
 676               * @property CAPTURE
 677               * @type int
 678               * @static
 679               * @final
 680               */
 681              CAPTURE: 7,
 682  
 683              /**
 684               * addListener/removeListener can throw errors in unexpected scenarios.
 685               * These errors are suppressed, the method returns false, and this property
 686               * is set
 687               * @property lastError
 688               * @static
 689               * @type Error
 690               */
 691              lastError: null,
 692  
 693              /**
 694               * Safari detection
 695               * @property isSafari
 696               * @private
 697               * @static
 698               * @deprecated use YAHOO.env.ua.webkit
 699               */
 700              isSafari: YAHOO.env.ua.webkit,
 701  
 702              /**
 703               * webkit version
 704               * @property webkit
 705               * @type string
 706               * @private
 707               * @static
 708               * @deprecated use YAHOO.env.ua.webkit
 709               */
 710              webkit: YAHOO.env.ua.webkit,
 711  
 712              /**
 713               * IE detection
 714               * @property isIE
 715               * @private
 716               * @static
 717               * @deprecated use YAHOO.env.ua.ie
 718               */
 719              isIE: isIE,
 720  
 721              /**
 722               * poll handle
 723               * @property _interval
 724               * @static
 725               * @private
 726               */
 727              _interval: null,
 728  
 729              /**
 730               * document readystate poll handle
 731               * @property _dri
 732               * @static
 733               * @private
 734               */
 735               _dri: null,
 736  
 737  
 738              /**
 739               * Map of special event types
 740               * @property _specialTypes
 741               * @static
 742               * @private
 743               */
 744              _specialTypes: {
 745                  focusin: (isIE ? "focusin" : "focus"),
 746                  focusout: (isIE ? "focusout" : "blur")
 747              },
 748  
 749  
 750              /**
 751               * True when the document is initially usable
 752               * @property DOMReady
 753               * @type boolean
 754               * @static
 755               */
 756              DOMReady: false,
 757  
 758              /**
 759               * Errors thrown by subscribers of custom events are caught
 760               * and the error message is written to the debug console.  If
 761               * this property is set to true, it will also re-throw the
 762               * error.
 763               * @property throwErrors
 764               * @type boolean
 765               * @default false
 766               */
 767              throwErrors: false,
 768  
 769  
 770              /**
 771               * @method startInterval
 772               * @static
 773               * @private
 774               */
 775              startInterval: function() {
 776                  if (!this._interval) {
 777                      // var self = this;
 778                      // var callback = function() { self._tryPreloadAttach(); };
 779                      // this._interval = setInterval(callback, this.POLL_INTERVAL);
 780                      this._interval = YAHOO.lang.later(this.POLL_INTERVAL, this, this._tryPreloadAttach, null, true);
 781                  }
 782              },
 783  
 784              /**
 785               * Executes the supplied callback when the item with the supplied
 786               * id is found.  This is meant to be used to execute behavior as
 787               * soon as possible as the page loads.  If you use this after the
 788               * initial page load it will poll for a fixed time for the element.
 789               * The number of times it will poll and the frequency are
 790               * configurable.  By default it will poll for 10 seconds.
 791               *
 792               * <p>The callback is executed with a single parameter:
 793               * the custom object parameter, if provided.</p>
 794               *
 795               * @method onAvailable
 796               *
 797               * @param {string||string[]}   id the id of the element, or an array
 798               * of ids to look for.
 799               * @param {function} fn what to execute when the element is found.
 800               * @param {object}   obj an optional object to be passed back as
 801               *                   a parameter to fn.
 802               * @param {boolean|object}  overrideContext If set to true, fn will execute
 803               *                   in the context of obj, if set to an object it
 804               *                   will execute in the context of that object
 805               * @param checkContent {boolean} check child node readiness (onContentReady)
 806               * @static
 807               */
 808              onAvailable: function(id, fn, obj, overrideContext, checkContent) {
 809  
 810                  var a = (YAHOO.lang.isString(id)) ? [id] : id;
 811  
 812                  for (var i=0; i<a.length; i=i+1) {
 813                      onAvailStack.push({id:         a[i],
 814                                         fn:         fn,
 815                                         obj:        obj,
 816                                         overrideContext:   overrideContext,
 817                                         checkReady: checkContent });
 818                  }
 819  
 820                  retryCount = this.POLL_RETRYS;
 821  
 822                  this.startInterval();
 823              },
 824  
 825              /**
 826               * Works the same way as onAvailable, but additionally checks the
 827               * state of sibling elements to determine if the content of the
 828               * available element is safe to modify.
 829               *
 830               * <p>The callback is executed with a single parameter:
 831               * the custom object parameter, if provided.</p>
 832               *
 833               * @method onContentReady
 834               *
 835               * @param {string}   id the id of the element to look for.
 836               * @param {function} fn what to execute when the element is ready.
 837               * @param {object}   obj an optional object to be passed back as
 838               *                   a parameter to fn.
 839               * @param {boolean|object}  overrideContext If set to true, fn will execute
 840               *                   in the context of obj.  If an object, fn will
 841               *                   exectute in the context of that object
 842               *
 843               * @static
 844               */
 845              onContentReady: function(id, fn, obj, overrideContext) {
 846                  this.onAvailable(id, fn, obj, overrideContext, true);
 847              },
 848  
 849              /**
 850               * Executes the supplied callback when the DOM is first usable.  This
 851               * will execute immediately if called after the DOMReady event has
 852               * fired.   @todo the DOMContentReady event does not fire when the
 853               * script is dynamically injected into the page.  This means the
 854               * DOMReady custom event will never fire in FireFox or Opera when the
 855               * library is injected.  It _will_ fire in Safari, and the IE
 856               * implementation would allow for us to fire it if the defered script
 857               * is not available.  We want this to behave the same in all browsers.
 858               * Is there a way to identify when the script has been injected
 859               * instead of included inline?  Is there a way to know whether the
 860               * window onload event has fired without having had a listener attached
 861               * to it when it did so?
 862               *
 863               * <p>The callback is a CustomEvent, so the signature is:</p>
 864               * <p>type &lt;string&gt;, args &lt;array&gt;, customobject &lt;object&gt;</p>
 865               * <p>For DOMReady events, there are no fire argments, so the
 866               * signature is:</p>
 867               * <p>"DOMReady", [], obj</p>
 868               *
 869               *
 870               * @method onDOMReady
 871               *
 872               * @param {function} fn what to execute when the element is found.
 873               * @param {object}   obj an optional object to be passed back as
 874               *                   a parameter to fn.
 875               * @param {boolean|object}  overrideContext If set to true, fn will execute
 876               *                   in the context of obj, if set to an object it
 877               *                   will execute in the context of that object
 878               *
 879               * @static
 880               */
 881              // onDOMReady: function(fn, obj, overrideContext) {
 882              onDOMReady: function() {
 883                  this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent, arguments);
 884              },
 885  
 886  
 887              /**
 888               * Appends an event handler
 889               *
 890               * @method _addListener
 891               *
 892               * @param {String|HTMLElement|Array|NodeList} el An id, an element
 893               *  reference, or a collection of ids and/or elements to assign the
 894               *  listener to.
 895               * @param {String}   sType     The type of event to append
 896               * @param {Function} fn        The method the event invokes
 897               * @param {Object}   obj    An arbitrary object that will be
 898               *                             passed as a parameter to the handler
 899               * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
 900               *                             the execution context of the listener. If an
 901               *                             object, this object becomes the execution
 902               *                             context.
 903               * @param {boolen}      capture capture or bubble phase
 904               * @return {Boolean} True if the action was successful or defered,
 905               *                        false if one or more of the elements
 906               *                        could not have the listener attached,
 907               *                        or if the operation throws an exception.
 908               * @private
 909               * @static
 910               */
 911              _addListener: function(el, sType, fn, obj, overrideContext, bCapture) {
 912  
 913                  if (!fn || !fn.call) {
 914                      return false;
 915                  }
 916  
 917                  // The el argument can be an array of elements or element ids.
 918                  if ( this._isValidCollection(el)) {
 919                      var ok = true;
 920                      for (var i=0,len=el.length; i<len; ++i) {
 921                          ok = this.on(el[i],
 922                                         sType,
 923                                         fn,
 924                                         obj,
 925                                         overrideContext) && ok;
 926                      }
 927                      return ok;
 928  
 929                  } else if (YAHOO.lang.isString(el)) {
 930                      var oEl = this.getEl(el);
 931                      // If the el argument is a string, we assume it is
 932                      // actually the id of the element.  If the page is loaded
 933                      // we convert el to the actual element, otherwise we
 934                      // defer attaching the event until onload event fires
 935  
 936                      // check to see if we need to delay hooking up the event
 937                      // until after the page loads.
 938                      if (oEl) {
 939                          el = oEl;
 940                      } else {
 941                          // defer adding the event until the element is available
 942                          this.onAvailable(el, function() {
 943                             YAHOO.util.Event._addListener(el, sType, fn, obj, overrideContext, bCapture);
 944                          });
 945  
 946                          return true;
 947                      }
 948                  }
 949  
 950                  // Element should be an html element or an array if we get
 951                  // here.
 952                  if (!el) {
 953                      return false;
 954                  }
 955  
 956                  // we need to make sure we fire registered unload events
 957                  // prior to automatically unhooking them.  So we hang on to
 958                  // these instead of attaching them to the window and fire the
 959                  // handles explicitly during our one unload event.
 960                  if ("unload" == sType && obj !== this) {
 961                      unloadListeners[unloadListeners.length] =
 962                              [el, sType, fn, obj, overrideContext];
 963                      return true;
 964                  }
 965  
 966  
 967                  // if the user chooses to override the context, we use the custom
 968                  // object passed in, otherwise the executing context will be the
 969                  // HTML element that the event is registered on
 970                  var context = el;
 971                  if (overrideContext) {
 972                      if (overrideContext === true) {
 973                          context = obj;
 974                      } else {
 975                          context = overrideContext;
 976                      }
 977                  }
 978  
 979                  // wrap the function so we can return the obj object when
 980                  // the event fires;
 981                  var wrappedFn = function(e) {
 982                          return fn.call(context, YAHOO.util.Event.getEvent(e, el),
 983                                  obj);
 984                      };
 985  
 986                  var li = [el, sType, fn, wrappedFn, context, obj, overrideContext, bCapture];
 987                  var index = listeners.length;
 988                  // cache the listener so we can try to automatically unload
 989                  listeners[index] = li;
 990  
 991                  try {
 992                      this._simpleAdd(el, sType, wrappedFn, bCapture);
 993                  } catch(ex) {
 994                      // handle an error trying to attach an event.  If it fails
 995                      // we need to clean up the cache
 996                      this.lastError = ex;
 997                      this.removeListener(el, sType, fn);
 998                      return false;
 999                  }
1000  
1001                  return true;
1002  
1003              },
1004  
1005              /**
1006               * Checks to see if the type requested is a special type
1007               * (as defined by the _specialTypes hash), and (if so) returns
1008               * the special type name.
1009               *
1010               * @method _getType
1011               *
1012               * @param {String}   sType     The type to look up
1013               * @private
1014               */
1015              _getType: function (type) {
1016  
1017                  return this._specialTypes[type] || type;
1018  
1019              },
1020  
1021  
1022              /**
1023               * Appends an event handler
1024               *
1025               * @method addListener
1026               *
1027               * @param {String|HTMLElement|Array|NodeList} el An id, an element
1028               *  reference, or a collection of ids and/or elements to assign the
1029               *  listener to.
1030               * @param {String}   sType     The type of event to append
1031               * @param {Function} fn        The method the event invokes
1032               * @param {Object}   obj    An arbitrary object that will be
1033               *                             passed as a parameter to the handler
1034               * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
1035               *                             the execution context of the listener. If an
1036               *                             object, this object becomes the execution
1037               *                             context.
1038               * @return {Boolean} True if the action was successful or defered,
1039               *                        false if one or more of the elements
1040               *                        could not have the listener attached,
1041               *                        or if the operation throws an exception.
1042               * @static
1043               */
1044              addListener: function (el, sType, fn, obj, overrideContext) {
1045  
1046                  var capture = ((sType == FOCUSIN || sType == FOCUSOUT) && !YAHOO.env.ua.ie) ? true : false;
1047  
1048                  return this._addListener(el, this._getType(sType), fn, obj, overrideContext, capture);
1049  
1050              },
1051  
1052  
1053              /**
1054               * Attaches a focusin event listener to the specified element for
1055               * the purpose of listening for the focus event on the element's
1056               * descendants.
1057               * @method addFocusListener
1058               *
1059               * @param {String|HTMLElement|Array|NodeList} el An id, an element
1060               *  reference, or a collection of ids and/or elements to assign the
1061               *  listener to.
1062               * @param {Function} fn        The method the event invokes
1063               * @param {Object}   obj    An arbitrary object that will be
1064               *                             passed as a parameter to the handler
1065               * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
1066               *                             the execution context of the listener. If an
1067               *                             object, this object becomes the execution
1068               *                             context.
1069               * @return {Boolean} True if the action was successful or defered,
1070               *                        false if one or more of the elements
1071               *                        could not have the listener attached,
1072               *                        or if the operation throws an exception.
1073               * @static
1074              * @deprecated use YAHOO.util.Event.on and specify "focusin" as the event type.
1075               */
1076              addFocusListener: function (el, fn, obj, overrideContext) {
1077                  return this.on(el, FOCUSIN, fn, obj, overrideContext);
1078              },
1079  
1080  
1081              /**
1082               * Removes a focusin event listener to the specified element for
1083               * the purpose of listening for the focus event on the element's
1084               * descendants.
1085               *
1086               * @method removeFocusListener
1087               *
1088               * @param {String|HTMLElement|Array|NodeList} el An id, an element
1089               *  reference, or a collection of ids and/or elements to remove
1090               *  the listener from.
1091               * @param {Function} fn the method the event invokes.  If fn is
1092               *  undefined, then all event handlers for the type of event are
1093               *  removed.
1094               * @return {boolean} true if the unbind was successful, false
1095               *  otherwise.
1096               * @static
1097               * @deprecated use YAHOO.util.Event.removeListener and specify "focusin" as the event type.
1098               */
1099              removeFocusListener: function (el, fn) {
1100                  return this.removeListener(el, FOCUSIN, fn);
1101              },
1102  
1103              /**
1104               * Attaches a focusout event listener to the specified element for
1105               * the purpose of listening for the blur event on the element's
1106               * descendants.
1107               *
1108               * @method addBlurListener
1109               *
1110               * @param {String|HTMLElement|Array|NodeList} el An id, an element
1111               *  reference, or a collection of ids and/or elements to assign the
1112               *  listener to.
1113               * @param {Function} fn        The method the event invokes
1114               * @param {Object}   obj    An arbitrary object that will be
1115               *                             passed as a parameter to the handler
1116               * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
1117               *                             the execution context of the listener. If an
1118               *                             object, this object becomes the execution
1119               *                             context.
1120               * @return {Boolean} True if the action was successful or defered,
1121               *                        false if one or more of the elements
1122               *                        could not have the listener attached,
1123               *                        or if the operation throws an exception.
1124               * @static
1125               * @deprecated use YAHOO.util.Event.on and specify "focusout" as the event type.
1126               */
1127              addBlurListener: function (el, fn, obj, overrideContext) {
1128                  return this.on(el, FOCUSOUT, fn, obj, overrideContext);
1129              },
1130  
1131              /**
1132               * Removes a focusout event listener to the specified element for
1133               * the purpose of listening for the blur event on the element's
1134               * descendants.
1135               *
1136               * @method removeBlurListener
1137               *
1138               * @param {String|HTMLElement|Array|NodeList} el An id, an element
1139               *  reference, or a collection of ids and/or elements to remove
1140               *  the listener from.
1141               * @param {Function} fn the method the event invokes.  If fn is
1142               *  undefined, then all event handlers for the type of event are
1143               *  removed.
1144               * @return {boolean} true if the unbind was successful, false
1145               *  otherwise.
1146               * @static
1147               * @deprecated use YAHOO.util.Event.removeListener and specify "focusout" as the event type.
1148               */
1149              removeBlurListener: function (el, fn) {
1150                  return this.removeListener(el, FOCUSOUT, fn);
1151              },
1152  
1153              /**
1154               * Removes an event listener
1155               *
1156               * @method removeListener
1157               *
1158               * @param {String|HTMLElement|Array|NodeList} el An id, an element
1159               *  reference, or a collection of ids and/or elements to remove
1160               *  the listener from.
1161               * @param {String} sType the type of event to remove.
1162               * @param {Function} fn the method the event invokes.  If fn is
1163               *  undefined, then all event handlers for the type of event are
1164               *  removed.
1165               * @return {boolean} true if the unbind was successful, false
1166               *  otherwise.
1167               * @static
1168               */
1169              removeListener: function(el, sType, fn) {
1170                  var i, len, li;
1171  
1172                  sType = this._getType(sType);
1173  
1174                  // The el argument can be a string
1175                  if (typeof el == "string") {
1176                      el = this.getEl(el);
1177                  // The el argument can be an array of elements or element ids.
1178                  } else if ( this._isValidCollection(el)) {
1179                      var ok = true;
1180                      for (i=el.length-1; i>-1; i--) {
1181                          ok = ( this.removeListener(el[i], sType, fn) && ok );
1182                      }
1183                      return ok;
1184                  }
1185  
1186                  if (!fn || !fn.call) {
1187                      //return false;
1188                      return this.purgeElement(el, false, sType);
1189                  }
1190  
1191                  if ("unload" == sType) {
1192  
1193                      for (i=unloadListeners.length-1; i>-1; i--) {
1194                          li = unloadListeners[i];
1195                          if (li &&
1196                              li[0] == el &&
1197                              li[1] == sType &&
1198                              li[2] == fn) {
1199                                  unloadListeners.splice(i, 1);
1200                                  // unloadListeners[i]=null;
1201                                  return true;
1202                          }
1203                      }
1204  
1205                      return false;
1206                  }
1207  
1208                  var cacheItem = null;
1209  
1210                  // The index is a hidden parameter; needed to remove it from
1211                  // the method signature because it was tempting users to
1212                  // try and take advantage of it, which is not possible.
1213                  var index = arguments[3];
1214  
1215                  if ("undefined" === typeof index) {
1216                      index = this._getCacheIndex(listeners, el, sType, fn);
1217                  }
1218  
1219                  if (index >= 0) {
1220                      cacheItem = listeners[index];
1221                  }
1222  
1223                  if (!el || !cacheItem) {
1224                      return false;
1225                  }
1226  
1227  
1228                  var bCapture = cacheItem[this.CAPTURE] === true ? true : false;
1229  
1230                  try {
1231                      this._simpleRemove(el, sType, cacheItem[this.WFN], bCapture);
1232                  } catch(ex) {
1233                      this.lastError = ex;
1234                      return false;
1235                  }
1236  
1237                  // removed the wrapped handler
1238                  delete listeners[index][this.WFN];
1239                  delete listeners[index][this.FN];
1240                  listeners.splice(index, 1);
1241                  // listeners[index]=null;
1242  
1243                  return true;
1244  
1245              },
1246  
1247              /**
1248               * Returns the event's target element.  Safari sometimes provides
1249               * a text node, and this is automatically resolved to the text
1250               * node's parent so that it behaves like other browsers.
1251               * @method getTarget
1252               * @param {Event} ev the event
1253               * @param {boolean} resolveTextNode when set to true the target's
1254               *                  parent will be returned if the target is a
1255               *                  text node.  @deprecated, the text node is
1256               *                  now resolved automatically
1257               * @return {HTMLElement} the event's target
1258               * @static
1259               */
1260              getTarget: function(ev, resolveTextNode) {
1261                  var t = ev.target || ev.srcElement;
1262                  return this.resolveTextNode(t);
1263              },
1264  
1265              /**
1266               * In some cases, some browsers will return a text node inside
1267               * the actual element that was targeted.  This normalizes the
1268               * return value for getTarget and getRelatedTarget.
1269               *
1270               * If accessing a property of the node throws an error, this is
1271               * probably the anonymous div wrapper Gecko adds inside text
1272               * nodes.  This likely will only occur when attempting to access
1273               * the relatedTarget.  In this case, we now return null because
1274               * the anonymous div is completely useless and we do not know
1275               * what the related target was because we can't even get to
1276               * the element's parent node.
1277               *
1278               * @method resolveTextNode
1279               * @param {HTMLElement} node node to resolve
1280               * @return {HTMLElement} the normized node
1281               * @static
1282               */
1283              resolveTextNode: function(n) {
1284                  try {
1285                      if (n && 3 == n.nodeType) {
1286                          return n.parentNode;
1287                      }
1288                  } catch(e) {
1289                      return null;
1290                  }
1291  
1292                  return n;
1293              },
1294  
1295              /**
1296               * Returns the event's pageX
1297               * @method getPageX
1298               * @param {Event} ev the event
1299               * @return {int} the event's pageX
1300               * @static
1301               */
1302              getPageX: function(ev) {
1303                  var x = ev.pageX;
1304                  if (!x && 0 !== x) {
1305                      x = ev.clientX || 0;
1306  
1307                      if ( this.isIE ) {
1308                          x += this._getScrollLeft();
1309                      }
1310                  }
1311  
1312                  return x;
1313              },
1314  
1315              /**
1316               * Returns the event's pageY
1317               * @method getPageY
1318               * @param {Event} ev the event
1319               * @return {int} the event's pageY
1320               * @static
1321               */
1322              getPageY: function(ev) {
1323                  var y = ev.pageY;
1324                  if (!y && 0 !== y) {
1325                      y = ev.clientY || 0;
1326  
1327                      if ( this.isIE ) {
1328                          y += this._getScrollTop();
1329                      }
1330                  }
1331  
1332  
1333                  return y;
1334              },
1335  
1336              /**
1337               * Returns the pageX and pageY properties as an indexed array.
1338               * @method getXY
1339               * @param {Event} ev the event
1340               * @return {[x, y]} the pageX and pageY properties of the event
1341               * @static
1342               */
1343              getXY: function(ev) {
1344                  return [this.getPageX(ev), this.getPageY(ev)];
1345              },
1346  
1347              /**
1348               * Returns the event's related target
1349               * @method getRelatedTarget
1350               * @param {Event} ev the event
1351               * @return {HTMLElement} the event's relatedTarget
1352               * @static
1353               */
1354              getRelatedTarget: function(ev) {
1355                  var t = ev.relatedTarget;
1356                  if (!t) {
1357                      if (ev.type == "mouseout") {
1358                          t = ev.toElement;
1359                      } else if (ev.type == "mouseover") {
1360                          t = ev.fromElement;
1361                      }
1362                  }
1363  
1364                  return this.resolveTextNode(t);
1365              },
1366  
1367              /**
1368               * Returns the time of the event.  If the time is not included, the
1369               * event is modified using the current time.
1370               * @method getTime
1371               * @param {Event} ev the event
1372               * @return {Date} the time of the event
1373               * @static
1374               */
1375              getTime: function(ev) {
1376                  if (!ev.time) {
1377                      var t = new Date().getTime();
1378                      try {
1379                          ev.time = t;
1380                      } catch(ex) {
1381                          this.lastError = ex;
1382                          return t;
1383                      }
1384                  }
1385  
1386                  return ev.time;
1387              },
1388  
1389              /**
1390               * Convenience method for stopPropagation + preventDefault
1391               * @method stopEvent
1392               * @param {Event} ev the event
1393               * @static
1394               */
1395              stopEvent: function(ev) {
1396                  this.stopPropagation(ev);
1397                  this.preventDefault(ev);
1398              },
1399  
1400              /**
1401               * Stops event propagation
1402               * @method stopPropagation
1403               * @param {Event} ev the event
1404               * @static
1405               */
1406              stopPropagation: function(ev) {
1407                  if (ev.stopPropagation) {
1408                      ev.stopPropagation();
1409                  } else {
1410                      ev.cancelBubble = true;
1411                  }
1412              },
1413  
1414              /**
1415               * Prevents the default behavior of the event
1416               * @method preventDefault
1417               * @param {Event} ev the event
1418               * @static
1419               */
1420              preventDefault: function(ev) {
1421                  if (ev.preventDefault) {
1422                      ev.preventDefault();
1423                  } else {
1424                      ev.returnValue = false;
1425                  }
1426              },
1427  
1428              /**
1429               * Finds the event in the window object, the caller's arguments, or
1430               * in the arguments of another method in the callstack.  This is
1431               * executed automatically for events registered through the event
1432               * manager, so the implementer should not normally need to execute
1433               * this function at all.
1434               * @method getEvent
1435               * @param {Event} e the event parameter from the handler
1436               * @param {HTMLElement} boundEl the element the listener is attached to
1437               * @return {Event} the event
1438               * @static
1439               */
1440              getEvent: function(e, boundEl) {
1441                  var ev = e || window.event;
1442  
1443                  if (!ev) {
1444                      var c = this.getEvent.caller;
1445                      while (c) {
1446                          ev = c.arguments[0];
1447                          if (ev && Event == ev.constructor) {
1448                              break;
1449                          }
1450                          c = c.caller;
1451                      }
1452                  }
1453  
1454                  return ev;
1455              },
1456  
1457              /**
1458               * Returns the charcode for an event
1459               * @method getCharCode
1460               * @param {Event} ev the event
1461               * @return {int} the event's charCode
1462               * @static
1463               */
1464              getCharCode: function(ev) {
1465                  var code = ev.keyCode || ev.charCode || 0;
1466  
1467                  // webkit key normalization
1468                  if (YAHOO.env.ua.webkit && (code in webkitKeymap)) {
1469                      code = webkitKeymap[code];
1470                  }
1471                  return code;
1472              },
1473  
1474              /**
1475               * Locating the saved event handler data by function ref
1476               *
1477               * @method _getCacheIndex
1478               * @static
1479               * @private
1480               */
1481              _getCacheIndex: function(a, el, sType, fn) {
1482                  for (var i=0, l=a.length; i<l; i=i+1) {
1483                      var li = a[i];
1484                      if ( li                 &&
1485                           li[this.FN] == fn  &&
1486                           li[this.EL] == el  &&
1487                           li[this.TYPE] == sType ) {
1488                          return i;
1489                      }
1490                  }
1491  
1492                  return -1;
1493              },
1494  
1495              /**
1496               * Generates an unique ID for the element if it does not already
1497               * have one.
1498               * @method generateId
1499               * @param el the element to create the id for
1500               * @return {string} the resulting id of the element
1501               * @static
1502               */
1503              generateId: function(el) {
1504                  var id = el.id;
1505  
1506                  if (!id) {
1507                      id = "yuievtautoid-" + counter;
1508                      ++counter;
1509                      el.id = id;
1510                  }
1511  
1512                  return id;
1513              },
1514  
1515  
1516              /**
1517               * We want to be able to use getElementsByTagName as a collection
1518               * to attach a group of events to.  Unfortunately, different
1519               * browsers return different types of collections.  This function
1520               * tests to determine if the object is array-like.  It will also
1521               * fail if the object is an array, but is empty.
1522               * @method _isValidCollection
1523               * @param o the object to test
1524               * @return {boolean} true if the object is array-like and populated
1525               * @static
1526               * @private
1527               */
1528              _isValidCollection: function(o) {
1529                  try {
1530                      return ( o                     && // o is something
1531                               typeof o !== "string" && // o is not a string
1532                               o.length              && // o is indexed
1533                               !o.tagName            && // o is not an HTML element
1534                               !o.alert              && // o is not a window
1535                               typeof o[0] !== "undefined" );
1536                  } catch(ex) {
1537                      return false;
1538                  }
1539  
1540              },
1541  
1542              /**
1543               * @private
1544               * @property elCache
1545               * DOM element cache
1546               * @static
1547               * @deprecated Elements are not cached due to issues that arise when
1548               * elements are removed and re-added
1549               */
1550              elCache: {},
1551  
1552              /**
1553               * We cache elements bound by id because when the unload event
1554               * fires, we can no longer use document.getElementById
1555               * @method getEl
1556               * @static
1557               * @private
1558               * @deprecated Elements are not cached any longer
1559               */
1560              getEl: function(id) {
1561                  return (typeof id === "string") ? document.getElementById(id) : id;
1562              },
1563  
1564              /**
1565               * Clears the element cache
1566               * @deprecated Elements are not cached any longer
1567               * @method clearCache
1568               * @static
1569               * @private
1570               */
1571              clearCache: function() { },
1572  
1573              /**
1574               * Custom event the fires when the dom is initially usable
1575               * @event DOMReadyEvent
1576               */
1577              DOMReadyEvent: new YAHOO.util.CustomEvent("DOMReady", YAHOO, 0, 0, 1),
1578  
1579              /**
1580               * hook up any deferred listeners
1581               * @method _load
1582               * @static
1583               * @private
1584               */
1585              _load: function(e) {
1586  
1587                  if (!loadComplete) {
1588                      loadComplete = true;
1589                      var EU = YAHOO.util.Event;
1590  
1591                      // Just in case DOMReady did not go off for some reason
1592                      EU._ready();
1593  
1594                      // Available elements may not have been detected before the
1595                      // window load event fires. Try to find them now so that the
1596                      // the user is more likely to get the onAvailable notifications
1597                      // before the window load notification
1598                      EU._tryPreloadAttach();
1599  
1600                  }
1601              },
1602  
1603              /**
1604               * Fires the DOMReady event listeners the first time the document is
1605               * usable.
1606               * @method _ready
1607               * @static
1608               * @private
1609               */
1610              _ready: function(e) {
1611                  var EU = YAHOO.util.Event;
1612                  if (!EU.DOMReady) {
1613                      EU.DOMReady=true;
1614  
1615                      // Fire the content ready custom event
1616                      EU.DOMReadyEvent.fire();
1617  
1618                      // Remove the DOMContentLoaded (FF/Opera)
1619                      EU._simpleRemove(document, "DOMContentLoaded", EU._ready);
1620                  }
1621              },
1622  
1623              /**
1624               * Polling function that runs before the onload event fires,
1625               * attempting to attach to DOM Nodes as soon as they are
1626               * available
1627               * @method _tryPreloadAttach
1628               * @static
1629               * @private
1630               */
1631              _tryPreloadAttach: function() {
1632  
1633                  if (onAvailStack.length === 0) {
1634                      retryCount = 0;
1635                      if (this._interval) {
1636                          // clearInterval(this._interval);
1637                          this._interval.cancel();
1638                          this._interval = null;
1639                      }
1640                      return;
1641                  }
1642  
1643                  if (this.locked) {
1644                      return;
1645                  }
1646  
1647                  if (this.isIE) {
1648                      // Hold off if DOMReady has not fired and check current
1649                      // readyState to protect against the IE operation aborted
1650                      // issue.
1651                      if (!this.DOMReady) {
1652                          this.startInterval();
1653                          return;
1654                      }
1655                  }
1656  
1657                  this.locked = true;
1658  
1659  
1660                  // keep trying until after the page is loaded.  We need to
1661                  // check the page load state prior to trying to bind the
1662                  // elements so that we can be certain all elements have been
1663                  // tested appropriately
1664                  var tryAgain = !loadComplete;
1665                  if (!tryAgain) {
1666                      tryAgain = (retryCount > 0 && onAvailStack.length > 0);
1667                  }
1668  
1669                  // onAvailable
1670                  var notAvail = [];
1671  
1672                  var executeItem = function (el, item) {
1673                      var context = el;
1674                      if (item.overrideContext) {
1675                          if (item.overrideContext === true) {
1676                              context = item.obj;
1677                          } else {
1678                              context = item.overrideContext;
1679                          }
1680                      }
1681                      item.fn.call(context, item.obj);
1682                  };
1683  
1684                  var i, len, item, el, ready=[];
1685  
1686                  // onAvailable onContentReady
1687                  for (i=0, len=onAvailStack.length; i<len; i=i+1) {
1688                      item = onAvailStack[i];
1689                      if (item) {
1690                          el = this.getEl(item.id);
1691                          if (el) {
1692                              if (item.checkReady) {
1693                                  if (loadComplete || el.nextSibling || !tryAgain) {
1694                                      ready.push(item);
1695                                      onAvailStack[i] = null;
1696                                  }
1697                              } else {
1698                                  executeItem(el, item);
1699                                  onAvailStack[i] = null;
1700                              }
1701                          } else {
1702                              notAvail.push(item);
1703                          }
1704                      }
1705                  }
1706  
1707                  // make sure onContentReady fires after onAvailable
1708                  for (i=0, len=ready.length; i<len; i=i+1) {
1709                      item = ready[i];
1710                      executeItem(this.getEl(item.id), item);
1711                  }
1712  
1713  
1714                  retryCount--;
1715  
1716                  if (tryAgain) {
1717                      for (i=onAvailStack.length-1; i>-1; i--) {
1718                          item = onAvailStack[i];
1719                          if (!item || !item.id) {
1720                              onAvailStack.splice(i, 1);
1721                          }
1722                      }
1723  
1724                      this.startInterval();
1725                  } else {
1726                      if (this._interval) {
1727                          // clearInterval(this._interval);
1728                          this._interval.cancel();
1729                          this._interval = null;
1730                      }
1731                  }
1732  
1733                  this.locked = false;
1734  
1735              },
1736  
1737              /**
1738               * Removes all listeners attached to the given element via addListener.
1739               * Optionally, the node's children can also be purged.
1740               * Optionally, you can specify a specific type of event to remove.
1741               * @method purgeElement
1742               * @param {HTMLElement} el the element to purge
1743               * @param {boolean} recurse recursively purge this element's children
1744               * as well.  Use with caution.
1745               * @param {string} sType optional type of listener to purge. If
1746               * left out, all listeners will be removed
1747               * @static
1748               */
1749              purgeElement: function(el, recurse, sType) {
1750                  var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el;
1751                  var elListeners = this.getListeners(oEl, sType), i, len;
1752                  if (elListeners) {
1753                      for (i=elListeners.length-1; i>-1; i--) {
1754                          var l = elListeners[i];
1755                          this.removeListener(oEl, l.type, l.fn);
1756                      }
1757                  }
1758  
1759                  if (recurse && oEl && oEl.childNodes) {
1760                      for (i=0,len=oEl.childNodes.length; i<len ; ++i) {
1761                          this.purgeElement(oEl.childNodes[i], recurse, sType);
1762                      }
1763                  }
1764              },
1765  
1766              /**
1767               * Returns all listeners attached to the given element via addListener.
1768               * Optionally, you can specify a specific type of event to return.
1769               * @method getListeners
1770               * @param el {HTMLElement|string} the element or element id to inspect
1771               * @param sType {string} optional type of listener to return. If
1772               * left out, all listeners will be returned
1773               * @return {Object} the listener. Contains the following fields:
1774               * &nbsp;&nbsp;type:   (string)   the type of event
1775               * &nbsp;&nbsp;fn:     (function) the callback supplied to addListener
1776               * &nbsp;&nbsp;obj:    (object)   the custom object supplied to addListener
1777               * &nbsp;&nbsp;adjust: (boolean|object)  whether or not to adjust the default context
1778               * &nbsp;&nbsp;scope: (boolean)  the derived context based on the adjust parameter
1779               * &nbsp;&nbsp;index:  (int)      its position in the Event util listener cache
1780               * @static
1781               */
1782              getListeners: function(el, sType) {
1783                  var results=[], searchLists;
1784                  if (!sType) {
1785                      searchLists = [listeners, unloadListeners];
1786                  } else if (sType === "unload") {
1787                      searchLists = [unloadListeners];
1788                  } else {
1789                      sType = this._getType(sType);
1790                      searchLists = [listeners];
1791                  }
1792  
1793                  var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el;
1794  
1795                  for (var j=0;j<searchLists.length; j=j+1) {
1796                      var searchList = searchLists[j];
1797                      if (searchList) {
1798                          for (var i=0,len=searchList.length; i<len ; ++i) {
1799                              var l = searchList[i];
1800                              if ( l  && l[this.EL] === oEl &&
1801                                      (!sType || sType === l[this.TYPE]) ) {
1802                                  results.push({
1803                                      type:   l[this.TYPE],
1804                                      fn:     l[this.FN],
1805                                      obj:    l[this.OBJ],
1806                                      adjust: l[this.OVERRIDE],
1807                                      scope:  l[this.ADJ_SCOPE],
1808                                      index:  i
1809                                  });
1810                              }
1811                          }
1812                      }
1813                  }
1814  
1815                  return (results.length) ? results : null;
1816              },
1817  
1818              /**
1819               * Removes all listeners registered by pe.event.  Called
1820               * automatically during the unload event.
1821               * @method _unload
1822               * @static
1823               * @private
1824               */
1825              _unload: function(e) {
1826  
1827                  var EU = YAHOO.util.Event, i, j, l, len, index,
1828                           ul = unloadListeners.slice(), context;
1829  
1830                  // execute and clear stored unload listeners
1831                  for (i=0, len=unloadListeners.length; i<len; ++i) {
1832                      l = ul[i];
1833                      if (l) {
1834                          try {
1835                              context = window;
1836                              if (l[EU.ADJ_SCOPE]) {
1837                                  if (l[EU.ADJ_SCOPE] === true) {
1838                                      context = l[EU.UNLOAD_OBJ];
1839                                  } else {
1840                                      context = l[EU.ADJ_SCOPE];
1841                                  }
1842                              }
1843                              l[EU.FN].call(context, EU.getEvent(e, l[EU.EL]), l[EU.UNLOAD_OBJ] );
1844                          } catch(e1) {}
1845                          ul[i] = null;
1846                      }
1847                  }
1848  
1849                  l = null;
1850                  context = null;
1851                  unloadListeners = null;
1852  
1853                  // Remove listeners to handle IE memory leaks
1854                  // 2.5.0 listeners are removed for all browsers again.  FireFox preserves
1855                  // at least some listeners between page refreshes, potentially causing
1856                  // errors during page load (mouseover listeners firing before they
1857                  // should if the user moves the mouse at the correct moment).
1858                  if (listeners) {
1859                      for (j=listeners.length-1; j>-1; j--) {
1860                          l = listeners[j];
1861                          if (l) {
1862                              try {
1863                                  EU.removeListener(l[EU.EL], l[EU.TYPE], l[EU.FN], j);
1864                              } catch(e2) {}
1865                          }
1866                      }
1867                      l=null;
1868                  }
1869  
1870                  try {
1871                      EU._simpleRemove(window, "unload", EU._unload);
1872                      EU._simpleRemove(window, "load", EU._load);
1873                  } catch(e3) {}
1874  
1875              },
1876  
1877              /**
1878               * Returns scrollLeft
1879               * @method _getScrollLeft
1880               * @static
1881               * @private
1882               */
1883              _getScrollLeft: function() {
1884                  return this._getScroll()[1];
1885              },
1886  
1887              /**
1888               * Returns scrollTop
1889               * @method _getScrollTop
1890               * @static
1891               * @private
1892               */
1893              _getScrollTop: function() {
1894                  return this._getScroll()[0];
1895              },
1896  
1897              /**
1898               * Returns the scrollTop and scrollLeft.  Used to calculate the
1899               * pageX and pageY in Internet Explorer
1900               * @method _getScroll
1901               * @static
1902               * @private
1903               */
1904              _getScroll: function() {
1905                  var dd = document.documentElement, db = document.body;
1906                  if (dd && (dd.scrollTop || dd.scrollLeft)) {
1907                      return [dd.scrollTop, dd.scrollLeft];
1908                  } else if (db) {
1909                      return [db.scrollTop, db.scrollLeft];
1910                  } else {
1911                      return [0, 0];
1912                  }
1913              },
1914  
1915              /**
1916               * Used by old versions of CustomEvent, restored for backwards
1917               * compatibility
1918               * @method regCE
1919               * @private
1920               * @static
1921               * @deprecated still here for backwards compatibility
1922               */
1923              regCE: function() {},
1924  
1925              /**
1926               * Adds a DOM event directly without the caching, cleanup, context adj, etc
1927               *
1928               * @method _simpleAdd
1929               * @param {HTMLElement} el      the element to bind the handler to
1930               * @param {string}      sType   the type of event handler
1931               * @param {function}    fn      the callback to invoke
1932               * @param {boolen}      capture capture or bubble phase
1933               * @static
1934               * @private
1935               */
1936              _simpleAdd: function () {
1937                  if (window.addEventListener) {
1938                      return function(el, sType, fn, capture) {
1939                          el.addEventListener(sType, fn, (capture));
1940                      };
1941                  } else if (window.attachEvent) {
1942                      return function(el, sType, fn, capture) {
1943                          el.attachEvent("on" + sType, fn);
1944                      };
1945                  } else {
1946                      return function(){};
1947                  }
1948              }(),
1949  
1950              /**
1951               * Basic remove listener
1952               *
1953               * @method _simpleRemove
1954               * @param {HTMLElement} el      the element to bind the handler to
1955               * @param {string}      sType   the type of event handler
1956               * @param {function}    fn      the callback to invoke
1957               * @param {boolen}      capture capture or bubble phase
1958               * @static
1959               * @private
1960               */
1961              _simpleRemove: function() {
1962                  if (window.removeEventListener) {
1963                      return function (el, sType, fn, capture) {
1964                          el.removeEventListener(sType, fn, (capture));
1965                      };
1966                  } else if (window.detachEvent) {
1967                      return function (el, sType, fn) {
1968                          el.detachEvent("on" + sType, fn);
1969                      };
1970                  } else {
1971                      return function(){};
1972                  }
1973              }()
1974          };
1975  
1976      }();
1977  
1978      (function() {
1979          var EU = YAHOO.util.Event;
1980  
1981          /**
1982           * Appends an event handler.  This is an alias for <code>addListener</code>
1983           *
1984           * @method on
1985           *
1986           * @param {String|HTMLElement|Array|NodeList} el An id, an element
1987           *  reference, or a collection of ids and/or elements to assign the
1988           *  listener to.
1989           * @param {String}   sType     The type of event to append
1990           * @param {Function} fn        The method the event invokes
1991           * @param {Object}   obj    An arbitrary object that will be
1992           *                             passed as a parameter to the handler
1993           * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
1994           *                             the execution context of the listener. If an
1995           *                             object, this object becomes the execution
1996           *                             context.
1997           * @return {Boolean} True if the action was successful or defered,
1998           *                        false if one or more of the elements
1999           *                        could not have the listener attached,
2000           *                        or if the operation throws an exception.
2001           * @static
2002           */
2003          EU.on = EU.addListener;
2004  
2005          /**
2006           * YAHOO.util.Event.onFocus is an alias for addFocusListener
2007           * @method onFocus
2008           * @see addFocusListener
2009           * @static
2010           * @deprecated use YAHOO.util.Event.on and specify "focusin" as the event type.
2011           */
2012          EU.onFocus = EU.addFocusListener;
2013  
2014          /**
2015           * YAHOO.util.Event.onBlur is an alias for addBlurListener
2016           * @method onBlur
2017           * @see addBlurListener
2018           * @static
2019           * @deprecated use YAHOO.util.Event.on and specify "focusout" as the event type.
2020           */
2021          EU.onBlur = EU.addBlurListener;
2022  
2023  /*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
2024  
2025          // Internet Explorer: use the readyState of a defered script.
2026          // This isolates what appears to be a safe moment to manipulate
2027          // the DOM prior to when the document's readyState suggests
2028          // it is safe to do so.
2029          if (EU.isIE) {
2030              if (self !== self.top) {
2031                  document.onreadystatechange = function() {
2032                      if (document.readyState == 'complete') {
2033                          document.onreadystatechange = null;
2034                          EU._ready();
2035                      }
2036                  };
2037              } else {
2038  
2039                  // Process onAvailable/onContentReady items when the
2040                  // DOM is ready.
2041                  YAHOO.util.Event.onDOMReady(
2042                          YAHOO.util.Event._tryPreloadAttach,
2043                          YAHOO.util.Event, true);
2044  
2045                  var n = document.createElement('p');
2046  
2047                  EU._dri = setInterval(function() {
2048                      try {
2049                          // throws an error if doc is not ready
2050                          n.doScroll('left');
2051                          clearInterval(EU._dri);
2052                          EU._dri = null;
2053                          EU._ready();
2054                          n = null;
2055                      } catch (ex) {
2056                      }
2057                  }, EU.POLL_INTERVAL);
2058              }
2059  
2060          // The document's readyState in Safari currently will
2061          // change to loaded/complete before images are loaded.
2062          } else if (EU.webkit && EU.webkit < 525) {
2063  
2064              EU._dri = setInterval(function() {
2065                  var rs=document.readyState;
2066                  if ("loaded" == rs || "complete" == rs) {
2067                      clearInterval(EU._dri);
2068                      EU._dri = null;
2069                      EU._ready();
2070                  }
2071              }, EU.POLL_INTERVAL);
2072  
2073          // FireFox and Opera: These browsers provide a event for this
2074          // moment.  The latest WebKit releases now support this event.
2075          } else {
2076  
2077              EU._simpleAdd(document, "DOMContentLoaded", EU._ready);
2078  
2079          }
2080          /////////////////////////////////////////////////////////////
2081  
2082  
2083          EU._simpleAdd(window, "load", EU._load);
2084          EU._simpleAdd(window, "unload", EU._unload);
2085          EU._tryPreloadAttach();
2086      })();
2087  
2088  }
2089  /**
2090   * EventProvider is designed to be used with YAHOO.augment to wrap
2091   * CustomEvents in an interface that allows events to be subscribed to
2092   * and fired by name.  This makes it possible for implementing code to
2093   * subscribe to an event that either has not been created yet, or will
2094   * not be created at all.
2095   *
2096   * @Class EventProvider
2097   */
2098  YAHOO.util.EventProvider = function() { };
2099  
2100  YAHOO.util.EventProvider.prototype = {
2101  
2102      /**
2103       * Private storage of custom events
2104       * @property __yui_events
2105       * @type Object[]
2106       * @private
2107       */
2108      __yui_events: null,
2109  
2110      /**
2111       * Private storage of custom event subscribers
2112       * @property __yui_subscribers
2113       * @type Object[]
2114       * @private
2115       */
2116      __yui_subscribers: null,
2117  
2118      /**
2119       * Subscribe to a CustomEvent by event type
2120       *
2121       * @method subscribe
2122       * @param p_type     {string}   the type, or name of the event
2123       * @param p_fn       {function} the function to exectute when the event fires
2124       * @param p_obj      {Object}   An object to be passed along when the event
2125       *                              fires
2126       * @param overrideContext {boolean}  If true, the obj passed in becomes the
2127       *                              execution scope of the listener
2128       */
2129      subscribe: function(p_type, p_fn, p_obj, overrideContext) {
2130  
2131          this.__yui_events = this.__yui_events || {};
2132          var ce = this.__yui_events[p_type];
2133  
2134          if (ce) {
2135              ce.subscribe(p_fn, p_obj, overrideContext);
2136          } else {
2137              this.__yui_subscribers = this.__yui_subscribers || {};
2138              var subs = this.__yui_subscribers;
2139              if (!subs[p_type]) {
2140                  subs[p_type] = [];
2141              }
2142              subs[p_type].push(
2143                  { fn: p_fn, obj: p_obj, overrideContext: overrideContext } );
2144          }
2145      },
2146  
2147      /**
2148       * Unsubscribes one or more listeners the from the specified event
2149       * @method unsubscribe
2150       * @param p_type {string}   The type, or name of the event.  If the type
2151       *                          is not specified, it will attempt to remove
2152       *                          the listener from all hosted events.
2153       * @param p_fn   {Function} The subscribed function to unsubscribe, if not
2154       *                          supplied, all subscribers will be removed.
2155       * @param p_obj  {Object}   The custom object passed to subscribe.  This is
2156       *                        optional, but if supplied will be used to
2157       *                        disambiguate multiple listeners that are the same
2158       *                        (e.g., you subscribe many object using a function
2159       *                        that lives on the prototype)
2160       * @return {boolean} true if the subscriber was found and detached.
2161       */
2162      unsubscribe: function(p_type, p_fn, p_obj) {
2163          this.__yui_events = this.__yui_events || {};
2164          var evts = this.__yui_events;
2165          if (p_type) {
2166              var ce = evts[p_type];
2167              if (ce) {
2168                  return ce.unsubscribe(p_fn, p_obj);
2169              }
2170          } else {
2171              var ret = true;
2172              for (var i in evts) {
2173                  if (YAHOO.lang.hasOwnProperty(evts, i)) {
2174                      ret = ret && evts[i].unsubscribe(p_fn, p_obj);
2175                  }
2176              }
2177              return ret;
2178          }
2179  
2180          return false;
2181      },
2182  
2183      /**
2184       * Removes all listeners from the specified event.  If the event type
2185       * is not specified, all listeners from all hosted custom events will
2186       * be removed.
2187       * @method unsubscribeAll
2188       * @param p_type {string}   The type, or name of the event
2189       */
2190      unsubscribeAll: function(p_type) {
2191          return this.unsubscribe(p_type);
2192      },
2193  
2194      /**
2195       * Creates a new custom event of the specified type.  If a custom event
2196       * by that name already exists, it will not be re-created.  In either
2197       * case the custom event is returned.
2198       *
2199       * @method createEvent
2200       *
2201       * @param p_type {string} the type, or name of the event
2202       * @param p_config {object} optional config params.  Valid properties are:
2203       *
2204       *  <ul>
2205       *    <li>
2206       *      scope: defines the default execution scope.  If not defined
2207       *      the default scope will be this instance.
2208       *    </li>
2209       *    <li>
2210       *      silent: if true, the custom event will not generate log messages.
2211       *      This is false by default.
2212       *    </li>
2213       *    <li>
2214       *      fireOnce: if true, the custom event will only notify subscribers
2215       *      once regardless of the number of times the event is fired.  In
2216       *      addition, new subscribers will be executed immediately if the
2217       *      event has already fired.
2218       *      This is false by default.
2219       *    </li>
2220       *    <li>
2221       *      onSubscribeCallback: specifies a callback to execute when the
2222       *      event has a new subscriber.  This will fire immediately for
2223       *      each queued subscriber if any exist prior to the creation of
2224       *      the event.
2225       *    </li>
2226       *  </ul>
2227       *
2228       *  @return {CustomEvent} the custom event
2229       *
2230       */
2231      createEvent: function(p_type, p_config) {
2232  
2233          this.__yui_events = this.__yui_events || {};
2234          var opts = p_config || {},
2235              events = this.__yui_events, ce;
2236  
2237          if (events[p_type]) {
2238          } else {
2239  
2240              ce = new YAHOO.util.CustomEvent(p_type, opts.scope || this, opts.silent,
2241                           YAHOO.util.CustomEvent.FLAT, opts.fireOnce);
2242  
2243              events[p_type] = ce;
2244  
2245              if (opts.onSubscribeCallback) {
2246                  ce.subscribeEvent.subscribe(opts.onSubscribeCallback);
2247              }
2248  
2249              this.__yui_subscribers = this.__yui_subscribers || {};
2250              var qs = this.__yui_subscribers[p_type];
2251  
2252              if (qs) {
2253                  for (var i=0; i<qs.length; ++i) {
2254                      ce.subscribe(qs[i].fn, qs[i].obj, qs[i].overrideContext);
2255                  }
2256              }
2257          }
2258  
2259          return events[p_type];
2260      },
2261  
2262  
2263     /**
2264       * Fire a custom event by name.  The callback functions will be executed
2265       * from the scope specified when the event was created, and with the
2266       * following parameters:
2267       *   <ul>
2268       *   <li>The first argument fire() was executed with</li>
2269       *   <li>The custom object (if any) that was passed into the subscribe()
2270       *       method</li>
2271       *   </ul>
2272       * @method fireEvent
2273       * @param p_type    {string}  the type, or name of the event
2274       * @param arguments {Object*} an arbitrary set of parameters to pass to
2275       *                            the handler.
2276       * @return {boolean} the return value from CustomEvent.fire
2277       *
2278       */
2279      fireEvent: function(p_type) {
2280  
2281          this.__yui_events = this.__yui_events || {};
2282          var ce = this.__yui_events[p_type];
2283  
2284          if (!ce) {
2285              return null;
2286          }
2287  
2288          var args = [];
2289          for (var i=1; i<arguments.length; ++i) {
2290              args.push(arguments[i]);
2291          }
2292          return ce.fire.apply(ce, args);
2293      },
2294  
2295      /**
2296       * Returns true if the custom event of the provided type has been created
2297       * with createEvent.
2298       * @method hasEvent
2299       * @param type {string} the type, or name of the event
2300       */
2301      hasEvent: function(type) {
2302          if (this.__yui_events) {
2303              if (this.__yui_events[type]) {
2304                  return true;
2305              }
2306          }
2307          return false;
2308      }
2309  
2310  };
2311  
2312  (function() {
2313  
2314      var Event = YAHOO.util.Event, Lang = YAHOO.lang;
2315  
2316  /**
2317  * KeyListener is a utility that provides an easy interface for listening for
2318  * keydown/keyup events fired against DOM elements.
2319  * @namespace YAHOO.util
2320  * @class KeyListener
2321  * @constructor
2322  * @param {HTMLElement} attachTo The element or element ID to which the key
2323  *                               event should be attached
2324  * @param {String}      attachTo The element or element ID to which the key
2325  *                               event should be attached
2326  * @param {Object}      keyData  The object literal representing the key(s)
2327  *                               to detect. Possible attributes are
2328  *                               shift(boolean), alt(boolean), ctrl(boolean)
2329  *                               and keys(either an int or an array of ints
2330  *                               representing keycodes).
2331  * @param {Function}    handler  The CustomEvent handler to fire when the
2332  *                               key event is detected
2333  * @param {Object}      handler  An object literal representing the handler.
2334  * @param {String}      event    Optional. The event (keydown or keyup) to
2335  *                               listen for. Defaults automatically to keydown.
2336  *
2337  * @knownissue the "keypress" event is completely broken in Safari 2.x and below.
2338  *             the workaround is use "keydown" for key listening.  However, if
2339  *             it is desired to prevent the default behavior of the keystroke,
2340  *             that can only be done on the keypress event.  This makes key
2341  *             handling quite ugly.
2342  * @knownissue keydown is also broken in Safari 2.x and below for the ESC key.
2343  *             There currently is no workaround other than choosing another
2344  *             key to listen for.
2345  */
2346  YAHOO.util.KeyListener = function(attachTo, keyData, handler, event) {
2347      if (!attachTo) {
2348      } else if (!keyData) {
2349      } else if (!handler) {
2350      }
2351  
2352      if (!event) {
2353          event = YAHOO.util.KeyListener.KEYDOWN;
2354      }
2355  
2356      /**
2357      * The CustomEvent fired internally when a key is pressed
2358      * @event keyEvent
2359      * @private
2360      * @param {Object} keyData The object literal representing the key(s) to
2361      *                         detect. Possible attributes are shift(boolean),
2362      *                         alt(boolean), ctrl(boolean) and keys(either an
2363      *                         int or an array of ints representing keycodes).
2364      */
2365      var keyEvent = new YAHOO.util.CustomEvent("keyPressed");
2366  
2367      /**
2368      * The CustomEvent fired when the KeyListener is enabled via the enable()
2369      * function
2370      * @event enabledEvent
2371      * @param {Object} keyData The object literal representing the key(s) to
2372      *                         detect. Possible attributes are shift(boolean),
2373      *                         alt(boolean), ctrl(boolean) and keys(either an
2374      *                         int or an array of ints representing keycodes).
2375      */
2376      this.enabledEvent = new YAHOO.util.CustomEvent("enabled");
2377  
2378      /**
2379      * The CustomEvent fired when the KeyListener is disabled via the
2380      * disable() function
2381      * @event disabledEvent
2382      * @param {Object} keyData The object literal representing the key(s) to
2383      *                         detect. Possible attributes are shift(boolean),
2384      *                         alt(boolean), ctrl(boolean) and keys(either an
2385      *                         int or an array of ints representing keycodes).
2386      */
2387      this.disabledEvent = new YAHOO.util.CustomEvent("disabled");
2388  
2389      if (Lang.isString(attachTo)) {
2390          attachTo = document.getElementById(attachTo); // No Dom util
2391      }
2392  
2393      if (Lang.isFunction(handler)) {
2394          keyEvent.subscribe(handler);
2395      } else {
2396          keyEvent.subscribe(handler.fn, handler.scope, handler.correctScope);
2397      }
2398  
2399      /**
2400      * Handles the key event when a key is pressed.
2401      * @method handleKeyPress
2402      * @param {DOMEvent} e   The keypress DOM event
2403      * @param {Object}   obj The DOM event scope object
2404      * @private
2405      */
2406      function handleKeyPress(e, obj) {
2407          if (! keyData.shift) {
2408              keyData.shift = false;
2409          }
2410          if (! keyData.alt) {
2411              keyData.alt = false;
2412          }
2413          if (! keyData.ctrl) {
2414              keyData.ctrl = false;
2415          }
2416  
2417          // check held down modifying keys first
2418          if (e.shiftKey == keyData.shift &&
2419              e.altKey   == keyData.alt &&
2420              e.ctrlKey  == keyData.ctrl) { // if we pass this, all modifiers match
2421  
2422              var dataItem, keys = keyData.keys, key;
2423  
2424              if (YAHOO.lang.isArray(keys)) {
2425                  for (var i=0;i<keys.length;i++) {
2426                      dataItem = keys[i];
2427                      key = Event.getCharCode(e);
2428  
2429                      if (dataItem == key) {
2430                          keyEvent.fire(key, e);
2431                          break;
2432                      }
2433                  }
2434              } else {
2435                  key = Event.getCharCode(e);
2436                  if (keys == key ) {
2437                      keyEvent.fire(key, e);
2438                  }
2439              }
2440          }
2441      }
2442  
2443      /**
2444      * Enables the KeyListener by attaching the DOM event listeners to the
2445      * target DOM element
2446      * @method enable
2447      */
2448      this.enable = function() {
2449          if (! this.enabled) {
2450              Event.on(attachTo, event, handleKeyPress);
2451              this.enabledEvent.fire(keyData);
2452          }
2453          /**
2454          * Boolean indicating the enabled/disabled state of the Tooltip
2455          * @property enabled
2456          * @type Boolean
2457          */
2458          this.enabled = true;
2459      };
2460  
2461      /**
2462      * Disables the KeyListener by removing the DOM event listeners from the
2463      * target DOM element
2464      * @method disable
2465      */
2466      this.disable = function() {
2467          if (this.enabled) {
2468              Event.removeListener(attachTo, event, handleKeyPress);
2469              this.disabledEvent.fire(keyData);
2470          }
2471          this.enabled = false;
2472      };
2473  
2474      /**
2475      * Returns a String representation of the object.
2476      * @method toString
2477      * @return {String}  The string representation of the KeyListener
2478      */
2479      this.toString = function() {
2480          return "KeyListener [" + keyData.keys + "] " + attachTo.tagName +
2481                  (attachTo.id ? "[" + attachTo.id + "]" : "");
2482      };
2483  
2484  };
2485  
2486  var KeyListener = YAHOO.util.KeyListener;
2487  
2488  /**
2489   * Constant representing the DOM "keydown" event.
2490   * @property YAHOO.util.KeyListener.KEYDOWN
2491   * @static
2492   * @final
2493   * @type String
2494   */
2495  KeyListener.KEYDOWN = "keydown";
2496  
2497  /**
2498   * Constant representing the DOM "keyup" event.
2499   * @property YAHOO.util.KeyListener.KEYUP
2500   * @static
2501   * @final
2502   * @type String
2503   */
2504  KeyListener.KEYUP = "keyup";
2505  
2506  /**
2507   * keycode constants for a subset of the special keys
2508   * @property KEY
2509   * @static
2510   * @final
2511   */
2512  KeyListener.KEY = {
2513      ALT          : 18,
2514      BACK_SPACE   : 8,
2515      CAPS_LOCK    : 20,
2516      CONTROL      : 17,
2517      DELETE       : 46,
2518      DOWN         : 40,
2519      END          : 35,
2520      ENTER        : 13,
2521      ESCAPE       : 27,
2522      HOME         : 36,
2523      LEFT         : 37,
2524      META         : 224,
2525      NUM_LOCK     : 144,
2526      PAGE_DOWN    : 34,
2527      PAGE_UP      : 33,
2528      PAUSE        : 19,
2529      PRINTSCREEN  : 44,
2530      RIGHT        : 39,
2531      SCROLL_LOCK  : 145,
2532      SHIFT        : 16,
2533      SPACE        : 32,
2534      TAB          : 9,
2535      UP           : 38
2536  };
2537  
2538  })();
2539  YAHOO.register("event", YAHOO.util.Event, {version: "2.9.0", build: "2800"});
2540  
2541      YAHOO.util.Event.generateId = function(el) {
2542          if (!el.id) {
2543              el.id = Y.guid();
2544          }
2545          return el.id;
2546      };
2547      YAHOO.util.Event._load();
2548  }, '2.9.0' ,{"requires": ["yui2-yahoo"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1