# Yahoo! UI Library

### event 3.0.0

Yahoo! UI Library > event > event-facade-dom.js (source view)
Search:
Filters Show Private Show Protected Show Deprecated

    (function() {

    /**
     * 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 {Event.Custom} the custom event wrapper for this DOM event
     */

    /*
     * @TODO constants? LEFTBUTTON, MIDDLEBUTTON, RIGHTBUTTON, keys
     */

    /*

    var whitelist = {
        altKey          : 1,
        // "button"          : 1, // we supply
        // "bubbles"         : 1, // needed?
        // "cancelable"      : 1, // needed?
        // "charCode"        : 1, // we supply
        cancelBubble    : 1,
        // "currentTarget"   : 1, // we supply
        ctrlKey         : 1,
        clientX         : 1, // needed?
        clientY         : 1, // needed?
        detail          : 1, // not fully implemented
        // "fromElement"     : 1,
        keyCode         : 1,
        // "height"          : 1, // needed?
        // "initEvent"       : 1, // need the init events?
        // "initMouseEvent"  : 1,
        // "initUIEvent"     : 1,
        // "layerX"          : 1, // needed?
        // "layerY"          : 1, // needed?
        metaKey         : 1,
        // "modifiers"       : 1, // needed?
        // "offsetX"         : 1, // needed?
        // "offsetY"         : 1, // needed?
        // "preventDefault"  : 1, // we supply
        // "reason"          : 1, // IE proprietary
        // "relatedTarget"   : 1,
        // "returnValue"     : 1, // needed?
        shiftKey        : 1,
        // "srcUrn"          : 1, // IE proprietary
        // "srcElement"      : 1,
        // "srcFilter"       : 1, IE proprietary
        // "stopPropagation" : 1, // we supply
        // "target"          : 1,
        // "timeStamp"       : 1, // needed?
        // "toElement"       : 1,
        type            : 1,
        // "view"            : 1,
        // "which"           : 1, // we supply
        // "width"           : 1, // needed?
        x               : 1,
        y               : 1
    },

    */

        var ua = Y.UA,

        /**
         * 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) {
            try {
                if (n && 3 == n.nodeType) {
                    n = n.parentNode;
                }
            } catch(e) {
                return null;
            }

            return Y.one(n);
        };

    // provide a single event with browser abstractions resolved
    //
    // include all properties for both browers?
    // include only DOM2 spec properties?
    // provide browser-specific facade?

    Y.DOMEventFacade = function(ev, currentTarget, wrapper) {

        wrapper = wrapper || {};

        var e = ev, ot = currentTarget, d = Y.config.doc, b = d.body,
            x = e.pageX, y = e.pageY, c, t;

        this.altKey   = e.altKey;
        this.ctrlKey  = e.ctrlKey;
        this.metaKey  = e.metaKey;
        this.shiftKey = e.shiftKey;
        this.type     = e.type;
        this.clientX  = e.clientX;
        this.clientY  = e.clientY;

        //////////////////////////////////////////////////////

        if (!x && 0 !== x) {
            x = e.clientX || 0;
            y = e.clientY || 0;

            if (ua.ie) {
                x += Math.max(d.documentElement.scrollLeft, b.scrollLeft);
                y += Math.max(d.documentElement.scrollTop, b.scrollTop);
            }
        }

        this._yuifacade = true;

        /**
         * The native event
         * @property _event
         */
        this._event = e;

        /**
         * The X location of the event on the page (including scroll)
         * @property pageX
         * @type int
         */
        this.pageX = x;

        /**
         * The Y location of the event on the page (including scroll)
         * @property pageY
         * @type int
         */
        this.pageY = y;

        //////////////////////////////////////////////////////

        c = e.keyCode || e.charCode || 0;

        if (ua.webkit && (c in webkitKeymap)) {
            c = webkitKeymap[c];
        }

        /**
         * The keyCode for key events.  Uses charCode if keyCode is not available
         * @property keyCode
         * @type int
         */
        this.keyCode = c;

        /**
         * The charCode for key events.  Same as keyCode
         * @property charCode
         * @type int
         */
        this.charCode = c;

        //////////////////////////////////////////////////////

        /**
         * The button that was pushed.
         * @property button
         * @type int
         */
        this.button = e.which || e.button;

        /**
         * The button that was pushed.  Same as button.
         * @property which
         * @type int
         */
        this.which = this.button;

        //////////////////////////////////////////////////////

        /**
         * Node reference for the targeted element
         * @propery target
         * @type Node
         */
        this.target = resolve(e.target || e.srcElement);

        /**
         * Node reference for the element that the listener was attached to.
         * @propery currentTarget
         * @type Node
         */
        this.currentTarget = resolve(ot);

        t = e.relatedTarget;

        if (!t) {
            if (e.type == "mouseout") {
                t = e.toElement;
            } else if (e.type == "mouseover") {
                t = e.fromElement;
            }
        }

        /**
         * Node reference to the relatedTarget
         * @propery relatedTarget
         * @type Node
         */
        this.relatedTarget = resolve(t);

        /**
         * 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 int
         */
        if (e.type == "mousewheel" || e.type == "DOMMouseScroll") {
            this.wheelDelta = (e.detail) ? (e.detail * -1) : Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
        }

        //////////////////////////////////////////////////////
        // methods

        /**
         * Stops the propagation to the next bubble target
         * @method stopPropagation
         */
        this.stopPropagation = function() {
            if (e.stopPropagation) {
                e.stopPropagation();
            } else {
                e.cancelBubble = true;
            }
            wrapper.stopped = 1;
        };

        /**
         * Stops the propagation to the next bubble target and
         * prevents any additional listeners from being exectued
         * on the current target.
         * @method stopImmediatePropagation
         */
        this.stopImmediatePropagation = function() {
            if (e.stopImmediatePropagation) {
                e.stopImmediatePropagation();
            } else {
                this.stopPropagation();
            }
            wrapper.stopped = 2;
        };

        /**
         * 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).
         */
        this.preventDefault = function(returnValue) {
            if (e.preventDefault) {
                e.preventDefault();
            }
            e.returnValue = returnValue || false;
            wrapper.prevented = 1;
        };

        /**
         * 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
         */
        this.halt = function(immediate) {
            if (immediate) {
                this.stopImmediatePropagation();
            } else {
                this.stopPropagation();
            }

            this.preventDefault();
        };

    };

    })();

Copyright © 2009 Yahoo! Inc. All rights reserved.