/* YUI 3.17.2 (build 9c3c78e) Copyright 2014 Yahoo! Inc. All rights reserved. Licensed under the BSD License. http://yuilibrary.com/license/ */ YUI.add('event-base', function (Y, NAME) { /* * DOM event listener abstraction layer * @module event * @submodule event-base */ /** * The domready event fires at the moment the browser's DOM is * usable. In most cases, this is before images are fully * downloaded, allowing you to provide a more responsive user * interface. * * In YUI 3, domready subscribers will be notified immediately if * that moment has already passed when the subscription is created. * * One exception is if the yui.js file is dynamically injected into * the page. If this is done, you must tell the YUI instance that * you did this in order for DOMReady (and window load events) to * fire normally. That configuration option is 'injected' -- set * it to true if the yui.js script is not included inline. * * This method is part of the 'event-ready' module, which is a * submodule of 'event'. * * @event domready * @for YUI */ Y.publish('domready', { fireOnce: true, async: true }); if (YUI.Env.DOMReady) { Y.fire('domready'); } else { Y.Do.before(function() { Y.fire('domready'); }, YUI.Env, '_ready'); } /** * Custom event engine, DOM event listener abstraction layer, synthetic DOM * events. * @module event * @submodule event-base */ /** * Wraps a DOM event, properties requiring browser abstraction are * fixed here. Provids a security layer when required. * @class DOMEventFacade * @param ev {Event} the DOM event * @param currentTarget {HTMLElement} the element the listener was attached to * @param wrapper {CustomEvent} the custom event wrapper for this DOM event */ var ua = Y.UA, EMPTY = {}, /** * webkit key remapping required for Safari < 3.1 * @property webkitKeymap * @private */ 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) 63272: 46, // delete 63273: 36, // home 63275: 35 // end }, /** * Returns a wrapped node. Intended to be used on event targets, * so it will return the node's parent if the target is a text * node. * * If accessing a property of the node throws an error, this is * probably the anonymous div wrapper Gecko adds inside text * nodes. This likely will only occur when attempting to access * the relatedTarget. In this case, we now return null because * the anonymous div is completely useless and we do not know * what the related target was because we can't even get to * the element's parent node. * * @method resolve * @private */ resolve = function(n) { if (!n) { return n; } try { if (n && 3 == n.nodeType) { n = n.parentNode; } } catch(e) { return null; } return Y.one(n); }, DOMEventFacade = function(ev, currentTarget, wrapper) { this._event = ev; this._currentTarget = currentTarget; this._wrapper = wrapper || EMPTY; // if not lazy init this.init(); }; Y.extend(DOMEventFacade, Object, { init: function() { var e = this._event, overrides = this._wrapper.overrides, x = e.pageX, y = e.pageY, c, currentTarget = this._currentTarget; this.altKey = e.altKey; this.ctrlKey = e.ctrlKey; this.metaKey = e.metaKey; this.shiftKey = e.shiftKey; this.type = (overrides && overrides.type) || e.type; this.clientX = e.clientX; this.clientY = e.clientY; this.pageX = x; this.pageY = y; // charCode is unknown in keyup, keydown. keyCode is unknown in keypress. // FF 3.6 - 8+? pass 0 for keyCode in keypress events. // Webkit, FF 3.6-8+?, and IE9+? pass 0 for charCode in keydown, keyup. // Webkit and IE9+? duplicate charCode in keyCode. // Opera never sets charCode, always keyCode (though with the charCode). // IE6-8 don't set charCode or which. // All browsers other than IE6-8 set which=keyCode in keydown, keyup, and // which=charCode in keypress. // // Moral of the story: (e.which || e.keyCode) will always return the // known code for that key event phase. e.keyCode is often different in // keypress from keydown and keyup. c = e.keyCode || e.charCode; if (ua.webkit && (c in webkitKeymap)) { c = webkitKeymap[c]; } this.keyCode = c; this.charCode = c; // Fill in e.which for IE - implementers should always use this over // e.keyCode or e.charCode. this.which = e.which || e.charCode || c; // this.button = e.button; this.button = this.which; this.target = resolve(e.target); this.currentTarget = resolve(currentTarget); this.relatedTarget = resolve(e.relatedTarget); if (e.type == "mousewheel" || e.type == "DOMMouseScroll") { this.wheelDelta = (e.detail) ? (e.detail * -1) : Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1); } if (this._touch) { this._touch(e, currentTarget, this._wrapper); } }, stopPropagation: function() { this._event.stopPropagation(); this._wrapper.stopped = 1; this.stopped = 1; }, stopImmediatePropagation: function() { var e = this._event; if (e.stopImmediatePropagation) { e.stopImmediatePropagation(); } else { this.stopPropagation(); } this._wrapper.stopped = 2; this.stopped = 2; }, preventDefault: function(returnValue) { var e = this._event; e.preventDefault(); if (returnValue) { e.returnValue = returnValue; } this._wrapper.prevented = 1; this.prevented = 1; }, halt: function(immediate) { if (immediate) { this.stopImmediatePropagation(); } else { this.stopPropagation(); } this.preventDefault(); } }); DOMEventFacade.resolve = resolve; Y.DOM2EventFacade = DOMEventFacade; Y.DOMEventFacade = DOMEventFacade; /** * The native event * @property _event * @type {DOMEvent} * @private */ /** The name of the event (e.g. "click") @property type @type {String} **/ /** `true` if the "alt" or "option" key is pressed. @property altKey @type {Boolean} **/ /** `true` if the shift key is pressed. @property shiftKey @type {Boolean} **/ /** `true` if the "Windows" key on a Windows keyboard, "command" key on an Apple keyboard, or "meta" key on other keyboards is pressed. @property metaKey @type {Boolean} **/ /** `true` if the "Ctrl" or "control" key is pressed. @property ctrlKey @type {Boolean} **/ /** * The X location of the event on the page (including scroll) * @property pageX * @type {Number} */ /** * The Y location of the event on the page (including scroll) * @property pageY * @type {Number} */ /** * The X location of the event in the viewport * @property clientX * @type {Number} */ /** * The Y location of the event in the viewport * @property clientY * @type {Number} */ /** * The keyCode for key events. Uses charCode if keyCode is not available * @property keyCode * @type {Number} */ /** * The charCode for key events. Same as keyCode * @property charCode * @type {Number} */ /** * The button that was pushed. 1 for left click, 2 for middle click, 3 for * right click. This is only reliably populated on `mouseup` events. * @property button * @type {Number} */ /** * The button that was pushed. Same as button. * @property which * @type {Number} */ /** * Node reference for the targeted element * @property target * @type {Node} */ /** * Node reference for the element that the listener was attached to. * @property currentTarget * @type {Node} */ /** * Node reference to the relatedTarget * @property relatedTarget * @type {Node} */ /** * Number representing the direction and velocity of the movement of the mousewheel. * Negative is down, the higher the number, the faster. Applies to the mousewheel event. * @property wheelDelta * @type {Number} */ /** * Stops the propagation to the next bubble target * @method stopPropagation */ /** * Stops the propagation to the next bubble target and * prevents any additional listeners from being exectued * on the current target. * @method stopImmediatePropagation */ /** * Prevents the event's default behavior * @method preventDefault * @param returnValue {string} sets the returnValue of the event to this value * (rather than the default false value). This can be used to add a customized * confirmation query to the beforeunload event). */ /** * Stops the event propagation and prevents the default * event behavior. * @method halt * @param immediate {boolean} if true additional listeners * on the current target will not be executed */ (function() { /** * 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. * @module event * @main event * @submodule event-base */ /** * 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 */ Y.Env.evt.dom_wrappers = {}; Y.Env.evt.dom_map = {}; var _eventenv = Y.Env.evt, config = Y.config, win = config.win, add = YUI.Env.add, remove = YUI.Env.remove, onLoad = function() { YUI.Env.windowLoaded = true; Y.Event._load(); remove(win, "load", onLoad); }, onUnload = function() { Y.Event._unload(); }, EVENT_READY = 'domready', COMPAT_ARG = '~yui|2|compat~', shouldIterate = function(o) { try { // TODO: See if there's a more performant way to return true early on this, for the common case return (o && typeof o !== "string" && Y.Lang.isNumber(o.length) && !o.tagName && !Y.DOM.isWindow(o)); } catch(ex) { return false; } }, // aliases to support DOM event subscription clean up when the last // subscriber is detached. deleteAndClean overrides the DOM event's wrapper // CustomEvent _delete method. _ceProtoDelete = Y.CustomEvent.prototype._delete, _deleteAndClean = function(s) { var ret = _ceProtoDelete.apply(this, arguments); if (!this.hasSubs()) { Y.Event._clean(this); } return ret; }, Event = function() { /** * True after the onload event has fired * @property _loadComplete * @type boolean * @static * @private */ var _loadComplete = false, /** * 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 _avail * @static * @private */ _avail = [], /** * Custom event wrappers for DOM events. Key is * 'event:' + Element uid stamp + event type * @property _wrappers * @type CustomEvent * @static * @private */ _wrappers = _eventenv.dom_wrappers, _windowLoadKey = null, /** * Custom event wrapper map DOM events. Key is * Element uid stamp. Each item is a hash of custom event * wrappers as provided in the _wrappers collection. This * provides the infrastructure for getListeners. * @property _el_events * @static * @private */ _el_events = _eventenv.dom_map; 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 1000@amp;40 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: 1000, /** * The poll interval in milliseconds * @property POLL_INTERVAL * @type int * @static * @final */ POLL_INTERVAL: 40, /** * 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, /** * 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, /** * @method startInterval * @static * @private */ startInterval: function() { if (!Event._interval) { Event._interval = setInterval(Event._poll, Event.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. * *
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} p_obj an optional object to be passed back as * a parameter to fn. * @param {boolean|object} p_override If set to true, fn will execute * in the context of p_obj, if set to an object it * will execute in the context of that object * @param checkContent {boolean} check child node readiness (onContentReady) * @static * @deprecated Use Y.on("available") */ // @TODO fix arguments onAvailable: function(id, fn, p_obj, p_override, checkContent, compat) { var a = Y.Array(id), i, availHandle; for (i=0; i