]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blobdiff - wradmin/static/yui/event/event.js
Rename public directory to static.
[philipp/winterrodeln/wradmin.git] / wradmin / static / yui / event / event.js
diff --git a/wradmin/static/yui/event/event.js b/wradmin/static/yui/event/event.js
new file mode 100644 (file)
index 0000000..37cbc28
--- /dev/null
@@ -0,0 +1,2529 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.7.0
+*/
+
+/**
+ * The CustomEvent class lets you define events for your application
+ * that can be subscribed to by one or more independent component.
+ *
+ * @param {String}  type The type of event, which is passed to the callback
+ *                  when the event fires
+ * @param {Object}  context The context the event will fire from.  "this" will
+ *                  refer to this object in the callback.  Default value: 
+ *                  the window object.  The listener can override this.
+ * @param {boolean} silent pass true to prevent the event from writing to
+ *                  the debugsystem
+ * @param {int}     signature the signature that the custom event subscriber
+ *                  will receive. YAHOO.util.CustomEvent.LIST or 
+ *                  YAHOO.util.CustomEvent.FLAT.  The default is
+ *                  YAHOO.util.CustomEvent.LIST.
+ * @namespace YAHOO.util
+ * @class CustomEvent
+ * @constructor
+ */
+YAHOO.util.CustomEvent = function(type, context, silent, signature) {
+
+    /**
+     * The type of event, returned to subscribers when the event fires
+     * @property type
+     * @type string
+     */
+    this.type = type;
+
+    /**
+     * The context the the event will fire from by default.  Defaults to the window 
+     * obj
+     * @property scope
+     * @type object
+     */
+    this.scope = context || window;
+
+    /**
+     * By default all custom events are logged in the debug build, set silent
+     * to true to disable debug outpu for this event.
+     * @property silent
+     * @type boolean
+     */
+    this.silent = silent;
+
+    /**
+     * Custom events support two styles of arguments provided to the event
+     * subscribers.  
+     * <ul>
+     * <li>YAHOO.util.CustomEvent.LIST: 
+     *   <ul>
+     *   <li>param1: event name</li>
+     *   <li>param2: array of arguments sent to fire</li>
+     *   <li>param3: <optional> a custom object supplied by the subscriber</li>
+     *   </ul>
+     * </li>
+     * <li>YAHOO.util.CustomEvent.FLAT
+     *   <ul>
+     *   <li>param1: the first argument passed to fire.  If you need to
+     *           pass multiple parameters, use and array or object literal</li>
+     *   <li>param2: <optional> a custom object supplied by the subscriber</li>
+     *   </ul>
+     * </li>
+     * </ul>
+     *   @property signature
+     *   @type int
+     */
+    this.signature = signature || YAHOO.util.CustomEvent.LIST;
+
+    /**
+     * The subscribers to this event
+     * @property subscribers
+     * @type Subscriber[]
+     */
+    this.subscribers = [];
+
+    if (!this.silent) {
+    }
+
+    var onsubscribeType = "_YUICEOnSubscribe";
+
+    // Only add subscribe events for events that are not generated by 
+    // CustomEvent
+    if (type !== onsubscribeType) {
+
+        /**
+         * Custom events provide a custom event that fires whenever there is
+         * a new subscriber to the event.  This provides an opportunity to
+         * handle the case where there is a non-repeating event that has
+         * already fired has a new subscriber.  
+         *
+         * @event subscribeEvent
+         * @type YAHOO.util.CustomEvent
+         * @param {Function} fn The function to execute
+         * @param {Object}   obj An object to be passed along when the event 
+         *                       fires defaults to the custom event
+         * @param {boolean|Object}  override If true, the obj passed in becomes 
+         *                                   the execution context of the listener.
+         *                                   if an object, that object becomes the
+         *                                   the execution context. defaults to
+         *                                   the custom event
+         */
+        this.subscribeEvent = 
+                new YAHOO.util.CustomEvent(onsubscribeType, this, true);
+
+    } 
+
+
+    /**
+     * In order to make it possible to execute the rest of the subscriber
+     * stack when one thows an exception, the subscribers exceptions are
+     * caught.  The most recent exception is stored in this property
+     * @property lastError
+     * @type Error
+     */
+    this.lastError = null;
+};
+
+/**
+ * Subscriber listener sigature constant.  The LIST type returns three
+ * parameters: the event type, the array of args passed to fire, and
+ * the optional custom object
+ * @property YAHOO.util.CustomEvent.LIST
+ * @static
+ * @type int
+ */
+YAHOO.util.CustomEvent.LIST = 0;
+
+/**
+ * Subscriber listener sigature constant.  The FLAT type returns two
+ * parameters: the first argument passed to fire and the optional 
+ * custom object
+ * @property YAHOO.util.CustomEvent.FLAT
+ * @static
+ * @type int
+ */
+YAHOO.util.CustomEvent.FLAT = 1;
+
+YAHOO.util.CustomEvent.prototype = {
+
+    /**
+     * Subscribes the caller to this event
+     * @method subscribe
+     * @param {Function} fn        The function to execute
+     * @param {Object}   obj       An object to be passed along when the event 
+     *                             fires
+     * @param {boolean|Object}  overrideContext If true, the obj passed in becomes 
+     *                                   the execution context of the listener.
+     *                                   if an object, that object becomes the
+     *                                   the execution context.
+     */
+    subscribe: function(fn, obj, overrideContext) {
+
+        if (!fn) {
+throw new Error("Invalid callback for subscriber to '" + this.type + "'");
+        }
+
+        if (this.subscribeEvent) {
+            this.subscribeEvent.fire(fn, obj, overrideContext);
+        }
+
+        this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, overrideContext) );
+    },
+
+    /**
+     * Unsubscribes subscribers.
+     * @method unsubscribe
+     * @param {Function} fn  The subscribed function to remove, if not supplied
+     *                       all will be removed
+     * @param {Object}   obj  The custom object passed to subscribe.  This is
+     *                        optional, but if supplied will be used to
+     *                        disambiguate multiple listeners that are the same
+     *                        (e.g., you subscribe many object using a function
+     *                        that lives on the prototype)
+     * @return {boolean} True if the subscriber was found and detached.
+     */
+    unsubscribe: function(fn, obj) {
+
+        if (!fn) {
+            return this.unsubscribeAll();
+        }
+
+        var found = false;
+        for (var i=0, len=this.subscribers.length; i<len; ++i) {
+            var s = this.subscribers[i];
+            if (s && s.contains(fn, obj)) {
+                this._delete(i);
+                found = true;
+            }
+        }
+
+        return found;
+    },
+
+    /**
+     * Notifies the subscribers.  The callback functions will be executed
+     * from the context specified when the event was created, and with the 
+     * following parameters:
+     *   <ul>
+     *   <li>The type of event</li>
+     *   <li>All of the arguments fire() was executed with as an array</li>
+     *   <li>The custom object (if any) that was passed into the subscribe() 
+     *       method</li>
+     *   </ul>
+     * @method fire 
+     * @param {Object*} arguments an arbitrary set of parameters to pass to 
+     *                            the handler.
+     * @return {boolean} false if one of the subscribers returned false, 
+     *                   true otherwise
+     */
+    fire: function() {
+
+        this.lastError = null;
+
+        var errors = [],
+            len=this.subscribers.length;
+
+        if (!len && this.silent) {
+            return true;
+        }
+
+        var args=[].slice.call(arguments, 0), ret=true, i, rebuild=false;
+
+        if (!this.silent) {
+        }
+
+        // make a copy of the subscribers so that there are
+        // no index problems if one subscriber removes another.
+        var subs = this.subscribers.slice(), throwErrors = YAHOO.util.Event.throwErrors;
+
+        for (i=0; i<len; ++i) {
+            var s = subs[i];
+            if (!s) {
+                rebuild=true;
+            } else {
+                if (!this.silent) {
+                }
+
+                var scope = s.getScope(this.scope);
+
+                if (this.signature == YAHOO.util.CustomEvent.FLAT) {
+                    var param = null;
+                    if (args.length > 0) {
+                        param = args[0];
+                    }
+
+                    try {
+                        ret = s.fn.call(scope, param, s.obj);
+                    } catch(e) {
+                        this.lastError = e;
+                        // errors.push(e);
+                        if (throwErrors) {
+                            throw e;
+                        }
+                    }
+                } else {
+                    try {
+                        ret = s.fn.call(scope, this.type, args, s.obj);
+                    } catch(ex) {
+                        this.lastError = ex;
+                        if (throwErrors) {
+                            throw ex;
+                        }
+                    }
+                }
+
+                if (false === ret) {
+                    if (!this.silent) {
+                    }
+
+                    break;
+                    // return false;
+                }
+            }
+        }
+
+        return (ret !== false);
+    },
+
+    /**
+     * Removes all listeners
+     * @method unsubscribeAll
+     * @return {int} The number of listeners unsubscribed
+     */
+    unsubscribeAll: function() {
+        var l = this.subscribers.length, i;
+        for (i=l-1; i>-1; i--) {
+            this._delete(i);
+        }
+
+        this.subscribers=[];
+
+        return l;
+    },
+
+    /**
+     * @method _delete
+     * @private
+     */
+    _delete: function(index) {
+        var s = this.subscribers[index];
+        if (s) {
+            delete s.fn;
+            delete s.obj;
+        }
+
+        // this.subscribers[index]=null;
+        this.subscribers.splice(index, 1);
+    },
+
+    /**
+     * @method toString
+     */
+    toString: function() {
+         return "CustomEvent: " + "'" + this.type  + "', " + 
+             "context: " + this.scope;
+
+    }
+};
+
+/////////////////////////////////////////////////////////////////////
+
+/**
+ * Stores the subscriber information to be used when the event fires.
+ * @param {Function} fn       The function to execute
+ * @param {Object}   obj      An object to be passed along when the event fires
+ * @param {boolean}  overrideContext If true, the obj passed in becomes the execution
+ *                            context of the listener
+ * @class Subscriber
+ * @constructor
+ */
+YAHOO.util.Subscriber = function(fn, obj, overrideContext) {
+
+    /**
+     * The callback that will be execute when the event fires
+     * @property fn
+     * @type function
+     */
+    this.fn = fn;
+
+    /**
+     * An optional custom object that will passed to the callback when
+     * the event fires
+     * @property obj
+     * @type object
+     */
+    this.obj = YAHOO.lang.isUndefined(obj) ? null : obj;
+
+    /**
+     * The default execution context for the event listener is defined when the
+     * event is created (usually the object which contains the event).
+     * By setting overrideContext to true, the execution context becomes the custom
+     * object passed in by the subscriber.  If overrideContext is an object, that 
+     * object becomes the context.
+     * @property overrideContext
+     * @type boolean|object
+     */
+    this.overrideContext = overrideContext;
+
+};
+
+/**
+ * Returns the execution context for this listener.  If overrideContext was set to true
+ * the custom obj will be the context.  If overrideContext is an object, that is the
+ * context, otherwise the default context will be used.
+ * @method getScope
+ * @param {Object} defaultScope the context to use if this listener does not
+ *                              override it.
+ */
+YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) {
+    if (this.overrideContext) {
+        if (this.overrideContext === true) {
+            return this.obj;
+        } else {
+            return this.overrideContext;
+        }
+    }
+    return defaultScope;
+};
+
+/**
+ * Returns true if the fn and obj match this objects properties.
+ * Used by the unsubscribe method to match the right subscriber.
+ *
+ * @method contains
+ * @param {Function} fn the function to execute
+ * @param {Object} obj an object to be passed along when the event fires
+ * @return {boolean} true if the supplied arguments match this 
+ *                   subscriber's signature.
+ */
+YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {
+    if (obj) {
+        return (this.fn == fn && this.obj == obj);
+    } else {
+        return (this.fn == fn);
+    }
+};
+
+/**
+ * @method toString
+ */
+YAHOO.util.Subscriber.prototype.toString = function() {
+    return "Subscriber { obj: " + this.obj  + 
+           ", overrideContext: " +  (this.overrideContext || "no") + " }";
+};
+
+/**
+ * The Event Utility provides utilities for managing DOM Events and tools
+ * for building event systems
+ *
+ * @module event
+ * @title Event Utility
+ * @namespace YAHOO.util
+ * @requires yahoo
+ */
+
+// The first instance of Event will win if it is loaded more than once.
+// @TODO this needs to be changed so that only the state data that needs to
+// be preserved is kept, while methods are overwritten/added as needed.
+// This means that the module pattern can't be used.
+if (!YAHOO.util.Event) {
+
+/**
+ * The event utility provides functions to add and remove event listeners,
+ * event cleansing.  It also tries to automatically remove listeners it
+ * registers during the unload event.
+ *
+ * @class Event
+ * @static
+ */
+    YAHOO.util.Event = function() {
+
+        /**
+         * True after the onload event has fired
+         * @property loadComplete
+         * @type boolean
+         * @static
+         * @private
+         */
+        var loadComplete =  false;
+
+        /**
+         * Cache of wrapped listeners
+         * @property listeners
+         * @type array
+         * @static
+         * @private
+         */
+        var listeners = [];
+
+        /**
+         * User-defined unload function that will be fired before all events
+         * are detached
+         * @property unloadListeners
+         * @type array
+         * @static
+         * @private
+         */
+        var unloadListeners = [];
+
+        /**
+         * Cache of DOM0 event handlers to work around issues with DOM2 events
+         * in Safari
+         * @property legacyEvents
+         * @static
+         * @private
+         */
+        var legacyEvents = [];
+
+        /**
+         * Listener stack for DOM0 events
+         * @property legacyHandlers
+         * @static
+         * @private
+         */
+        var legacyHandlers = [];
+
+        /**
+         * The number of times to poll after window.onload.  This number is
+         * increased if additional late-bound handlers are requested after
+         * the page load.
+         * @property retryCount
+         * @static
+         * @private
+         */
+        var retryCount = 0;
+
+        /**
+         * onAvailable listeners
+         * @property onAvailStack
+         * @static
+         * @private
+         */
+        var onAvailStack = [];
+
+        /**
+         * Lookup table for legacy events
+         * @property legacyMap
+         * @static
+         * @private
+         */
+        var legacyMap = [];
+
+        /**
+         * Counter for auto id generation
+         * @property counter
+         * @static
+         * @private
+         */
+        var counter = 0;
+        
+        /**
+         * Normalized keycodes for webkit/safari
+         * @property webkitKeymap
+         * @type {int: int}
+         * @private
+         * @static
+         * @final
+         */
+        var webkitKeymap = {
+            63232: 38, // up
+            63233: 40, // down
+            63234: 37, // left
+            63235: 39, // right
+            63276: 33, // page up
+            63277: 34, // page down
+            25: 9      // SHIFT-TAB (Safari provides a different key code in
+                       // this case, even though the shiftKey modifier is set)
+        };
+        
+        // String constants used by the addFocusListener and removeFocusListener methods
+        var _FOCUS = YAHOO.env.ua.ie ? "focusin" : "focus";
+        var _BLUR = YAHOO.env.ua.ie ? "focusout" : "blur";      
+
+        return {
+
+            /**
+             * The number of times we should look for elements that are not
+             * in the DOM at the time the event is requested after the document
+             * has been loaded.  The default is 2000@amp;20 ms, so it will poll
+             * for 40 seconds or until all outstanding handlers are bound
+             * (whichever comes first).
+             * @property POLL_RETRYS
+             * @type int
+             * @static
+             * @final
+             */
+            POLL_RETRYS: 2000,
+
+            /**
+             * The poll interval in milliseconds
+             * @property POLL_INTERVAL
+             * @type int
+             * @static
+             * @final
+             */
+            POLL_INTERVAL: 20,
+
+            /**
+             * Element to bind, int constant
+             * @property EL
+             * @type int
+             * @static
+             * @final
+             */
+            EL: 0,
+
+            /**
+             * Type of event, int constant
+             * @property TYPE
+             * @type int
+             * @static
+             * @final
+             */
+            TYPE: 1,
+
+            /**
+             * Function to execute, int constant
+             * @property FN
+             * @type int
+             * @static
+             * @final
+             */
+            FN: 2,
+
+            /**
+             * Function wrapped for context correction and cleanup, int constant
+             * @property WFN
+             * @type int
+             * @static
+             * @final
+             */
+            WFN: 3,
+
+            /**
+             * Object passed in by the user that will be returned as a 
+             * parameter to the callback, int constant.  Specific to
+             * unload listeners
+             * @property OBJ
+             * @type int
+             * @static
+             * @final
+             */
+            UNLOAD_OBJ: 3,
+
+            /**
+             * Adjusted context, either the element we are registering the event
+             * on or the custom object passed in by the listener, int constant
+             * @property ADJ_SCOPE
+             * @type int
+             * @static
+             * @final
+             */
+            ADJ_SCOPE: 4,
+
+            /**
+             * The original obj passed into addListener
+             * @property OBJ
+             * @type int
+             * @static
+             * @final
+             */
+            OBJ: 5,
+
+            /**
+             * The original context parameter passed into addListener
+             * @property OVERRIDE
+             * @type int
+             * @static
+             * @final
+             */
+            OVERRIDE: 6,
+
+            /**
+             * addListener/removeListener can throw errors in unexpected scenarios.
+             * These errors are suppressed, the method returns false, and this property
+             * is set
+             * @property lastError
+             * @static
+             * @type Error
+             */
+            lastError: null,
+
+            /**
+             * Safari detection
+             * @property isSafari
+             * @private
+             * @static
+             * @deprecated use YAHOO.env.ua.webkit
+             */
+            isSafari: YAHOO.env.ua.webkit,
+            
+            /**
+             * webkit version
+             * @property webkit
+             * @type string
+             * @private
+             * @static
+             * @deprecated use YAHOO.env.ua.webkit
+             */
+            webkit: YAHOO.env.ua.webkit,
+            
+            /**
+             * IE detection 
+             * @property isIE
+             * @private
+             * @static
+             * @deprecated use YAHOO.env.ua.ie
+             */
+            isIE: YAHOO.env.ua.ie,
+
+            /**
+             * poll handle
+             * @property _interval
+             * @static
+             * @private
+             */
+            _interval: null,
+
+            /**
+             * document readystate poll handle
+             * @property _dri
+             * @static
+             * @private
+             */
+             _dri: null,
+
+            /**
+             * True when the document is initially usable
+             * @property DOMReady
+             * @type boolean
+             * @static
+             */
+            DOMReady: false,
+
+            /**
+             * Errors thrown by subscribers of custom events are caught
+             * and the error message is written to the debug console.  If
+             * this property is set to true, it will also re-throw the
+             * error.
+             * @property throwErrors
+             * @type boolean
+             * @default false
+             */
+            throwErrors: false,
+
+            /**
+             * @method startInterval
+             * @static
+             * @private
+             */
+            startInterval: function() {
+                if (!this._interval) {
+                    var self = this;
+                    var callback = function() { self._tryPreloadAttach(); };
+                    this._interval = setInterval(callback, this.POLL_INTERVAL);
+                }
+            },
+
+            /**
+             * Executes the supplied callback when the item with the supplied
+             * id is found.  This is meant to be used to execute behavior as
+             * soon as possible as the page loads.  If you use this after the
+             * initial page load it will poll for a fixed time for the element.
+             * The number of times it will poll and the frequency are
+             * configurable.  By default it will poll for 10 seconds.
+             *
+             * <p>The callback is executed with a single parameter:
+             * the custom object parameter, if provided.</p>
+             *
+             * @method onAvailable
+             *
+             * @param {string||string[]}   id the id of the element, or an array
+             * of ids to look for.
+             * @param {function} fn what to execute when the element is found.
+             * @param {object}   obj an optional object to be passed back as
+             *                   a parameter to fn.
+             * @param {boolean|object}  overrideContext If set to true, fn will execute
+             *                   in the context of obj, if set to an object it
+             *                   will execute in the context of that object
+             * @param checkContent {boolean} check child node readiness (onContentReady)
+             * @static
+             */
+            onAvailable: function(id, fn, obj, overrideContext, checkContent) {
+
+                var a = (YAHOO.lang.isString(id)) ? [id] : id;
+
+                for (var i=0; i<a.length; i=i+1) {
+                    onAvailStack.push({id:         a[i], 
+                                       fn:         fn, 
+                                       obj:        obj, 
+                                       overrideContext:   overrideContext, 
+                                       checkReady: checkContent });
+                }
+
+                retryCount = this.POLL_RETRYS;
+
+                this.startInterval();
+            },
+
+            /**
+             * Works the same way as onAvailable, but additionally checks the
+             * state of sibling elements to determine if the content of the
+             * available element is safe to modify.
+             *
+             * <p>The callback is executed with a single parameter:
+             * the custom object parameter, if provided.</p>
+             *
+             * @method onContentReady
+             *
+             * @param {string}   id the id of the element to look for.
+             * @param {function} fn what to execute when the element is ready.
+             * @param {object}   obj an optional object to be passed back as
+             *                   a parameter to fn.
+             * @param {boolean|object}  overrideContext If set to true, fn will execute
+             *                   in the context of obj.  If an object, fn will
+             *                   exectute in the context of that object
+             *
+             * @static
+             */
+            onContentReady: function(id, fn, obj, overrideContext) {
+                this.onAvailable(id, fn, obj, overrideContext, true);
+            },
+
+            /**
+             * Executes the supplied callback when the DOM is first usable.  This
+             * will execute immediately if called after the DOMReady event has
+             * fired.   @todo the DOMContentReady event does not fire when the
+             * script is dynamically injected into the page.  This means the
+             * DOMReady custom event will never fire in FireFox or Opera when the
+             * library is injected.  It _will_ fire in Safari, and the IE 
+             * implementation would allow for us to fire it if the defered script
+             * is not available.  We want this to behave the same in all browsers.
+             * Is there a way to identify when the script has been injected 
+             * instead of included inline?  Is there a way to know whether the 
+             * window onload event has fired without having had a listener attached 
+             * to it when it did so?
+             *
+             * <p>The callback is a CustomEvent, so the signature is:</p>
+             * <p>type &lt;string&gt;, args &lt;array&gt;, customobject &lt;object&gt;</p>
+             * <p>For DOMReady events, there are no fire argments, so the
+             * signature is:</p>
+             * <p>"DOMReady", [], obj</p>
+             *
+             *
+             * @method onDOMReady
+             *
+             * @param {function} fn what to execute when the element is found.
+             * @param {object}   obj an optional object to be passed back as
+             *                   a parameter to fn.
+             * @param {boolean|object}  overrideContext If set to true, fn will execute
+             *                   in the context of obj, if set to an object it
+             *                   will execute in the context of that object
+             *
+             * @static
+             */
+            onDOMReady: function(fn, obj, overrideContext) {
+                if (this.DOMReady) {
+                    setTimeout(function() {
+                        var s = window;
+                        if (overrideContext) {
+                            if (overrideContext === true) {
+                                s = obj;
+                            } else {
+                                s = overrideContext;
+                            }
+                        }
+                        fn.call(s, "DOMReady", [], obj);
+                    }, 0);
+                } else {
+                    this.DOMReadyEvent.subscribe(fn, obj, overrideContext);
+                }
+            },
+
+
+            /**
+             * Appends an event handler
+             *
+             * @method _addListener
+             *
+             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
+             *  reference, or a collection of ids and/or elements to assign the 
+             *  listener to.
+             * @param {String}   sType     The type of event to append
+             * @param {Function} fn        The method the event invokes
+             * @param {Object}   obj    An arbitrary object that will be 
+             *                             passed as a parameter to the handler
+             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
+             *                             the execution context of the listener. If an
+             *                             object, this object becomes the execution
+             *                             context.
+             * @param {boolen}      capture capture or bubble phase
+             * @return {Boolean} True if the action was successful or defered,
+             *                        false if one or more of the elements 
+             *                        could not have the listener attached,
+             *                        or if the operation throws an exception.
+             * @private
+             * @static
+             */
+            _addListener: function(el, sType, fn, obj, overrideContext, bCapture) {
+
+                if (!fn || !fn.call) {
+                    return false;
+                }
+
+                // The el argument can be an array of elements or element ids.
+                if ( this._isValidCollection(el)) {
+                    var ok = true;
+                    for (var i=0,len=el.length; i<len; ++i) {
+                        ok = this.on(el[i], 
+                                       sType, 
+                                       fn, 
+                                       obj, 
+                                       overrideContext) && ok;
+                    }
+                    return ok;
+
+                } else if (YAHOO.lang.isString(el)) {
+                    var oEl = this.getEl(el);
+                    // If the el argument is a string, we assume it is 
+                    // actually the id of the element.  If the page is loaded
+                    // we convert el to the actual element, otherwise we 
+                    // defer attaching the event until onload event fires
+
+                    // check to see if we need to delay hooking up the event 
+                    // until after the page loads.
+                    if (oEl) {
+                        el = oEl;
+                    } else {
+                        // defer adding the event until the element is available
+                        this.onAvailable(el, function() {
+                           YAHOO.util.Event.on(el, sType, fn, obj, overrideContext);
+                        });
+
+                        return true;
+                    }
+                }
+
+                // Element should be an html element or an array if we get 
+                // here.
+                if (!el) {
+                    return false;
+                }
+
+                // we need to make sure we fire registered unload events 
+                // prior to automatically unhooking them.  So we hang on to 
+                // these instead of attaching them to the window and fire the
+                // handles explicitly during our one unload event.
+                if ("unload" == sType && obj !== this) {
+                    unloadListeners[unloadListeners.length] =
+                            [el, sType, fn, obj, overrideContext];
+                    return true;
+                }
+
+
+                // if the user chooses to override the context, we use the custom
+                // object passed in, otherwise the executing context will be the
+                // HTML element that the event is registered on
+                var context = el;
+                if (overrideContext) {
+                    if (overrideContext === true) {
+                        context = obj;
+                    } else {
+                        context = overrideContext;
+                    }
+                }
+
+                // wrap the function so we can return the obj object when
+                // the event fires;
+                var wrappedFn = function(e) {
+                        return fn.call(context, YAHOO.util.Event.getEvent(e, el), 
+                                obj);
+                    };
+
+                var li = [el, sType, fn, wrappedFn, context, obj, overrideContext];
+                var index = listeners.length;
+                // cache the listener so we can try to automatically unload
+                listeners[index] = li;
+
+                if (this.useLegacyEvent(el, sType)) {
+                    var legacyIndex = this.getLegacyIndex(el, sType);
+
+                    // Add a new dom0 wrapper if one is not detected for this
+                    // element
+                    if ( legacyIndex == -1 || 
+                                el != legacyEvents[legacyIndex][0] ) {
+
+                        legacyIndex = legacyEvents.length;
+                        legacyMap[el.id + sType] = legacyIndex;
+
+                        // cache the signature for the DOM0 event, and 
+                        // include the existing handler for the event, if any
+                        legacyEvents[legacyIndex] = 
+                            [el, sType, el["on" + sType]];
+                        legacyHandlers[legacyIndex] = [];
+
+                        el["on" + sType] = 
+                            function(e) {
+                                YAHOO.util.Event.fireLegacyEvent(
+                                    YAHOO.util.Event.getEvent(e), legacyIndex);
+                            };
+                    }
+
+                    // add a reference to the wrapped listener to our custom
+                    // stack of events
+                    //legacyHandlers[legacyIndex].push(index);
+                    legacyHandlers[legacyIndex].push(li);
+
+                } else {
+                    try {
+                        this._simpleAdd(el, sType, wrappedFn, bCapture);
+                    } catch(ex) {
+                        // handle an error trying to attach an event.  If it fails
+                        // we need to clean up the cache
+                        this.lastError = ex;
+                        this.removeListener(el, sType, fn);
+                        return false;
+                    }
+                }
+
+                return true;
+                
+            },
+
+
+            /**
+             * Appends an event handler
+             *
+             * @method addListener
+             *
+             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
+             *  reference, or a collection of ids and/or elements to assign the 
+             *  listener to.
+             * @param {String}   sType     The type of event to append
+             * @param {Function} fn        The method the event invokes
+             * @param {Object}   obj    An arbitrary object that will be 
+             *                             passed as a parameter to the handler
+             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
+             *                             the execution context of the listener. If an
+             *                             object, this object becomes the execution
+             *                             context.
+             * @return {Boolean} True if the action was successful or defered,
+             *                        false if one or more of the elements 
+             *                        could not have the listener attached,
+             *                        or if the operation throws an exception.
+             * @static
+             */
+            addListener: function (el, sType, fn, obj, overrideContext) {
+                return this._addListener(el, sType, fn, obj, overrideContext, false);
+            },
+
+            /**
+             * Appends a focus event handler.  (The focusin event is used for Internet Explorer, 
+             * the focus, capture-event for Opera, WebKit.)
+             *
+             * @method addFocusListener
+             *
+             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
+             *  reference, or a collection of ids and/or elements to assign the 
+             *  listener to.
+             * @param {Function} fn        The method the event invokes
+             * @param {Object}   obj    An arbitrary object that will be 
+             *                             passed as a parameter to the handler
+             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
+             *                             the execution context of the listener. If an
+             *                             object, this object becomes the execution
+             *                             context.
+             * @return {Boolean} True if the action was successful or defered,
+             *                        false if one or more of the elements 
+             *                        could not have the listener attached,
+             *                        or if the operation throws an exception.
+             * @static
+             */
+            addFocusListener: function (el, fn, obj, overrideContext) {
+                return this._addListener(el, _FOCUS, fn, obj, overrideContext, true);
+            },          
+
+
+            /**
+             * Removes a focus event listener
+             *
+             * @method removeListener
+             *
+             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
+             *  reference, or a collection of ids and/or elements to remove
+             *  the listener from.
+             * @param {Function} fn the method the event invokes.  If fn is
+             *  undefined, then all event handlers for the type of event are 
+             *  removed.
+             * @return {boolean} true if the unbind was successful, false 
+             *  otherwise.
+             * @static
+             */
+            removeFocusListener: function (el, fn) { 
+                return this.removeListener(el, _FOCUS, fn);
+            },
+
+            /**
+             * Appends a blur event handler.  (The focusout event is used for Internet Explorer, 
+             * the focusout, capture-event for Opera, WebKit.)
+             *
+             * @method addBlurListener
+             *
+             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
+             *  reference, or a collection of ids and/or elements to assign the 
+             *  listener to.
+             * @param {Function} fn        The method the event invokes
+             * @param {Object}   obj    An arbitrary object that will be 
+             *                             passed as a parameter to the handler
+             * @param {Boolean|object}  overrideContext  If true, the obj passed in becomes
+             *                             the execution context of the listener. If an
+             *                             object, this object becomes the execution
+             *                             context.
+             * @return {Boolean} True if the action was successful or defered,
+             *                        false if one or more of the elements 
+             *                        could not have the listener attached,
+             *                        or if the operation throws an exception.
+             * @static
+             */
+            addBlurListener: function (el, fn, obj, overrideContext) {
+                return this._addListener(el, _BLUR, fn, obj, overrideContext, true);
+            },          
+
+            /**
+             * Removes a blur event listener
+             *
+             * @method removeListener
+             *
+             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
+             *  reference, or a collection of ids and/or elements to remove
+             *  the listener from.
+             * @param {Function} fn the method the event invokes.  If fn is
+             *  undefined, then all event handlers for the type of event are 
+             *  removed.
+             * @return {boolean} true if the unbind was successful, false 
+             *  otherwise.
+             * @static
+             */
+            removeBlurListener: function (el, fn) { 
+            
+                return this.removeListener(el, _BLUR, fn);
+            
+            },
+
+            /**
+             * When using legacy events, the handler is routed to this object
+             * so we can fire our custom listener stack.
+             * @method fireLegacyEvent
+             * @static
+             * @private
+             */
+            fireLegacyEvent: function(e, legacyIndex) {
+                var ok=true, le, lh, li, context, ret;
+                
+                lh = legacyHandlers[legacyIndex].slice();
+                for (var i=0, len=lh.length; i<len; ++i) {
+                // for (var i in lh.length) {
+                    li = lh[i];
+                    if ( li && li[this.WFN] ) {
+                        context = li[this.ADJ_SCOPE];
+                        ret = li[this.WFN].call(context, e);
+                        ok = (ok && ret);
+                    }
+                }
+
+                // Fire the original handler if we replaced one.  We fire this
+                // after the other events to keep stopPropagation/preventDefault
+                // that happened in the DOM0 handler from touching our DOM2
+                // substitute
+                le = legacyEvents[legacyIndex];
+                if (le && le[2]) {
+                    le[2](e);
+                }
+                
+                return ok;
+            },
+
+            /**
+             * Returns the legacy event index that matches the supplied 
+             * signature
+             * @method getLegacyIndex
+             * @static
+             * @private
+             */
+            getLegacyIndex: function(el, sType) {
+                var key = this.generateId(el) + sType;
+                if (typeof legacyMap[key] == "undefined") { 
+                    return -1;
+                } else {
+                    return legacyMap[key];
+                }
+            },
+
+            /**
+             * Logic that determines when we should automatically use legacy
+             * events instead of DOM2 events.  Currently this is limited to old
+             * Safari browsers with a broken preventDefault
+             * @method useLegacyEvent
+             * @static
+             * @private
+             */
+            useLegacyEvent: function(el, sType) {
+return (this.webkit && this.webkit < 419 && ("click"==sType || "dblclick"==sType));
+            },
+                    
+            /**
+             * Removes an event listener
+             *
+             * @method removeListener
+             *
+             * @param {String|HTMLElement|Array|NodeList} el An id, an element 
+             *  reference, or a collection of ids and/or elements to remove
+             *  the listener from.
+             * @param {String} sType the type of event to remove.
+             * @param {Function} fn the method the event invokes.  If fn is
+             *  undefined, then all event handlers for the type of event are 
+             *  removed.
+             * @return {boolean} true if the unbind was successful, false 
+             *  otherwise.
+             * @static
+             */
+            removeListener: function(el, sType, fn) {
+                var i, len, li;
+
+                // The el argument can be a string
+                if (typeof el == "string") {
+                    el = this.getEl(el);
+                // The el argument can be an array of elements or element ids.
+                } else if ( this._isValidCollection(el)) {
+                    var ok = true;
+                    for (i=el.length-1; i>-1; i--) {
+                        ok = ( this.removeListener(el[i], sType, fn) && ok );
+                    }
+                    return ok;
+                }
+
+                if (!fn || !fn.call) {
+                    //return false;
+                    return this.purgeElement(el, false, sType);
+                }
+
+                if ("unload" == sType) {
+
+                    for (i=unloadListeners.length-1; i>-1; i--) {
+                        li = unloadListeners[i];
+                        if (li && 
+                            li[0] == el && 
+                            li[1] == sType && 
+                            li[2] == fn) {
+                                unloadListeners.splice(i, 1);
+                                // unloadListeners[i]=null;
+                                return true;
+                        }
+                    }
+
+                    return false;
+                }
+
+                var cacheItem = null;
+
+                // The index is a hidden parameter; needed to remove it from
+                // the method signature because it was tempting users to
+                // try and take advantage of it, which is not possible.
+                var index = arguments[3];
+  
+                if ("undefined" === typeof index) {
+                    index = this._getCacheIndex(el, sType, fn);
+                }
+
+                if (index >= 0) {
+                    cacheItem = listeners[index];
+                }
+
+                if (!el || !cacheItem) {
+                    return false;
+                }
+
+
+                if (this.useLegacyEvent(el, sType)) {
+                    var legacyIndex = this.getLegacyIndex(el, sType);
+                    var llist = legacyHandlers[legacyIndex];
+                    if (llist) {
+                        for (i=0, len=llist.length; i<len; ++i) {
+                        // for (i in llist.length) {
+                            li = llist[i];
+                            if (li && 
+                                li[this.EL] == el && 
+                                li[this.TYPE] == sType && 
+                                li[this.FN] == fn) {
+                                    llist.splice(i, 1);
+                                    // llist[i]=null;
+                                    break;
+                            }
+                        }
+                    }
+
+                } else {
+                    try {
+                        this._simpleRemove(el, sType, cacheItem[this.WFN], false);
+                    } catch(ex) {
+                        this.lastError = ex;
+                        return false;
+                    }
+                }
+
+                // removed the wrapped handler
+                delete listeners[index][this.WFN];
+                delete listeners[index][this.FN];
+                listeners.splice(index, 1);
+                // listeners[index]=null;
+
+                return true;
+
+            },
+
+            /**
+             * Returns the event's target element.  Safari sometimes provides
+             * a text node, and this is automatically resolved to the text
+             * node's parent so that it behaves like other browsers.
+             * @method getTarget
+             * @param {Event} ev the event
+             * @param {boolean} resolveTextNode when set to true the target's
+             *                  parent will be returned if the target is a 
+             *                  text node.  @deprecated, the text node is
+             *                  now resolved automatically
+             * @return {HTMLElement} the event's target
+             * @static
+             */
+            getTarget: function(ev, resolveTextNode) {
+                var t = ev.target || ev.srcElement;
+                return this.resolveTextNode(t);
+            },
+
+            /**
+             * In some cases, some browsers will return a text node inside
+             * the actual element that was targeted.  This normalizes the
+             * return value for getTarget and getRelatedTarget.
+             * @method resolveTextNode
+             * @param {HTMLElement} node node to resolve
+             * @return {HTMLElement} the normized node
+             * @static
+             */
+            resolveTextNode: function(n) {
+                try {
+                    if (n && 3 == n.nodeType) {
+                        return n.parentNode;
+                    }
+                } catch(e) { }
+
+                return n;
+            },
+
+            /**
+             * Returns the event's pageX
+             * @method getPageX
+             * @param {Event} ev the event
+             * @return {int} the event's pageX
+             * @static
+             */
+            getPageX: function(ev) {
+                var x = ev.pageX;
+                if (!x && 0 !== x) {
+                    x = ev.clientX || 0;
+
+                    if ( this.isIE ) {
+                        x += this._getScrollLeft();
+                    }
+                }
+
+                return x;
+            },
+
+            /**
+             * Returns the event's pageY
+             * @method getPageY
+             * @param {Event} ev the event
+             * @return {int} the event's pageY
+             * @static
+             */
+            getPageY: function(ev) {
+                var y = ev.pageY;
+                if (!y && 0 !== y) {
+                    y = ev.clientY || 0;
+
+                    if ( this.isIE ) {
+                        y += this._getScrollTop();
+                    }
+                }
+
+
+                return y;
+            },
+
+            /**
+             * Returns the pageX and pageY properties as an indexed array.
+             * @method getXY
+             * @param {Event} ev the event
+             * @return {[x, y]} the pageX and pageY properties of the event
+             * @static
+             */
+            getXY: function(ev) {
+                return [this.getPageX(ev), this.getPageY(ev)];
+            },
+
+            /**
+             * Returns the event's related target 
+             * @method getRelatedTarget
+             * @param {Event} ev the event
+             * @return {HTMLElement} the event's relatedTarget
+             * @static
+             */
+            getRelatedTarget: function(ev) {
+                var t = ev.relatedTarget;
+                if (!t) {
+                    if (ev.type == "mouseout") {
+                        t = ev.toElement;
+                    } else if (ev.type == "mouseover") {
+                        t = ev.fromElement;
+                    }
+                }
+
+                return this.resolveTextNode(t);
+            },
+
+            /**
+             * Returns the time of the event.  If the time is not included, the
+             * event is modified using the current time.
+             * @method getTime
+             * @param {Event} ev the event
+             * @return {Date} the time of the event
+             * @static
+             */
+            getTime: function(ev) {
+                if (!ev.time) {
+                    var t = new Date().getTime();
+                    try {
+                        ev.time = t;
+                    } catch(ex) { 
+                        this.lastError = ex;
+                        return t;
+                    }
+                }
+
+                return ev.time;
+            },
+
+            /**
+             * Convenience method for stopPropagation + preventDefault
+             * @method stopEvent
+             * @param {Event} ev the event
+             * @static
+             */
+            stopEvent: function(ev) {
+                this.stopPropagation(ev);
+                this.preventDefault(ev);
+            },
+
+            /**
+             * Stops event propagation
+             * @method stopPropagation
+             * @param {Event} ev the event
+             * @static
+             */
+            stopPropagation: function(ev) {
+                if (ev.stopPropagation) {
+                    ev.stopPropagation();
+                } else {
+                    ev.cancelBubble = true;
+                }
+            },
+
+            /**
+             * Prevents the default behavior of the event
+             * @method preventDefault
+             * @param {Event} ev the event
+             * @static
+             */
+            preventDefault: function(ev) {
+                if (ev.preventDefault) {
+                    ev.preventDefault();
+                } else {
+                    ev.returnValue = false;
+                }
+            },
+             
+            /**
+             * Finds the event in the window object, the caller's arguments, or
+             * in the arguments of another method in the callstack.  This is
+             * executed automatically for events registered through the event
+             * manager, so the implementer should not normally need to execute
+             * this function at all.
+             * @method getEvent
+             * @param {Event} e the event parameter from the handler
+             * @param {HTMLElement} boundEl the element the listener is attached to
+             * @return {Event} the event 
+             * @static
+             */
+            getEvent: function(e, boundEl) {
+                var ev = e || window.event;
+
+                if (!ev) {
+                    var c = this.getEvent.caller;
+                    while (c) {
+                        ev = c.arguments[0];
+                        if (ev && Event == ev.constructor) {
+                            break;
+                        }
+                        c = c.caller;
+                    }
+                }
+
+                return ev;
+            },
+
+            /**
+             * Returns the charcode for an event
+             * @method getCharCode
+             * @param {Event} ev the event
+             * @return {int} the event's charCode
+             * @static
+             */
+            getCharCode: function(ev) {
+                var code = ev.keyCode || ev.charCode || 0;
+
+                // webkit key normalization
+                if (YAHOO.env.ua.webkit && (code in webkitKeymap)) {
+                    code = webkitKeymap[code];
+                }
+                return code;
+            },
+
+            /**
+             * Locating the saved event handler data by function ref
+             *
+             * @method _getCacheIndex
+             * @static
+             * @private
+             */
+            _getCacheIndex: function(el, sType, fn) {
+                for (var i=0, l=listeners.length; i<l; i=i+1) {
+                    var li = listeners[i];
+                    if ( li                 && 
+                         li[this.FN] == fn  && 
+                         li[this.EL] == el  && 
+                         li[this.TYPE] == sType ) {
+                        return i;
+                    }
+                }
+
+                return -1;
+            },
+
+            /**
+             * Generates an unique ID for the element if it does not already 
+             * have one.
+             * @method generateId
+             * @param el the element to create the id for
+             * @return {string} the resulting id of the element
+             * @static
+             */
+            generateId: function(el) {
+                var id = el.id;
+
+                if (!id) {
+                    id = "yuievtautoid-" + counter;
+                    ++counter;
+                    el.id = id;
+                }
+
+                return id;
+            },
+
+
+            /**
+             * We want to be able to use getElementsByTagName as a collection
+             * to attach a group of events to.  Unfortunately, different 
+             * browsers return different types of collections.  This function
+             * tests to determine if the object is array-like.  It will also 
+             * fail if the object is an array, but is empty.
+             * @method _isValidCollection
+             * @param o the object to test
+             * @return {boolean} true if the object is array-like and populated
+             * @static
+             * @private
+             */
+            _isValidCollection: function(o) {
+                try {
+                    return ( o                     && // o is something
+                             typeof o !== "string" && // o is not a string
+                             o.length              && // o is indexed
+                             !o.tagName            && // o is not an HTML element
+                             !o.alert              && // o is not a window
+                             typeof o[0] !== "undefined" );
+                } catch(ex) {
+                    return false;
+                }
+
+            },
+
+            /**
+             * @private
+             * @property elCache
+             * DOM element cache
+             * @static
+             * @deprecated Elements are not cached due to issues that arise when
+             * elements are removed and re-added
+             */
+            elCache: {},
+
+            /**
+             * We cache elements bound by id because when the unload event 
+             * fires, we can no longer use document.getElementById
+             * @method getEl
+             * @static
+             * @private
+             * @deprecated Elements are not cached any longer
+             */
+            getEl: function(id) {
+                return (typeof id === "string") ? document.getElementById(id) : id;
+            },
+
+            /**
+             * Clears the element cache
+             * @deprecated Elements are not cached any longer
+             * @method clearCache
+             * @static
+             * @private
+             */
+            clearCache: function() { },
+
+            /**
+             * Custom event the fires when the dom is initially usable
+             * @event DOMReadyEvent
+             */
+            DOMReadyEvent: new YAHOO.util.CustomEvent("DOMReady", this),
+
+            /**
+             * hook up any deferred listeners
+             * @method _load
+             * @static
+             * @private
+             */
+            _load: function(e) {
+
+                if (!loadComplete) {
+                    loadComplete = true;
+                    var EU = YAHOO.util.Event;
+
+                    // Just in case DOMReady did not go off for some reason
+                    EU._ready();
+
+                    // Available elements may not have been detected before the
+                    // window load event fires. Try to find them now so that the
+                    // the user is more likely to get the onAvailable notifications
+                    // before the window load notification
+                    EU._tryPreloadAttach();
+
+                }
+            },
+
+            /**
+             * Fires the DOMReady event listeners the first time the document is
+             * usable.
+             * @method _ready
+             * @static
+             * @private
+             */
+            _ready: function(e) {
+                var EU = YAHOO.util.Event;
+                if (!EU.DOMReady) {
+                    EU.DOMReady=true;
+
+                    // Fire the content ready custom event
+                    EU.DOMReadyEvent.fire();
+
+                    // Remove the DOMContentLoaded (FF/Opera)
+                    EU._simpleRemove(document, "DOMContentLoaded", EU._ready);
+                }
+            },
+
+            /**
+             * Polling function that runs before the onload event fires, 
+             * attempting to attach to DOM Nodes as soon as they are 
+             * available
+             * @method _tryPreloadAttach
+             * @static
+             * @private
+             */
+            _tryPreloadAttach: function() {
+
+                if (onAvailStack.length === 0) {
+                    retryCount = 0;
+                    if (this._interval) {
+                        clearInterval(this._interval);
+                        this._interval = null;
+                    } 
+                    return;
+                }
+
+                if (this.locked) {
+                    return;
+                }
+
+                if (this.isIE) {
+                    // Hold off if DOMReady has not fired and check current
+                    // readyState to protect against the IE operation aborted
+                    // issue.
+                    if (!this.DOMReady) {
+                        this.startInterval();
+                        return;
+                    }
+                }
+
+                this.locked = true;
+
+
+                // keep trying until after the page is loaded.  We need to 
+                // check the page load state prior to trying to bind the 
+                // elements so that we can be certain all elements have been 
+                // tested appropriately
+                var tryAgain = !loadComplete;
+                if (!tryAgain) {
+                    tryAgain = (retryCount > 0 && onAvailStack.length > 0);
+                }
+
+                // onAvailable
+                var notAvail = [];
+
+                var executeItem = function (el, item) {
+                    var context = el;
+                    if (item.overrideContext) {
+                        if (item.overrideContext === true) {
+                            context = item.obj;
+                        } else {
+                            context = item.overrideContext;
+                        }
+                    }
+                    item.fn.call(context, item.obj);
+                };
+
+                var i, len, item, el, ready=[];
+
+                // onAvailable onContentReady
+                for (i=0, len=onAvailStack.length; i<len; i=i+1) {
+                    item = onAvailStack[i];
+                    if (item) {
+                        el = this.getEl(item.id);
+                        if (el) {
+                            if (item.checkReady) {
+                                if (loadComplete || el.nextSibling || !tryAgain) {
+                                    ready.push(item);
+                                    onAvailStack[i] = null;
+                                }
+                            } else {
+                                executeItem(el, item);
+                                onAvailStack[i] = null;
+                            }
+                        } else {
+                            notAvail.push(item);
+                        }
+                    }
+                }
+                
+                // make sure onContentReady fires after onAvailable
+                for (i=0, len=ready.length; i<len; i=i+1) {
+                    item = ready[i];
+                    executeItem(this.getEl(item.id), item);
+                }
+
+
+                retryCount--;
+
+                if (tryAgain) {
+                    for (i=onAvailStack.length-1; i>-1; i--) {
+                        item = onAvailStack[i];
+                        if (!item || !item.id) {
+                            onAvailStack.splice(i, 1);
+                        }
+                    }
+
+                    this.startInterval();
+                } else {
+                    if (this._interval) {
+                        clearInterval(this._interval);
+                        this._interval = null;
+                    }
+                }
+
+                this.locked = false;
+
+            },
+
+            /**
+             * Removes all listeners attached to the given element via addListener.
+             * Optionally, the node's children can also be purged.
+             * Optionally, you can specify a specific type of event to remove.
+             * @method purgeElement
+             * @param {HTMLElement} el the element to purge
+             * @param {boolean} recurse recursively purge this element's children
+             * as well.  Use with caution.
+             * @param {string} sType optional type of listener to purge. If
+             * left out, all listeners will be removed
+             * @static
+             */
+            purgeElement: function(el, recurse, sType) {
+                var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el;
+                var elListeners = this.getListeners(oEl, sType), i, len;
+                if (elListeners) {
+                    for (i=elListeners.length-1; i>-1; i--) {
+                        var l = elListeners[i];
+                        this.removeListener(oEl, l.type, l.fn);
+                    }
+                }
+
+                if (recurse && oEl && oEl.childNodes) {
+                    for (i=0,len=oEl.childNodes.length; i<len ; ++i) {
+                        this.purgeElement(oEl.childNodes[i], recurse, sType);
+                    }
+                }
+            },
+
+            /**
+             * Returns all listeners attached to the given element via addListener.
+             * Optionally, you can specify a specific type of event to return.
+             * @method getListeners
+             * @param el {HTMLElement|string} the element or element id to inspect 
+             * @param sType {string} optional type of listener to return. If
+             * left out, all listeners will be returned
+             * @return {Object} the listener. Contains the following fields:
+             * &nbsp;&nbsp;type:   (string)   the type of event
+             * &nbsp;&nbsp;fn:     (function) the callback supplied to addListener
+             * &nbsp;&nbsp;obj:    (object)   the custom object supplied to addListener
+             * &nbsp;&nbsp;adjust: (boolean|object)  whether or not to adjust the default context
+             * &nbsp;&nbsp;scope: (boolean)  the derived context based on the adjust parameter
+             * &nbsp;&nbsp;index:  (int)      its position in the Event util listener cache
+             * @static
+             */           
+            getListeners: function(el, sType) {
+                var results=[], searchLists;
+                if (!sType) {
+                    searchLists = [listeners, unloadListeners];
+                } else if (sType === "unload") {
+                    searchLists = [unloadListeners];
+                } else {
+                    searchLists = [listeners];
+                }
+
+                var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el;
+
+                for (var j=0;j<searchLists.length; j=j+1) {
+                    var searchList = searchLists[j];
+                    if (searchList) {
+                        for (var i=0,len=searchList.length; i<len ; ++i) {
+                            var l = searchList[i];
+                            if ( l  && l[this.EL] === oEl && 
+                                    (!sType || sType === l[this.TYPE]) ) {
+                                results.push({
+                                    type:   l[this.TYPE],
+                                    fn:     l[this.FN],
+                                    obj:    l[this.OBJ],
+                                    adjust: l[this.OVERRIDE],
+                                    scope:  l[this.ADJ_SCOPE],
+                                    index:  i
+                                });
+                            }
+                        }
+                    }
+                }
+
+                return (results.length) ? results : null;
+            },
+
+            /**
+             * Removes all listeners registered by pe.event.  Called 
+             * automatically during the unload event.
+             * @method _unload
+             * @static
+             * @private
+             */
+            _unload: function(e) {
+
+                var EU = YAHOO.util.Event, i, j, l, len, index,
+                         ul = unloadListeners.slice(), context;
+
+                // execute and clear stored unload listeners
+                for (i=0, len=unloadListeners.length; i<len; ++i) {
+                    l = ul[i];
+                    if (l) {
+                        context = window;
+                        if (l[EU.ADJ_SCOPE]) {
+                            if (l[EU.ADJ_SCOPE] === true) {
+                                context = l[EU.UNLOAD_OBJ];
+                            } else {
+                                context = l[EU.ADJ_SCOPE];
+                            }
+                        }
+                        l[EU.FN].call(context, EU.getEvent(e, l[EU.EL]), l[EU.UNLOAD_OBJ] );
+                        ul[i] = null;
+                    }
+                }
+
+                l = null;
+                context = null;
+                unloadListeners = null;
+
+                // Remove listeners to handle IE memory leaks
+                //if (YAHOO.env.ua.ie && listeners && listeners.length > 0) {
+                
+                // 2.5.0 listeners are removed for all browsers again.  FireFox preserves
+                // at least some listeners between page refreshes, potentially causing
+                // errors during page load (mouseover listeners firing before they
+                // should if the user moves the mouse at the correct moment).
+                if (listeners) {
+                    for (j=listeners.length-1; j>-1; j--) {
+                        l = listeners[j];
+                        if (l) {
+                            EU.removeListener(l[EU.EL], l[EU.TYPE], l[EU.FN], j);
+                        } 
+                    }
+                    l=null;
+                }
+
+                legacyEvents = null;
+
+                EU._simpleRemove(window, "unload", EU._unload);
+
+            },
+
+            /**
+             * Returns scrollLeft
+             * @method _getScrollLeft
+             * @static
+             * @private
+             */
+            _getScrollLeft: function() {
+                return this._getScroll()[1];
+            },
+
+            /**
+             * Returns scrollTop
+             * @method _getScrollTop
+             * @static
+             * @private
+             */
+            _getScrollTop: function() {
+                return this._getScroll()[0];
+            },
+
+            /**
+             * Returns the scrollTop and scrollLeft.  Used to calculate the 
+             * pageX and pageY in Internet Explorer
+             * @method _getScroll
+             * @static
+             * @private
+             */
+            _getScroll: function() {
+                var dd = document.documentElement, db = document.body;
+                if (dd && (dd.scrollTop || dd.scrollLeft)) {
+                    return [dd.scrollTop, dd.scrollLeft];
+                } else if (db) {
+                    return [db.scrollTop, db.scrollLeft];
+                } else {
+                    return [0, 0];
+                }
+            },
+            
+            /**
+             * Used by old versions of CustomEvent, restored for backwards
+             * compatibility
+             * @method regCE
+             * @private
+             * @static
+             * @deprecated still here for backwards compatibility
+             */
+            regCE: function() {
+                // does nothing
+            },
+
+            /**
+             * Adds a DOM event directly without the caching, cleanup, context adj, etc
+             *
+             * @method _simpleAdd
+             * @param {HTMLElement} el      the element to bind the handler to
+             * @param {string}      sType   the type of event handler
+             * @param {function}    fn      the callback to invoke
+             * @param {boolen}      capture capture or bubble phase
+             * @static
+             * @private
+             */
+            _simpleAdd: function () {
+                if (window.addEventListener) {
+                    return function(el, sType, fn, capture) {
+                        el.addEventListener(sType, fn, (capture));
+                    };
+                } else if (window.attachEvent) {
+                    return function(el, sType, fn, capture) {
+                        el.attachEvent("on" + sType, fn);
+                    };
+                } else {
+                    return function(){};
+                }
+            }(),
+
+            /**
+             * Basic remove listener
+             *
+             * @method _simpleRemove
+             * @param {HTMLElement} el      the element to bind the handler to
+             * @param {string}      sType   the type of event handler
+             * @param {function}    fn      the callback to invoke
+             * @param {boolen}      capture capture or bubble phase
+             * @static
+             * @private
+             */
+            _simpleRemove: function() {
+                if (window.removeEventListener) {
+                    return function (el, sType, fn, capture) {
+                        el.removeEventListener(sType, fn, (capture));
+                    };
+                } else if (window.detachEvent) {
+                    return function (el, sType, fn) {
+                        el.detachEvent("on" + sType, fn);
+                    };
+                } else {
+                    return function(){};
+                }
+            }()
+        };
+
+    }();
+
+    (function() {
+        var EU = YAHOO.util.Event;
+
+        /**
+         * YAHOO.util.Event.on is an alias for addListener
+         * @method on
+         * @see addListener
+         * @static
+         */
+        EU.on = EU.addListener;
+
+        /**
+         * YAHOO.util.Event.onFocus is an alias for addFocusListener
+         * @method on
+         * @see addFocusListener
+         * @static
+         */
+        EU.onFocus = EU.addFocusListener;
+
+        /**
+         * YAHOO.util.Event.onBlur is an alias for addBlurListener
+         * @method onBlur
+         * @see addBlurListener
+         * @static
+         */     
+        EU.onBlur = EU.addBlurListener;
+
+
+/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller */
+
+        // Internet Explorer: use the readyState of a defered script.
+        // This isolates what appears to be a safe moment to manipulate
+        // the DOM prior to when the document's readyState suggests
+        // it is safe to do so.
+        if (EU.isIE) {
+
+            // Process onAvailable/onContentReady items when the 
+            // DOM is ready.
+            YAHOO.util.Event.onDOMReady(
+                    YAHOO.util.Event._tryPreloadAttach,
+                    YAHOO.util.Event, true);
+            
+            var n = document.createElement('p');  
+
+            EU._dri = setInterval(function() {
+                try {
+                    // throws an error if doc is not ready
+                    n.doScroll('left');
+                    clearInterval(EU._dri);
+                    EU._dri = null;
+                    EU._ready();
+                    n = null;
+                } catch (ex) { 
+                }
+            }, EU.POLL_INTERVAL); 
+
+        
+        // The document's readyState in Safari currently will
+        // change to loaded/complete before images are loaded.
+        } else if (EU.webkit && EU.webkit < 525) {
+
+            EU._dri = setInterval(function() {
+                var rs=document.readyState;
+                if ("loaded" == rs || "complete" == rs) {
+                    clearInterval(EU._dri);
+                    EU._dri = null;
+                    EU._ready();
+                }
+            }, EU.POLL_INTERVAL); 
+
+        // FireFox and Opera: These browsers provide a event for this
+        // moment.  The latest WebKit releases now support this event.
+        } else {
+
+            EU._simpleAdd(document, "DOMContentLoaded", EU._ready);
+
+        }
+        /////////////////////////////////////////////////////////////
+
+
+        EU._simpleAdd(window, "load", EU._load);
+        EU._simpleAdd(window, "unload", EU._unload);
+        EU._tryPreloadAttach();
+    })();
+
+}
+/**
+ * EventProvider is designed to be used with YAHOO.augment to wrap 
+ * CustomEvents in an interface that allows events to be subscribed to 
+ * and fired by name.  This makes it possible for implementing code to
+ * subscribe to an event that either has not been created yet, or will
+ * not be created at all.
+ *
+ * @Class EventProvider
+ */
+YAHOO.util.EventProvider = function() { };
+
+YAHOO.util.EventProvider.prototype = {
+
+    /**
+     * Private storage of custom events
+     * @property __yui_events
+     * @type Object[]
+     * @private
+     */
+    __yui_events: null,
+
+    /**
+     * Private storage of custom event subscribers
+     * @property __yui_subscribers
+     * @type Object[]
+     * @private
+     */
+    __yui_subscribers: null,
+    
+    /**
+     * Subscribe to a CustomEvent by event type
+     *
+     * @method subscribe
+     * @param p_type     {string}   the type, or name of the event
+     * @param p_fn       {function} the function to exectute when the event fires
+     * @param p_obj      {Object}   An object to be passed along when the event 
+     *                              fires
+     * @param overrideContext {boolean}  If true, the obj passed in becomes the 
+     *                              execution scope of the listener
+     */
+    subscribe: function(p_type, p_fn, p_obj, overrideContext) {
+
+        this.__yui_events = this.__yui_events || {};
+        var ce = this.__yui_events[p_type];
+
+        if (ce) {
+            ce.subscribe(p_fn, p_obj, overrideContext);
+        } else {
+            this.__yui_subscribers = this.__yui_subscribers || {};
+            var subs = this.__yui_subscribers;
+            if (!subs[p_type]) {
+                subs[p_type] = [];
+            }
+            subs[p_type].push(
+                { fn: p_fn, obj: p_obj, overrideContext: overrideContext } );
+        }
+    },
+
+    /**
+     * Unsubscribes one or more listeners the from the specified event
+     * @method unsubscribe
+     * @param p_type {string}   The type, or name of the event.  If the type
+     *                          is not specified, it will attempt to remove
+     *                          the listener from all hosted events.
+     * @param p_fn   {Function} The subscribed function to unsubscribe, if not
+     *                          supplied, all subscribers will be removed.
+     * @param p_obj  {Object}   The custom object passed to subscribe.  This is
+     *                        optional, but if supplied will be used to
+     *                        disambiguate multiple listeners that are the same
+     *                        (e.g., you subscribe many object using a function
+     *                        that lives on the prototype)
+     * @return {boolean} true if the subscriber was found and detached.
+     */
+    unsubscribe: function(p_type, p_fn, p_obj) {
+        this.__yui_events = this.__yui_events || {};
+        var evts = this.__yui_events;
+        if (p_type) {
+            var ce = evts[p_type];
+            if (ce) {
+                return ce.unsubscribe(p_fn, p_obj);
+            }
+        } else {
+            var ret = true;
+            for (var i in evts) {
+                if (YAHOO.lang.hasOwnProperty(evts, i)) {
+                    ret = ret && evts[i].unsubscribe(p_fn, p_obj);
+                }
+            }
+            return ret;
+        }
+
+        return false;
+    },
+    
+    /**
+     * Removes all listeners from the specified event.  If the event type
+     * is not specified, all listeners from all hosted custom events will
+     * be removed.
+     * @method unsubscribeAll
+     * @param p_type {string}   The type, or name of the event
+     */
+    unsubscribeAll: function(p_type) {
+        return this.unsubscribe(p_type);
+    },
+
+    /**
+     * Creates a new custom event of the specified type.  If a custom event
+     * by that name already exists, it will not be re-created.  In either
+     * case the custom event is returned. 
+     *
+     * @method createEvent
+     *
+     * @param p_type {string} the type, or name of the event
+     * @param p_config {object} optional config params.  Valid properties are:
+     *
+     *  <ul>
+     *    <li>
+     *      scope: defines the default execution scope.  If not defined
+     *      the default scope will be this instance.
+     *    </li>
+     *    <li>
+     *      silent: if true, the custom event will not generate log messages.
+     *      This is false by default.
+     *    </li>
+     *    <li>
+     *      onSubscribeCallback: specifies a callback to execute when the
+     *      event has a new subscriber.  This will fire immediately for
+     *      each queued subscriber if any exist prior to the creation of
+     *      the event.
+     *    </li>
+     *  </ul>
+     *
+     *  @return {CustomEvent} the custom event
+     *
+     */
+    createEvent: function(p_type, p_config) {
+
+        this.__yui_events = this.__yui_events || {};
+        var opts = p_config || {};
+        var events = this.__yui_events;
+
+        if (events[p_type]) {
+        } else {
+
+            var scope  = opts.scope  || this;
+            var silent = (opts.silent);
+
+            var ce = new YAHOO.util.CustomEvent(p_type, scope, silent,
+                    YAHOO.util.CustomEvent.FLAT);
+            events[p_type] = ce;
+
+            if (opts.onSubscribeCallback) {
+                ce.subscribeEvent.subscribe(opts.onSubscribeCallback);
+            }
+
+            this.__yui_subscribers = this.__yui_subscribers || {};
+            var qs = this.__yui_subscribers[p_type];
+
+            if (qs) {
+                for (var i=0; i<qs.length; ++i) {
+                    ce.subscribe(qs[i].fn, qs[i].obj, qs[i].overrideContext);
+                }
+            }
+        }
+
+        return events[p_type];
+    },
+
+
+   /**
+     * Fire a custom event by name.  The callback functions will be executed
+     * from the scope specified when the event was created, and with the 
+     * following parameters:
+     *   <ul>
+     *   <li>The first argument fire() was executed with</li>
+     *   <li>The custom object (if any) that was passed into the subscribe() 
+     *       method</li>
+     *   </ul>
+     * @method fireEvent
+     * @param p_type    {string}  the type, or name of the event
+     * @param arguments {Object*} an arbitrary set of parameters to pass to 
+     *                            the handler.
+     * @return {boolean} the return value from CustomEvent.fire
+     *                   
+     */
+    fireEvent: function(p_type, arg1, arg2, etc) {
+
+        this.__yui_events = this.__yui_events || {};
+        var ce = this.__yui_events[p_type];
+
+        if (!ce) {
+            return null;
+        }
+
+        var args = [];
+        for (var i=1; i<arguments.length; ++i) {
+            args.push(arguments[i]);
+        }
+        return ce.fire.apply(ce, args);
+    },
+
+    /**
+     * Returns true if the custom event of the provided type has been created
+     * with createEvent.
+     * @method hasEvent
+     * @param type {string} the type, or name of the event
+     */
+    hasEvent: function(type) {
+        if (this.__yui_events) {
+            if (this.__yui_events[type]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+};
+
+(function() {
+
+    var Event = YAHOO.util.Event, Lang = YAHOO.lang;
+
+/**
+* KeyListener is a utility that provides an easy interface for listening for
+* keydown/keyup events fired against DOM elements.
+* @namespace YAHOO.util
+* @class KeyListener
+* @constructor
+* @param {HTMLElement} attachTo The element or element ID to which the key 
+*                               event should be attached
+* @param {String}      attachTo The element or element ID to which the key
+*                               event should be attached
+* @param {Object}      keyData  The object literal representing the key(s) 
+*                               to detect. Possible attributes are 
+*                               shift(boolean), alt(boolean), ctrl(boolean) 
+*                               and keys(either an int or an array of ints 
+*                               representing keycodes).
+* @param {Function}    handler  The CustomEvent handler to fire when the 
+*                               key event is detected
+* @param {Object}      handler  An object literal representing the handler. 
+* @param {String}      event    Optional. The event (keydown or keyup) to 
+*                               listen for. Defaults automatically to keydown.
+*
+* @knownissue the "keypress" event is completely broken in Safari 2.x and below.
+*             the workaround is use "keydown" for key listening.  However, if
+*             it is desired to prevent the default behavior of the keystroke,
+*             that can only be done on the keypress event.  This makes key
+*             handling quite ugly.
+* @knownissue keydown is also broken in Safari 2.x and below for the ESC key.
+*             There currently is no workaround other than choosing another
+*             key to listen for.
+*/
+YAHOO.util.KeyListener = function(attachTo, keyData, handler, event) {
+    if (!attachTo) {
+    } else if (!keyData) {
+    } else if (!handler) {
+    } 
+    
+    if (!event) {
+        event = YAHOO.util.KeyListener.KEYDOWN;
+    }
+
+    /**
+    * The CustomEvent fired internally when a key is pressed
+    * @event keyEvent
+    * @private
+    * @param {Object} keyData The object literal representing the key(s) to 
+    *                         detect. Possible attributes are shift(boolean), 
+    *                         alt(boolean), ctrl(boolean) and keys(either an 
+    *                         int or an array of ints representing keycodes).
+    */
+    var keyEvent = new YAHOO.util.CustomEvent("keyPressed");
+    
+    /**
+    * The CustomEvent fired when the KeyListener is enabled via the enable() 
+    * function
+    * @event enabledEvent
+    * @param {Object} keyData The object literal representing the key(s) to 
+    *                         detect. Possible attributes are shift(boolean), 
+    *                         alt(boolean), ctrl(boolean) and keys(either an 
+    *                         int or an array of ints representing keycodes).
+    */
+    this.enabledEvent = new YAHOO.util.CustomEvent("enabled");
+
+    /**
+    * The CustomEvent fired when the KeyListener is disabled via the 
+    * disable() function
+    * @event disabledEvent
+    * @param {Object} keyData The object literal representing the key(s) to 
+    *                         detect. Possible attributes are shift(boolean), 
+    *                         alt(boolean), ctrl(boolean) and keys(either an 
+    *                         int or an array of ints representing keycodes).
+    */
+    this.disabledEvent = new YAHOO.util.CustomEvent("disabled");
+
+    if (Lang.isString(attachTo)) {
+        attachTo = document.getElementById(attachTo); // No Dom util
+    }
+
+    if (Lang.isFunction(handler)) {
+        keyEvent.subscribe(handler);
+    } else {
+        keyEvent.subscribe(handler.fn, handler.scope, handler.correctScope);
+    }
+
+    /**
+    * Handles the key event when a key is pressed.
+    * @method handleKeyPress
+    * @param {DOMEvent} e   The keypress DOM event
+    * @param {Object}   obj The DOM event scope object
+    * @private
+    */
+    function handleKeyPress(e, obj) {
+        if (! keyData.shift) {  
+            keyData.shift = false; 
+        }
+        if (! keyData.alt) {    
+            keyData.alt = false;
+        }
+        if (! keyData.ctrl) {
+            keyData.ctrl = false;
+        }
+
+        // check held down modifying keys first
+        if (e.shiftKey == keyData.shift && 
+            e.altKey   == keyData.alt &&
+            e.ctrlKey  == keyData.ctrl) { // if we pass this, all modifiers match
+            
+            var dataItem, keys = keyData.keys, key;
+
+            if (YAHOO.lang.isArray(keys)) {
+                for (var i=0;i<keys.length;i++) {
+                    dataItem = keys[i];
+                    key = Event.getCharCode(e);
+
+                    if (dataItem == key) {
+                        keyEvent.fire(key, e);
+                        break;
+                    }
+                }
+            } else {
+                key = Event.getCharCode(e);
+                if (keys == key ) {
+                    keyEvent.fire(key, e);
+                }
+            }
+        }
+    }
+
+    /**
+    * Enables the KeyListener by attaching the DOM event listeners to the 
+    * target DOM element
+    * @method enable
+    */
+    this.enable = function() {
+        if (! this.enabled) {
+            Event.on(attachTo, event, handleKeyPress);
+            this.enabledEvent.fire(keyData);
+        }
+        /**
+        * Boolean indicating the enabled/disabled state of the Tooltip
+        * @property enabled
+        * @type Boolean
+        */
+        this.enabled = true;
+    };
+
+    /**
+    * Disables the KeyListener by removing the DOM event listeners from the 
+    * target DOM element
+    * @method disable
+    */
+    this.disable = function() {
+        if (this.enabled) {
+            Event.removeListener(attachTo, event, handleKeyPress);
+            this.disabledEvent.fire(keyData);
+        }
+        this.enabled = false;
+    };
+
+    /**
+    * Returns a String representation of the object.
+    * @method toString
+    * @return {String}  The string representation of the KeyListener
+    */ 
+    this.toString = function() {
+        return "KeyListener [" + keyData.keys + "] " + attachTo.tagName + 
+                (attachTo.id ? "[" + attachTo.id + "]" : "");
+    };
+
+};
+
+var KeyListener = YAHOO.util.KeyListener;
+
+/**
+ * Constant representing the DOM "keydown" event.
+ * @property YAHOO.util.KeyListener.KEYDOWN
+ * @static
+ * @final
+ * @type String
+ */
+KeyListener.KEYDOWN = "keydown";
+
+/**
+ * Constant representing the DOM "keyup" event.
+ * @property YAHOO.util.KeyListener.KEYUP
+ * @static
+ * @final
+ * @type String
+ */
+KeyListener.KEYUP = "keyup";
+
+/**
+ * keycode constants for a subset of the special keys
+ * @property KEY
+ * @static
+ * @final
+ */
+KeyListener.KEY = {
+    ALT          : 18,
+    BACK_SPACE   : 8,
+    CAPS_LOCK    : 20,
+    CONTROL      : 17,
+    DELETE       : 46,
+    DOWN         : 40,
+    END          : 35,
+    ENTER        : 13,
+    ESCAPE       : 27,
+    HOME         : 36,
+    LEFT         : 37,
+    META         : 224,
+    NUM_LOCK     : 144,
+    PAGE_DOWN    : 34,
+    PAGE_UP      : 33, 
+    PAUSE        : 19,
+    PRINTSCREEN  : 44,
+    RIGHT        : 39,
+    SCROLL_LOCK  : 145,
+    SHIFT        : 16,
+    SPACE        : 32,
+    TAB          : 9,
+    UP           : 38
+};
+
+})();
+YAHOO.register("event", YAHOO.util.Event, {version: "2.7.0", build: "1799"});