Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Unified Diff: chrome/test/data/dromaeo/lib/yui-event.js

Issue 269054: Importing dromaeo performance tests to src/chrome/test/data.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/test/data/dromaeo/lib/yui-dom.js ('k') | chrome/test/data/dromaeo/lib/yui-selector.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/data/dromaeo/lib/yui-event.js
===================================================================
--- chrome/test/data/dromaeo/lib/yui-event.js (revision 0)
+++ chrome/test/data/dromaeo/lib/yui-event.js (revision 0)
@@ -0,0 +1,2562 @@
+/*
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.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} oScope 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, oScope, silent, signature) {
+
+ /**
+ * The type of event, returned to subscribers when the event fires
+ * @property type
+ * @type string
+ */
+ this.type = type;
+
+ /**
+ * The scope the the event will fire from by default. Defaults to the window
+ * obj
+ * @property scope
+ * @type object
+ */
+ this.scope = oScope || 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
+ * @param {boolean|Object} override If true, the obj passed in becomes
+ * the execution scope of the listener.
+ * if an object, that object becomes the
+ * the execution scope.
+ */
+ 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} override If true, the obj passed in becomes
+ * the execution scope of the listener.
+ * if an object, that object becomes the
+ * the execution scope.
+ */
+ subscribe: function(fn, obj, override) {
+
+ if (!fn) {
+throw new Error("Invalid callback for subscriber to '" + this.type + "'");
+ }
+
+ if (this.subscribeEvent) {
+ this.subscribeEvent.fire(fn, obj, override);
+ }
+
+ this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, override) );
+ },
+
+ /**
+ * 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 scope 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() {
+ for (var i=this.subscribers.length-1; i>-1; i--) {
+ this._delete(i);
+ }
+
+ this.subscribers=[];
+
+ return i;
+ },
+
+ /**
+ * @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 + "', " +
+ "scope: " + 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} override If true, the obj passed in becomes the execution
+ * scope of the listener
+ * @class Subscriber
+ * @constructor
+ */
+YAHOO.util.Subscriber = function(fn, obj, override) {
+
+ /**
+ * 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 scope for the event listener is defined when the
+ * event is created (usually the object which contains the event).
+ * By setting override to true, the execution scope becomes the custom
+ * object passed in by the subscriber. If override is an object, that
+ * object becomes the scope.
+ * @property override
+ * @type boolean|object
+ */
+ this.override = override;
+
+};
+
+/**
+ * Returns the execution scope for this listener. If override was set to true
+ * the custom obj will be the scope. If override is an object, that is the
+ * scope, otherwise the default scope will be used.
+ * @method getScope
+ * @param {Object} defaultScope the scope to use if this listener does not
+ * override it.
+ */
+YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) {
+ if (this.override) {
+ if (this.override === true) {
+ return this.obj;
+ } else {
+ return this.override;
+ }
+ }
+ 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 +
+ ", override: " + (this.override || "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 scope 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 scope, 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 scope parameter passed into addListener
+ * @property OVERRIDE
+ * @type int
+ * @static
+ * @final
+ */
+ OVERRIDE: 6,
+
+ /**
+ * The original capture parameter passed into _addListener
+ * @property CAPTURE
+ * @type int
+ * @static
+ * @final
+ */
+ CAPTURE: 7,
+
+
+ /**
+ * 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[]} p_id the id of the element, or an array
+ * of ids to look for.
+ * @param {function} p_fn what to execute when the element is found.
+ * @param {object} p_obj an optional object to be passed back as
+ * a parameter to p_fn.
+ * @param {boolean|object} p_override If set to true, p_fn will execute
+ * in the scope of p_obj, if set to an object it
+ * will execute in the scope of that object
+ * @param checkContent {boolean} check child node readiness (onContentReady)
+ * @static
+ */
+ onAvailable: function(p_id, p_fn, p_obj, p_override, checkContent) {
+
+ var a = (YAHOO.lang.isString(p_id)) ? [p_id] : p_id;
+
+ for (var i=0; i<a.length; i=i+1) {
+ onAvailStack.push({id: a[i],
+ fn: p_fn,
+ obj: p_obj,
+ override: p_override,
+ 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} p_id the id of the element to look for.
+ * @param {function} p_fn what to execute when the element is ready.
+ * @param {object} p_obj an optional object to be passed back as
+ * a parameter to p_fn.
+ * @param {boolean|object} p_override If set to true, p_fn will execute
+ * in the scope of p_obj. If an object, p_fn will
+ * exectute in the scope of that object
+ *
+ * @static
+ */
+ onContentReady: function(p_id, p_fn, p_obj, p_override) {
+ this.onAvailable(p_id, p_fn, p_obj, p_override, 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} p_fn what to execute when the element is found.
+ * @param {object} p_obj an optional object to be passed back as
+ * a parameter to p_fn.
+ * @param {boolean|object} p_scope If set to true, p_fn will execute
+ * in the scope of p_obj, if set to an object it
+ * will execute in the scope of that object
+ *
+ * @static
+ */
+ onDOMReady: function(p_fn, p_obj, p_override) {
+ if (this.DOMReady) {
+ setTimeout(function() {
+ var s = window;
+ if (p_override) {
+ if (p_override === true) {
+ s = p_obj;
+ } else {
+ s = p_override;
+ }
+ }
+ p_fn.call(s, "DOMReady", [], p_obj);
+ }, 0);
+ } else {
+ this.DOMReadyEvent.subscribe(p_fn, p_obj, p_override);
+ }
+ },
+
+
+ /**
+ * 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} override If true, the obj passed in becomes
+ * the execution scope of the listener. If an
+ * object, this object becomes the execution
+ * scope.
+ * @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, override, capture) {
+
+ 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._addListener(el[i],
+ sType,
+ fn,
+ obj,
+ override,
+ capture) && 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._addListener(el, sType, fn, obj, override, capture);
+ });
+
+ 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, override, capture];
+ return true;
+ }
+
+
+ // if the user chooses to override the scope, we use the custom
+ // object passed in, otherwise the executing scope will be the
+ // HTML element that the event is registered on
+ var scope = el;
+ if (override) {
+ if (override === true) {
+ scope = obj;
+ } else {
+ scope = override;
+ }
+ }
+
+ // wrap the function so we can return the obj object when
+ // the event fires;
+ var wrappedFn = function(e) {
+ return fn.call(scope, YAHOO.util.Event.getEvent(e, el),
+ obj);
+ };
+
+ var li = [el, sType, fn, wrappedFn, scope, obj, override, capture];
+ 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, capture);
+ } 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, capture);
+ 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} override If true, the obj passed in becomes
+ * the execution scope of the listener. If an
+ * object, this object becomes the execution
+ * scope.
+ * @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, override) {
+ return this._addListener(el, sType, fn, obj, override, false);
+ },
+
+ /**
+ * Appends a focus event handler. (The focusin event is used for Internet Explorer,
+ * the focus, capture-event for Opera, WebKit, and Gecko.)
+ *
+ * @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} override If true, the obj passed in becomes
+ * the execution scope of the listener. If an
+ * object, this object becomes the execution
+ * scope.
+ * @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, override) {
+ return this._addListener(el, _FOCUS, fn, obj, override, true);
+ },
+
+
+ /**
+ * Removes a focus event listener
+ *
+ * @method removeFocusListener
+ *
+ * @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, true);
+ },
+
+ /**
+ * Appends a blur event handler. (The focusout event is used for Internet Explorer,
+ * the focusout, capture-event for Opera, WebKit, and Gecko.)
+ *
+ * @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} override If true, the obj passed in becomes
+ * the execution scope of the listener. If an
+ * object, this object becomes the execution
+ * scope.
+ * @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, override) {
+ return this._addListener(el, _BLUR, fn, obj, override, true);
+ },
+
+ /**
+ * Removes a blur event listener
+ *
+ * @method removeBlurListener
+ *
+ * @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, true);
+
+ },
+
+ /**
+ * 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, scope, 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] ) {
+ scope = li[this.ADJ_SCOPE];
+ ret = li[this.WFN].call(scope, 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.
+ * @param {boolen} capture capture or bubble phase
+ * @return {boolean} true if the unbind was successful, false
+ * otherwise.
+ * @static
+ * @private
+ */
+ _removeListener: function(el, sType, fn, capture) {
+ 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, capture) && 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[4];
+
+ 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], capture);
+ } 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;
+
+ },
+
+
+ /**
+ * 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) {
+
+ return this._removeListener(el, sType, fn, false);
+
+ },
+
+
+ /**
+ * 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;
+ 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 scope = el;
+ if (item.override) {
+ if (item.override === true) {
+ scope = item.obj;
+ } else {
+ scope = item.override;
+ }
+ }
+ item.fn.call(scope, 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 {
+ 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, l.capture);
+ }
+ }
+
+ 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 scope
+ * &nbsp;&nbsp;scope: (boolean) the derived scope based on the adjust parameter
+ * &nbsp;&nbsp;scope: (capture) the capture parameter supplied to addListener
+ * &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],
+ capture: l[this.CAPTURE],
+ 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();
+
+ // execute and clear stored unload listeners
+ for (i=0,len=unloadListeners.length; i<len; ++i) {
+ l = ul[i];
+ if (l) {
+ var scope = window;
+ if (l[EU.ADJ_SCOPE]) {
+ if (l[EU.ADJ_SCOPE] === true) {
+ scope = l[EU.UNLOAD_OBJ];
+ } else {
+ scope = l[EU.ADJ_SCOPE];
+ }
+ }
+ l[EU.FN].call(scope, EU.getEvent(e, l[EU.EL]), l[EU.UNLOAD_OBJ] );
+ ul[i] = null;
+ l=null;
+ scope=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], l[EU.CAPTURE], 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, scope 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 p_override {boolean} If true, the obj passed in becomes the
+ * execution scope of the listener
+ */
+ subscribe: function(p_type, p_fn, p_obj, p_override) {
+
+ this.__yui_events = this.__yui_events || {};
+ var ce = this.__yui_events[p_type];
+
+ if (ce) {
+ ce.subscribe(p_fn, p_obj, p_override);
+ } 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, override: p_override } );
+ }
+ },
+
+ /**
+ * 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].override);
+ }
+ }
+ }
+
+ 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;
+ }
+
+};
+
+//@TODO optimize
+//@TODO use event utility, lang abstractions
+//@TODO replace
+
+/**
+* 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 (typeof attachTo == 'string') {
+ attachTo = document.getElementById(attachTo);
+ }
+
+ if (typeof handler == 'function') {
+ 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;
+
+ if (keyData.keys instanceof Array) {
+ for (var i=0;i<keyData.keys.length;i++) {
+ dataItem = keyData.keys[i];
+
+ if (dataItem == e.charCode ) {
+ keyEvent.fire(e.charCode, e);
+ break;
+ } else if (dataItem == e.keyCode) {
+ keyEvent.fire(e.keyCode, e);
+ break;
+ }
+ }
+ } else {
+ dataItem = keyData.keys;
+ if (dataItem == e.charCode ) {
+ keyEvent.fire(e.charCode, e);
+ } else if (dataItem == e.keyCode) {
+ keyEvent.fire(e.keyCode, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Enables the KeyListener by attaching the DOM event listeners to the
+ * target DOM element
+ * @method enable
+ */
+ this.enable = function() {
+ if (! this.enabled) {
+ YAHOO.util.Event.addListener(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) {
+ YAHOO.util.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 + "]" : "");
+ };
+
+};
+
+/**
+ * Constant representing the DOM "keydown" event.
+ * @property YAHOO.util.KeyListener.KEYDOWN
+ * @static
+ * @final
+ * @type String
+ */
+YAHOO.util.KeyListener.KEYDOWN = "keydown";
+
+/**
+ * Constant representing the DOM "keyup" event.
+ * @property YAHOO.util.KeyListener.KEYUP
+ * @static
+ * @final
+ * @type String
+ */
+YAHOO.util.KeyListener.KEYUP = "keyup";
+
+/**
+ * keycode constants for a subset of the special keys
+ * @property KEY
+ * @static
+ * @final
+ */
+YAHOO.util.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.6.0", build: "1321"});
« no previous file with comments | « chrome/test/data/dromaeo/lib/yui-dom.js ('k') | chrome/test/data/dromaeo/lib/yui-selector.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698