Beispiel #1
0
 public EventTarget(Bridge.Html5.EventTarget opt_element = null)
 {
     orgTarget_            = opt_element;
     eventTargetListeners_ = new ListenerMap(this);
     actualEventTarget_    = this;
     this.addImplementation();
 }
Beispiel #2
0
        /// <summary>
        /// </summary>
        /// <param name="src">The source object.</param>
        /// <returns>A listener map for the given
        /// source object, or null if none exists.</returns>
        private static ListenerMap getListenerMap_(Bridge.Html5.EventTarget src)
        {
            var listenerMap = src[LISTENER_MAP_PROP_];

            // IE serializes the property as well (e.g. when serializing outer
            // HTML). So we must check that the value is of the correct type.
            return(listenerMap as ListenerMap);
        }
Beispiel #3
0
 /// <summary>
 /// Accepts a browser event object and creates a patched, cross browser event
 /// object.
 /// The content of this object will not be initialized if no event object is
 /// provided. If this is the case, init() needs to be invoked separately.
 /// </summary>
 /// <param name="opt_e">Browser event object.</param>
 /// <param name="opt_currentTarget">Current target for event.</param>
 public BrowserEvent(Bridge.Html5.Event opt_e, Bridge.Html5.EventTarget opt_currentTarget = null)
     : base(opt_e)
 {
     if (opt_e != null)
     {
         this.init(opt_e, opt_currentTarget);
     }
 }
Beispiel #4
0
 internal void initMouseEvent(string typeArg, bool bubbles, bool cancelable,
                              object view, int detail, double screenX, double screenY,
                              double clientX, double clientY, bool ctrlKey, bool altKey, bool shiftKey,
                              bool metaKey, MouseButton button, Bridge.Html5.EventTarget target)
 {
     this.type       = typeArg;
     this.bubbles    = bubbles;
     this.cancelable = cancelable;
     this.view       = view;
     this.detail     = detail;
     this.screenX    = (int)screenX;
     this.screenY    = (int)screenY;
     this.clientX    = (int)clientX;
     this.clientY    = (int)clientY;
     this.ctrlKey    = ctrlKey;
     this.altKey     = altKey;
     this.shiftKey   = shiftKey;
     this.metaKey    = metaKey;
     this.button     = (int)button;
     this.target     = target;
 }
Beispiel #5
0
        /// <summary>
        /// Note that a one-off listener will not change an existing listener,
        /// if any. On the other hand a normal listener will change existing
        /// one-off listener to become a normal listener.
        /// </summary>
        /// <param name="src">The node to listen to events on.</param>
        /// <param name="type">Event type.</param>
        /// <param name="listener">Callback function.</param>
        /// <param name="callOnce">Whether the listener is a one-off
        /// listener or otherwise.</param>
        /// <param name="opt_capt">Whether to fire in capture phase (defaults to
        /// false).</param>
        /// <param name="opt_handler">Element in whose scope to call the listener.</param>
        /// <returns>Unique key for the listener.</returns>
        private static Listener listen_(Bridge.Html5.EventTarget src, string type, Delegate listener,
                                        bool callOnce, bool opt_capt = false, object opt_handler = null)
        {
            if (type == null)
            {
                throw new Exception("Invalid event type");
            }

            var capture = !!opt_capt;

            if (capture && !goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT)
            {
                if (goog.events.CAPTURE_SIMULATION_MODE ==
                    goog.events.CaptureSimulationMode.OFF_AND_FAIL)
                {
                    goog.asserts.fail("Can not register capture listener in IE8-.");
                    return(null);
                }
                else if (
                    goog.events.CAPTURE_SIMULATION_MODE ==
                    goog.events.CaptureSimulationMode.OFF_AND_SILENT)
                {
                    return(null);
                }
            }

            var listenerMap = goog.events.getListenerMap_(src);

            if (listenerMap == null)
            {
                src[goog.events.LISTENER_MAP_PROP_] = listenerMap =
                    new goog.events.ListenerMap(src);
            }

            var listenerObj =
                listenerMap.add(type, listener, callOnce, opt_capt, opt_handler);

            // If the listenerObj already has a proxy, it has been set up
            // previously. We simply return.
            if (listenerObj.proxy != null)
            {
                return(listenerObj);
            }

            var proxy = goog.events.getProxy();

            listenerObj.proxy = proxy;

            proxy.src      = src;
            proxy.listener = listenerObj.listener;
#if false
            // Attach the proxy through the browser's API
            if (Script.IsDefined(src, "addEventListener"))
            {
                src.AddEventListener(type, proxy.Instance, capture);
            }
            else if (Script.IsDefined(src, "attachEvent"))
            {
                // The else if above used to be an unconditional else. It would call
                // exception on IE11, spoiling the day of some callers. The previous
                // incarnation of this code, from 2007, indicates that it replaced an
                // earlier still version that caused excess allocations on IE6.
                Script.Get <Action <object, Delegate> >(src, "attachEvent")(goog.events.getOnString_(type), proxy.Instance);
            }
            else
            {
                throw new Exception("addEventListener and attachEvent are unavailable.");
            }
#else
            src.AddEventListener(type, proxy.Instance, capture);
#endif
            goog.events.listenerCountEstimate_++;
            return(listenerObj);
        }
