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 <string>, args <array>, customobject <object></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: |
+ * type: (string) the type of event |
+ * fn: (function) the callback supplied to addListener |
+ * obj: (object) the custom object supplied to addListener |
+ * adjust: (boolean|object) whether or not to adjust the default scope |
+ * scope: (boolean) the derived scope based on the adjust parameter |
+ * scope: (capture) the capture parameter supplied to addListener |
+ * 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"}); |