/* Copyright (c) 2009, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.8.0r4 */ /** * The CustomEvent class lets you define events for your application * that can be subscribed to by one or more independent component. * * @param {String} type The type of event, which is passed to the callback * when the event fires * @param {Object} context The context the event will fire from. "this" will * refer to this object in the callback. Default value: * the window object. The listener can override this. * @param {boolean} silent pass true to prevent the event from writing to * the debugsystem * @param {int} signature the signature that the custom event subscriber * will receive. YAHOO.util.CustomEvent.LIST or * YAHOO.util.CustomEvent.FLAT. The default is * YAHOO.util.CustomEvent.LIST. * @param fireOnce {boolean} If configured to fire once, the custom event * will only notify subscribers a single time regardless of how many times * the event is fired. In addition, new subscribers will be notified * immediately if the event has already been fired. * @namespace YAHOO.util * @class CustomEvent * @constructor */ YAHOO.util.CustomEvent = function(type, context, silent, signature, fireOnce) { /** * The type of event, returned to subscribers when the event fires * @property type * @type string */ this.type = type; /** * The context the event will fire from by default. Defaults to the window obj. * @property scope * @type object */ this.scope = context || window; /** * By default all custom events are logged in the debug build. Set silent to true * to disable debug output for this event. * @property silent * @type boolean */ this.silent = silent; /** * If configured to fire once, the custom event will only notify subscribers * a single time regardless of how many times the event is fired. In addition, * new subscribers will be notified immediately if the event has already been * fired. * @property fireOnce * @type boolean * @default false */ this.fireOnce = fireOnce; /** * Indicates whether or not this event has ever been fired. * @property fired * @type boolean * @default false */ this.fired = false; /** * For fireOnce events the arguments the event was fired with are stored * so that new subscribers get the proper payload. * @property firedWith * @type Array */ this.firedWith = null; /** * Custom events support two styles of arguments provided to the event * subscribers. * * @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) { YAHOO.log( "Creating " + this, "info", "Event" ); } 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 fn {Function} The function to execute * @param obj An object to be passed along when the event fires. * Defaults to the custom event. * @param override If true, the obj passed in becomes the * execution context of the listener. If an object, that object becomes * the execution context. Defaults to the custom event. */ this.subscribeEvent = new YAHOO.util.CustomEvent(onsubscribeType, this, true); } /** * In order to make it possible to execute the rest of the subscriber * stack when one thows an exception, the subscribers exceptions are * caught. The most recent exception is stored in this property * @property lastError * @type Error */ this.lastError = null; }; /** * Subscriber listener sigature constant. The LIST type returns three * parameters: the event type, the array of args passed to fire, and * the optional custom object * @property YAHOO.util.CustomEvent.LIST * @static * @type int */ YAHOO.util.CustomEvent.LIST = 0; /** * Subscriber listener sigature constant. The FLAT type returns two * parameters: the first argument passed to fire and the optional * custom object * @property YAHOO.util.CustomEvent.FLAT * @static * @type int */ YAHOO.util.CustomEvent.FLAT = 1; YAHOO.util.CustomEvent.prototype = { /** * Subscribes the caller to this event * @method subscribe * @param {Function} fn The function to execute * @param {Object} obj An object to be passed along when the event fires. * overrideContext If true, the obj passed in becomes the execution * context of the listener. If an object, that object becomes the execution context. */ subscribe: function(fn, obj, overrideContext) { if (!fn) { throw new Error("Invalid callback for subscriber to '" + this.type + "'"); } if (this.subscribeEvent) { this.subscribeEvent.fire(fn, obj, overrideContext); } var s = new YAHOO.util.Subscriber(fn, obj, overrideContext); if (this.fireOnce && this.fired) { this.notify(s, this.firedWith); } else { this.subscribers.push(s); } }, /** * 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 *
  • The type of event
  • *
  • All of the arguments fire() was executed with as an array
  • *
  • The custom object (if any) that was passed into the subscribe() * method
  • * * @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; var args=[].slice.call(arguments, 0), ret=true, i, rebuild=false; if (this.fireOnce) { if (this.fired) { YAHOO.log('fireOnce event has already fired: ' + this.type); return true; } else { this.firedWith = args; } } this.fired = true; if (!len && this.silent) { //YAHOO.log('DEBUG no subscribers'); return true; } if (!this.silent) { YAHOO.log( "Firing " + this + ", " + "args: " + args + ", " + "subscribers: " + len, "info", "Event" ); } // make a copy of the subscribers so that there are // no index problems if one subscriber removes another. var subs = this.subscribers.slice(); for (i=0; i " + s, "info", "Event" ); } if (this.signature == YAHOO.util.CustomEvent.FLAT) { if (args.length > 0) { param = args[0]; } try { ret = s.fn.call(scope, param, s.obj); } catch(e) { this.lastError = e; // errors.push(e); YAHOO.log(this + " subscriber exception: " + e, "error", "Event"); if (throwErrors) { throw e; } } } else { try { ret = s.fn.call(scope, this.type, args, s.obj); } catch(ex) { this.lastError = ex; YAHOO.log(this + " subscriber exception: " + ex, "error", "Event"); if (throwErrors) { throw ex; } } } return ret; }, /** * Removes all listeners * @method unsubscribeAll * @return {int} The number of listeners unsubscribed */ unsubscribeAll: function() { var l = this.subscribers.length, i; for (i=l-1; i>-1; i--) { this._delete(i); } this.subscribers=[]; return l; }, /** * @method _delete * @private */ _delete: function(index) { var s = this.subscribers[index]; if (s) { delete s.fn; delete s.obj; } // this.subscribers[index]=null; this.subscribers.splice(index, 1); }, /** * @method toString */ toString: function() { return "CustomEvent: " + "'" + this.type + "', " + "context: " + this.scope; } }; ///////////////////////////////////////////////////////////////////// /** * Stores the subscriber information to be used when the event fires. * @param {Function} fn The function to execute * @param {Object} obj An object to be passed along when the event fires * @param {boolean} overrideContext If true, the obj passed in becomes the execution * context of the listener * @class Subscriber * @constructor */ YAHOO.util.Subscriber = function(fn, obj, overrideContext) { /** * The callback that will be execute when the event fires * @property fn * @type function */ this.fn = fn; /** * An optional custom object that will passed to the callback when * the event fires * @property obj * @type object */ this.obj = YAHOO.lang.isUndefined(obj) ? null : obj; /** * The default execution context for the event listener is defined when the * event is created (usually the object which contains the event). * By setting overrideContext to true, the execution context becomes the custom * object passed in by the subscriber. If overrideContext is an object, that * object becomes the context. * @property overrideContext * @type boolean|object */ this.overrideContext = overrideContext; }; /** * Returns the execution context for this listener. If overrideContext was set to true * the custom obj will be the context. If overrideContext is an object, that is the * context, otherwise the default context will be used. * @method getScope * @param {Object} defaultScope the context to use if this listener does not * override it. */ YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) { if (this.overrideContext) { if (this.overrideContext === true) { return this.obj; } else { return this.overrideContext; } } return defaultScope; }; /** * Returns true if the fn and obj match this objects properties. * Used by the unsubscribe method to match the right subscriber. * * @method contains * @param {Function} fn the function to execute * @param {Object} obj an object to be passed along when the event fires * @return {boolean} true if the supplied arguments match this * subscriber's signature. */ YAHOO.util.Subscriber.prototype.contains = function(fn, obj) { if (obj) { return (this.fn == fn && this.obj == obj); } else { return (this.fn == fn); } }; /** * @method toString */ YAHOO.util.Subscriber.prototype.toString = function() { return "Subscriber { obj: " + this.obj + ", overrideContext: " + (this.overrideContext || "no") + " }"; }; /** * The Event Utility provides utilities for managing DOM Events and tools * for building event systems * * @module event * @title Event Utility * @namespace YAHOO.util * @requires yahoo */ // The first instance of Event will win if it is loaded more than once. // @TODO this needs to be changed so that only the state data that needs to // be preserved is kept, while methods are overwritten/added as needed. // This means that the module pattern can't be used. if (!YAHOO.util.Event) { /** * The event utility provides functions to add and remove event listeners, * event cleansing. It also tries to automatically remove listeners it * registers during the unload event. * * @class Event * @static */ YAHOO.util.Event = function() { /** * True after the onload event has fired * @property loadComplete * @type boolean * @static * @private */ var loadComplete = false, /** * Cache of wrapped listeners * @property listeners * @type array * @static * @private */ listeners = [], /** * User-defined unload function that will be fired before all events * are detached * @property unloadListeners * @type array * @static * @private */ unloadListeners = [], /** * 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 */ retryCount = 0, /** * onAvailable listeners * @property onAvailStack * @static * @private */ onAvailStack = [], /** * Counter for auto id generation * @property counter * @static * @private */ counter = 0, /** * Normalized keycodes for webkit/safari * @property webkitKeymap * @type {int: int} * @private * @static * @final */ 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) }, isIE = YAHOO.env.ua.ie, // String constants used by the addFocusListener and removeFocusListener methods FOCUSIN = "focusin", FOCUSOUT = "focusout"; 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 500@amp;40 ms, so it will poll * for 20 seconds or until all outstanding handlers are bound * (whichever comes first). * @property POLL_RETRYS * @type int * @static * @final */ POLL_RETRYS: 500, /** * The poll interval in milliseconds * @property POLL_INTERVAL * @type int * @static * @final */ POLL_INTERVAL: 40, /** * Element to bind, int constant * @property EL * @type int * @static * @final */ EL: 0, /** * Type of event, int constant * @property TYPE * @type int * @static * @final */ TYPE: 1, /** * Function to execute, int constant * @property FN * @type int * @static * @final */ FN: 2, /** * Function wrapped for context correction and cleanup, int constant * @property WFN * @type int * @static * @final */ WFN: 3, /** * Object passed in by the user that will be returned as a * parameter to the callback, int constant. Specific to * unload listeners * @property OBJ * @type int * @static * @final */ UNLOAD_OBJ: 3, /** * Adjusted context, either the element we are registering the event * on or the custom object passed in by the listener, int constant * @property ADJ_SCOPE * @type int * @static * @final */ ADJ_SCOPE: 4, /** * The original obj passed into addListener * @property OBJ * @type int * @static * @final */ OBJ: 5, /** * The original context parameter passed into addListener * @property OVERRIDE * @type int * @static * @final */ OVERRIDE: 6, /** * 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: isIE, /** * poll handle * @property _interval * @static * @private */ _interval: null, /** * document readystate poll handle * @property _dri * @static * @private */ _dri: null, /** * Map of special event types * @property _specialTypes * @static * @private */ _specialTypes: { focusin: (isIE ? "focusin" : "focus"), focusout: (isIE ? "focusout" : "blur") }, /** * 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); this._interval = YAHOO.lang.later(this.POLL_INTERVAL, this, this._tryPreloadAttach, null, true); } }, /** * 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. * *

    The callback is executed with a single parameter: * the custom object parameter, if provided.

    * * @method onAvailable * * @param {string||string[]} id the id of the element, or an array * of ids to look for. * @param {function} fn what to execute when the element is found. * @param {object} obj an optional object to be passed back as * a parameter to fn. * @param {boolean|object} overrideContext If set to true, fn will execute * in the context of obj, if set to an object it * will execute in the context of that object * @param checkContent {boolean} check child node readiness (onContentReady) * @static */ onAvailable: function(id, fn, obj, overrideContext, checkContent) { var a = (YAHOO.lang.isString(id)) ? [id] : id; for (var i=0; iThe callback is executed with a single parameter: * the custom object parameter, if provided.

    * * @method onContentReady * * @param {string} id the id of the element to look for. * @param {function} fn what to execute when the element is ready. * @param {object} obj an optional object to be passed back as * a parameter to fn. * @param {boolean|object} overrideContext If set to true, fn will execute * in the context of obj. If an object, fn will * exectute in the context of that object * * @static */ onContentReady: function(id, fn, obj, overrideContext) { this.onAvailable(id, fn, obj, overrideContext, true); }, /** * Executes the supplied callback when the DOM is first usable. This * will execute immediately if called after the DOMReady event has * fired. @todo the DOMContentReady event does not fire when the * script is dynamically injected into the page. This means the * DOMReady custom event will never fire in FireFox or Opera when the * library is injected. It _will_ fire in Safari, and the IE * implementation would allow for us to fire it if the defered script * is not available. We want this to behave the same in all browsers. * Is there a way to identify when the script has been injected * instead of included inline? Is there a way to know whether the * window onload event has fired without having had a listener attached * to it when it did so? * *

    The callback is a CustomEvent, so the signature is:

    *

    type <string>, args <array>, customobject <object>

    *

    For DOMReady events, there are no fire argments, so the * signature is:

    *

    "DOMReady", [], obj

    * * * @method onDOMReady * * @param {function} fn what to execute when the element is found. * @param {object} obj an optional object to be passed back as * a parameter to fn. * @param {boolean|object} overrideContext If set to true, fn will execute * in the context of obj, if set to an object it * will execute in the context of that object * * @static */ // onDOMReady: function(fn, obj, overrideContext) { onDOMReady: function() { this.DOMReadyEvent.subscribe.apply(this.DOMReadyEvent, arguments); }, /** * Appends an event handler * * @method _addListener * * @param {String|HTMLElement|Array|NodeList} el An id, an element * reference, or a collection of ids and/or elements to assign the * listener to. * @param {String} sType The type of event to append * @param {Function} fn The method the event invokes * @param {Object} obj An arbitrary object that will be * passed as a parameter to the handler * @param {Boolean|object} overrideContext If true, the obj passed in becomes * the execution context of the listener. If an * object, this object becomes the execution * context. * @param {boolen} capture capture or bubble phase * @return {Boolean} True if the action was successful or defered, * false if one or more of the elements * could not have the listener attached, * or if the operation throws an exception. * @private * @static */ _addListener: function(el, sType, fn, obj, overrideContext, bCapture) { if (!fn || !fn.call) { YAHOO.log(sType + " addListener failed, invalid callback", "error", "Event"); 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-1; i--) { ok = ( this.removeListener(el[i], sType, fn) && ok ); } return ok; } if (!fn || !fn.call) { // this.logger.debug("Error, function is not valid " + fn); //return false; return this.purgeElement(el, false, sType); } if ("unload" == sType) { for (i=unloadListeners.length-1; i>-1; i--) { li = unloadListeners[i]; if (li && li[0] == el && li[1] == sType && li[2] == fn) { unloadListeners.splice(i, 1); // unloadListeners[i]=null; return true; } } return false; } var cacheItem = null; // The index is a hidden parameter; needed to remove it from // the method signature because it was tempting users to // try and take advantage of it, which is not possible. var index = arguments[3]; if ("undefined" === typeof index) { index = this._getCacheIndex(listeners, el, sType, fn); } if (index >= 0) { cacheItem = listeners[index]; } if (!el || !cacheItem) { // this.logger.debug("cached listener not found"); return false; } // this.logger.debug("Removing handler: " + el + ", " + sType); var bCapture = cacheItem[this.CAPTURE] === true ? true : false; try { this._simpleRemove(el, sType, cacheItem[this.WFN], bCapture); } catch(ex) { this.lastError = ex; return false; } // removed the wrapped handler delete listeners[index][this.WFN]; delete listeners[index][this.FN]; listeners.splice(index, 1); // listeners[index]=null; return true; }, /** * Returns the event's target element. Safari sometimes provides * a text node, and this is automatically resolved to the text * node's parent so that it behaves like other browsers. * @method getTarget * @param {Event} ev the event * @param {boolean} resolveTextNode when set to true the target's * parent will be returned if the target is a * text node. @deprecated, the text node is * now resolved automatically * @return {HTMLElement} the event's target * @static */ getTarget: function(ev, resolveTextNode) { var t = ev.target || ev.srcElement; return this.resolveTextNode(t); }, /** * In some cases, some browsers will return a text node inside * the actual element that was targeted. This normalizes the * return value for getTarget and getRelatedTarget. * @method resolveTextNode * @param {HTMLElement} node node to resolve * @return {HTMLElement} the normized node * @static */ resolveTextNode: function(n) { try { if (n && 3 == n.nodeType) { return n.parentNode; } } catch(e) { } return n; }, /** * Returns the event's pageX * @method getPageX * @param {Event} ev the event * @return {int} the event's pageX * @static */ getPageX: function(ev) { var x = ev.pageX; if (!x && 0 !== x) { x = ev.clientX || 0; if ( this.isIE ) { x += this._getScrollLeft(); } } return x; }, /** * Returns the event's pageY * @method getPageY * @param {Event} ev the event * @return {int} the event's pageY * @static */ getPageY: function(ev) { var y = ev.pageY; if (!y && 0 !== y) { y = ev.clientY || 0; if ( this.isIE ) { y += this._getScrollTop(); } } return y; }, /** * Returns the pageX and pageY properties as an indexed array. * @method getXY * @param {Event} ev the event * @return {[x, y]} the pageX and pageY properties of the event * @static */ getXY: function(ev) { return [this.getPageX(ev), this.getPageY(ev)]; }, /** * Returns the event's related target * @method getRelatedTarget * @param {Event} ev the event * @return {HTMLElement} the event's relatedTarget * @static */ getRelatedTarget: function(ev) { var t = ev.relatedTarget; if (!t) { if (ev.type == "mouseout") { t = ev.toElement; } else if (ev.type == "mouseover") { t = ev.fromElement; } } return this.resolveTextNode(t); }, /** * Returns the time of the event. If the time is not included, the * event is modified using the current time. * @method getTime * @param {Event} ev the event * @return {Date} the time of the event * @static */ getTime: function(ev) { if (!ev.time) { var t = new Date().getTime(); try { ev.time = t; } catch(ex) { this.lastError = ex; return t; } } return ev.time; }, /** * Convenience method for stopPropagation + preventDefault * @method stopEvent * @param {Event} ev the event * @static */ stopEvent: function(ev) { this.stopPropagation(ev); this.preventDefault(ev); }, /** * Stops event propagation * @method stopPropagation * @param {Event} ev the event * @static */ stopPropagation: function(ev) { if (ev.stopPropagation) { ev.stopPropagation(); } else { ev.cancelBubble = true; } }, /** * Prevents the default behavior of the event * @method preventDefault * @param {Event} ev the event * @static */ preventDefault: function(ev) { if (ev.preventDefault) { ev.preventDefault(); } else { ev.returnValue = false; } }, /** * Finds the event in the window object, the caller's arguments, or * in the arguments of another method in the callstack. This is * executed automatically for events registered through the event * manager, so the implementer should not normally need to execute * this function at all. * @method getEvent * @param {Event} e the event parameter from the handler * @param {HTMLElement} boundEl the element the listener is attached to * @return {Event} the event * @static */ getEvent: function(e, boundEl) { var ev = e || window.event; if (!ev) { var c = this.getEvent.caller; while (c) { ev = c.arguments[0]; if (ev && Event == ev.constructor) { break; } c = c.caller; } } return ev; }, /** * Returns the charcode for an event * @method getCharCode * @param {Event} ev the event * @return {int} the event's charCode * @static */ getCharCode: function(ev) { var code = ev.keyCode || ev.charCode || 0; // webkit key normalization if (YAHOO.env.ua.webkit && (code in webkitKeymap)) { code = webkitKeymap[code]; } return code; }, /** * Locating the saved event handler data by function ref * * @method _getCacheIndex * @static * @private */ _getCacheIndex: function(a, el, sType, fn) { for (var i=0, l=a.length; i 0 && onAvailStack.length > 0); } // onAvailable var notAvail = []; var executeItem = function (el, item) { var context = el; if (item.overrideContext) { if (item.overrideContext === true) { context = item.obj; } else { context = item.overrideContext; } } item.fn.call(context, item.obj); }; var i, len, item, el, ready=[]; // onAvailable onContentReady for (i=0, len=onAvailStack.length; i-1; i--) { item = onAvailStack[i]; if (!item || !item.id) { onAvailStack.splice(i, 1); } } this.startInterval(); } else { if (this._interval) { // clearInterval(this._interval); this._interval.cancel(); this._interval = null; } } this.locked = false; }, /** * Removes all listeners attached to the given element via addListener. * Optionally, the node's children can also be purged. * Optionally, you can specify a specific type of event to remove. * @method purgeElement * @param {HTMLElement} el the element to purge * @param {boolean} recurse recursively purge this element's children * as well. Use with caution. * @param {string} sType optional type of listener to purge. If * left out, all listeners will be removed * @static */ purgeElement: function(el, recurse, sType) { var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el; var elListeners = this.getListeners(oEl, sType), i, len; if (elListeners) { for (i=elListeners.length-1; i>-1; i--) { var l = elListeners[i]; this.removeListener(oEl, l.type, l.fn); } } if (recurse && oEl && oEl.childNodes) { for (i=0,len=oEl.childNodes.length; i-1; j--) { l = listeners[j]; if (l) { EU.removeListener(l[EU.EL], l[EU.TYPE], l[EU.FN], j); } } l=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() {}, /** * Adds a DOM event directly without the caching, cleanup, context adj, etc * * @method _simpleAdd * @param {HTMLElement} el the element to bind the handler to * @param {string} sType the type of event handler * @param {function} fn the callback to invoke * @param {boolen} capture capture or bubble phase * @static * @private */ _simpleAdd: function () { if (window.addEventListener) { return function(el, sType, fn, capture) { el.addEventListener(sType, fn, (capture)); }; } else if (window.attachEvent) { return function(el, sType, fn, capture) { el.attachEvent("on" + sType, fn); }; } else { return function(){}; } }(), /** * Basic remove listener * * @method _simpleRemove * @param {HTMLElement} el the element to bind the handler to * @param {string} sType the type of event handler * @param {function} fn the callback to invoke * @param {boolen} capture capture or bubble phase * @static * @private */ _simpleRemove: function() { if (window.removeEventListener) { return function (el, sType, fn, capture) { el.removeEventListener(sType, fn, (capture)); }; } else if (window.detachEvent) { return function (el, sType, fn) { el.detachEvent("on" + sType, fn); }; } else { return function(){}; } }() }; }(); (function() { var EU = YAHOO.util.Event; /** * YAHOO.util.Event.on is an alias for addListener * @method on * @see addListener * @static */ EU.on = EU.addListener; /** * YAHOO.util.Event.onFocus is an alias for addFocusListener * @method onFocus * @see addFocusListener * @static * @deprecated use YAHOO.util.Event.on and specify "focusin" as the event type. */ EU.onFocus = EU.addFocusListener; /** * YAHOO.util.Event.onBlur is an alias for addBlurListener * @method onBlur * @see addBlurListener * @static * @deprecated use YAHOO.util.Event.on and specify "focusout" as the event type. */ EU.onBlur = EU.addBlurListener; /*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */ // 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) { if (self !== self.top) { document.onreadystatechange = function() { if (document.readyState == 'complete') { document.onreadystatechange = null; EU._ready(); } }; } else { // Process onAvailable/onContentReady items when the // DOM is ready. YAHOO.util.Event.onDOMReady( YAHOO.util.Event._tryPreloadAttach, YAHOO.util.Event, true); var n = document.createElement('p'); EU._dri = setInterval(function() { try { // throws an error if doc is not ready n.doScroll('left'); clearInterval(EU._dri); EU._dri = null; EU._ready(); n = null; } catch (ex) { } }, EU.POLL_INTERVAL); } // The document's readyState in Safari currently will // change to loaded/complete before images are loaded. } else if (EU.webkit && EU.webkit < 525) { EU._dri = setInterval(function() { var rs=document.readyState; if ("loaded" == rs || "complete" == rs) { clearInterval(EU._dri); EU._dri = null; EU._ready(); } }, EU.POLL_INTERVAL); // FireFox and Opera: These browsers provide a event for this // moment. The latest WebKit releases now support this event. } else { EU._simpleAdd(document, "DOMContentLoaded", EU._ready); } ///////////////////////////////////////////////////////////// EU._simpleAdd(window, "load", EU._load); EU._simpleAdd(window, "unload", EU._unload); EU._tryPreloadAttach(); })(); } /** * EventProvider is designed to be used with YAHOO.augment to wrap * CustomEvents in an interface that allows events to be subscribed to * and fired by name. This makes it possible for implementing code to * subscribe to an event that either has not been created yet, or will * not be created at all. * * @Class EventProvider */ YAHOO.util.EventProvider = function() { }; YAHOO.util.EventProvider.prototype = { /** * Private storage of custom events * @property __yui_events * @type Object[] * @private */ __yui_events: null, /** * Private storage of custom event subscribers * @property __yui_subscribers * @type Object[] * @private */ __yui_subscribers: null, /** * Subscribe to a CustomEvent by event type * * @method subscribe * @param p_type {string} the type, or name of the event * @param p_fn {function} the function to exectute when the event fires * @param p_obj {Object} An object to be passed along when the event * fires * @param overrideContext {boolean} If true, the obj passed in becomes the * execution scope of the listener */ subscribe: function(p_type, p_fn, p_obj, overrideContext) { this.__yui_events = this.__yui_events || {}; var ce = this.__yui_events[p_type]; if (ce) { ce.subscribe(p_fn, p_obj, overrideContext); } else { this.__yui_subscribers = this.__yui_subscribers || {}; var subs = this.__yui_subscribers; if (!subs[p_type]) { subs[p_type] = []; } subs[p_type].push( { fn: p_fn, obj: p_obj, overrideContext: overrideContext } ); } }, /** * Unsubscribes one or more listeners the from the specified event * @method unsubscribe * @param p_type {string} The type, or name of the event. If the type * is not specified, it will attempt to remove * the listener from all hosted events. * @param p_fn {Function} The subscribed function to unsubscribe, if not * supplied, all subscribers will be removed. * @param p_obj {Object} The custom object passed to subscribe. This is * optional, but if supplied will be used to * disambiguate multiple listeners that are the same * (e.g., you subscribe many object using a function * that lives on the prototype) * @return {boolean} true if the subscriber was found and detached. */ unsubscribe: function(p_type, p_fn, p_obj) { this.__yui_events = this.__yui_events || {}; var evts = this.__yui_events; if (p_type) { var ce = evts[p_type]; if (ce) { return ce.unsubscribe(p_fn, p_obj); } } else { var ret = true; for (var i in evts) { if (YAHOO.lang.hasOwnProperty(evts, i)) { ret = ret && evts[i].unsubscribe(p_fn, p_obj); } } return ret; } return false; }, /** * Removes all listeners from the specified event. If the event type * is not specified, all listeners from all hosted custom events will * be removed. * @method unsubscribeAll * @param p_type {string} The type, or name of the event */ unsubscribeAll: function(p_type) { return this.unsubscribe(p_type); }, /** * Creates a new custom event of the specified type. If a custom event * by that name already exists, it will not be re-created. In either * case the custom event is returned. * * @method createEvent * * @param p_type {string} the type, or name of the event * @param p_config {object} optional config params. Valid properties are: * *
      *
    • * scope: defines the default execution scope. If not defined * the default scope will be this instance. *
    • *
    • * silent: if true, the custom event will not generate log messages. * This is false by default. *
    • *
    • * fireOnce: if true, the custom event will only notify subscribers * once regardless of the number of times the event is fired. In * addition, new subscribers will be executed immediately if the * event has already fired. * This is false by default. *
    • *
    • * 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. *
    • *
    * * @return {CustomEvent} the custom event * */ createEvent: function(p_type, p_config) { this.__yui_events = this.__yui_events || {}; var opts = p_config || {}, events = this.__yui_events, ce; if (events[p_type]) { YAHOO.log("EventProvider createEvent skipped: '"+p_type+"' already exists"); } else { ce = new YAHOO.util.CustomEvent(p_type, opts.scope || this, opts.silent, YAHOO.util.CustomEvent.FLAT, opts.fireOnce); 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 *
  • The first argument fire() was executed with
  • *
  • The custom object (if any) that was passed into the subscribe() * method
  • * * @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) { this.__yui_events = this.__yui_events || {}; var ce = this.__yui_events[p_type]; if (!ce) { YAHOO.log(p_type + "event fired before it was created."); return null; } var args = []; for (var i=1; i