Beispiel #6
0
        /// <summary>
        /// Handles an event and dispatches it to the correct listeners. This
        /// function is a proxy for the real listener the user specified.
        /// </summary>
        /// <param name="listener">The listener object.</param>
        /// <param name="opt_evt">Optional event object that gets passed in via the
        /// native event handlers.</param>
        /// <returns>Result of the event handler.</returns>
        private static bool handleBrowserEvent_(Bridge.Html5.EventTarget _this, goog.events.Listener listener, Bridge.Html5.Event opt_evt = null)
        {
            if (listener.removed)
            {
                return(true);
            }

            // Synthesize event propagation if the browser does not support W3C
            // event model.
            if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT)
            {
                var ieEvent = opt_evt ??
                              ((Bridge.Html5.Event)goog.le.getObjectByName("window.event"));
                var evt = new goog.events.BrowserEvent(ieEvent, _this);
                /** @type {boolean} */
                var retval = true;

                if (goog.events.CAPTURE_SIMULATION_MODE ==
                    goog.events.CaptureSimulationMode.ON)
                {
                    // If we have not marked this event yet, we should perform capture
                    // simulation.
                    if (!goog.events.isMarkedIeEvent_(ieEvent))
                    {
                        goog.events.markIeEvent_(ieEvent);

                        var ancestors = new JsArray <Node>();
                        for (var parent = (Node)evt.currentTarget; parent != null;
                             parent = parent.ParentNode)
                        {
                            ancestors.Push(parent);
                        }

                        // Fire capture listeners.
                        var type = listener.type;
                        for (var i = ancestors.Length - 1; !evt.propagationStopped_ && i >= 0;
                             i--)
                        {
                            evt.currentTarget = ancestors[i];
                            var result =
                                goog.events.fireListeners_(ancestors[i], type, true, evt);
                            retval = retval && result != null;
                        }

                        // Fire bubble listeners.
                        //
                        // We can technically rely on IE to perform bubble event
                        // propagation. However, it turns out that IE fires events in
                        // opposite order of attachEvent registration, which broke
                        // some code and tests that rely on the order. (While W3C DOM
                        // Level 2 Events TR leaves the event ordering unspecified,
                        // modern browsers and W3C DOM Level 3 Events Working Draft
                        // actually specify the order as the registration order.)
                        for (var i = 0; !evt.propagationStopped_ && i < ancestors.Length; i++)
                        {
                            evt.currentTarget = ancestors[i];
                            var result =
                                goog.events.fireListeners_(ancestors[i], type, false, evt);
                            retval = retval && result != null;
                        }
                    }
                }
                else
                {
                    retval = goog.events.fireListener(listener, evt);
                }
                return(retval);
            }

            // Otherwise, simply fire the listener.
            return(goog.events.fireListener(
                       listener, new goog.events.BrowserEvent(opt_evt, _this)));
        }
Beispiel #7
0
            /// <summary>
            /// Accepts a browser event object and creates a patched, cross browser event
            /// object.
            /// </summary>
            /// <param name="e">Browser event object.</param>
            /// <param name="opt_currentTarget">Current target for event.</param>
            public void init(Bridge.Html5.Event e, Bridge.Html5.EventTarget opt_currentTarget)
            {
                var type = this.type = e.Type;

                /**
                 * On touch devices use the first "changed touch" as the relevant touch.
                 * @type {Touch}
                 */
                var relevantTouch = e.ChangedTouches != null ? e.ChangedTouches[0] : null;

                // TODO(nicksantos): Change this.target to type EventTarget.
                this.target = (e.Target) ?? e.SrcElement;

                // TODO(nicksantos): Change this.currentTarget to type EventTarget.
                this.currentTarget = opt_currentTarget;

                var relatedTarget = (Node)e.RelatedTarget;

                if (relatedTarget != null)
                {
                    // There's a bug in FireFox where sometimes, relatedTarget will be a
                    // chrome element, and accessing any property of it will get a permission
                    // denied exception. See:
                    // https://bugzilla.mozilla.org/show_bug.cgi?id=497780
                    if (goog.userAgent.GECKO)
                    {
                        if (!goog.reflect.canAccessProperty(relatedTarget, "nodeName"))
                        {
                            relatedTarget = null;
                        }
                    }
                    // TODO(arv): Use goog.events.EventType when it has been refactored into its
                    // own file.
                }
                else if (type == goog.events.EventType.MOUSEOVER)
                {
                    relatedTarget = e.FromElement;
                }
                else if (type == goog.events.EventType.MOUSEOUT)
                {
                    relatedTarget = e.ToElement;
                }

                this.relatedTarget = relatedTarget;

                if (relevantTouch != null)
                {
                    this.clientX = Script.IsDefined(relevantTouch, "clientX") ?
                                   (int)relevantTouch.ClientX :
                                   (int)relevantTouch.PageX;
                    this.clientY = Script.IsDefined(relevantTouch, "clientY") ?
                                   (int)relevantTouch.ClientY :
                                   (int)relevantTouch.PageY;
                    this.screenX = relevantTouch.ScreenX;
                    this.screenY = relevantTouch.ScreenY;
                }
                else
                {
                    // Webkit emits a lame warning whenever layerX/layerY is accessed.
                    // http://code.google.com/p/chromium/issues/detail?id=101733
                    this.offsetX = (goog.userAgent.WEBKIT || e.IsDefined("offsetX")) ?
                                   (int)e.OffsetX :
                                   (int)e.LayerX;
                    this.offsetY = (goog.userAgent.WEBKIT || e.IsDefined("offsetY")) ?
                                   (int)e.OffsetY :
                                   (int)e.LayerY;
                    this.clientX = e.IsDefined("clientX") ? (int)e.ClientX : (int)e.PageX;
                    this.clientY = e.IsDefined("clientY") ? (int)e.ClientY : (int)e.PageY;
                    this.screenX = e.IsDefined("screenX") ? (int)e.ScreenX : 0;
                    this.screenY = e.IsDefined("screenY") ? (int)e.ScreenY : 0;
                }

                this.button = e.Button;

                this.keyCode             = e.IsDefined("keyCode") ? e.KeyCode : 0;
                this.charCode            = e.IsDefined("charCode") ? e.CharCode : (type == "keypress" ? e.KeyCode : 0);
                this.ctrlKey             = e.CtrlKey;
                this.altKey              = e.AltKey;
                this.shiftKey            = e.ShiftKey;
                this.metaKey             = e.MetaKey;
                this.platformModifierKey = goog.userAgent.MAC ? e.MetaKey : e.CtrlKey;
                this.state  = e.State;
                this.event_ = e;
                if (e.IsDefined("defaultPrevented"))
                {
                    this.preventDefault();
                }
            }
Beispiel #8
0
 public EventHandler unlisten(Bridge.Html5.EventTarget src, Union <string, JsArray <string> > type,
                              Delegate opt_fn = null, bool opt_capture = false, object opt_scope = null)
 {
     return(unlisten(new EventTarget(src), type, opt_fn, opt_capture, opt_scope));
 }