From 05de2b5109f8bf94da423c98cec2e676232e3de6 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 20 Jan 2012 03:37:11 +0100 Subject: [PATCH 1/6] Don't let button controls interfer with handlers. This change involves removal of the map's eventsDiv and introduces an OpenLayers.Events.buttonclick component that adds a buttonclick event which makes sure that only events that are not related to clicking a button propagate. This allows button controls to be on the map's viewPortDiv again. --- lib/OpenLayers.js | 1 + lib/OpenLayers/Control/LayerSwitcher.js | 110 ++++++----------- lib/OpenLayers/Control/OverviewMap.js | 62 +++++----- lib/OpenLayers/Control/PanZoom.js | 85 ++++++-------- lib/OpenLayers/Control/Panel.js | 47 ++++---- lib/OpenLayers/Events.js | 86 ++++++++++++-- lib/OpenLayers/Events/buttonclick.js | 150 ++++++++++++++++++++++++ lib/OpenLayers/Handler/Box.js | 8 +- lib/OpenLayers/Handler/Drag.js | 2 +- lib/OpenLayers/Handler/Hover.js | 2 +- lib/OpenLayers/Handler/Point.js | 2 +- lib/OpenLayers/Layer/EventPane.js | 2 +- lib/OpenLayers/Map.js | 13 +- lib/OpenLayers/Util.js | 1 + lib/deprecated.js | 10 +- tests/Control/PanZoom.html | 12 +- tests/Control/Panel.html | 6 +- tests/Events.html | 5 +- tests/Events/buttonclick.html | 133 +++++++++++++++++++++ tests/Handler/Drag.html | 2 +- tests/Layer/EventPane.html | 4 +- tests/list-tests.html | 1 + 22 files changed, 520 insertions(+), 224 deletions(-) create mode 100644 lib/OpenLayers/Events/buttonclick.js create mode 100644 tests/Events/buttonclick.html diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index c8bab14984..3ffa1b6a84 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -111,6 +111,7 @@ "Rico/Corner.js", "Rico/Color.js", "OpenLayers/Events.js", + "OpenLayers/Events/buttonclick.js", "OpenLayers/Request.js", "OpenLayers/Request/XMLHttpRequest.js", "OpenLayers/Projection.js", diff --git a/lib/OpenLayers/Control/LayerSwitcher.js b/lib/OpenLayers/Control/LayerSwitcher.js index 3f81b3bfdc..552b650155 100644 --- a/lib/OpenLayers/Control/LayerSwitcher.js +++ b/lib/OpenLayers/Control/LayerSwitcher.js @@ -7,6 +7,7 @@ * @requires OpenLayers/Control.js * @requires OpenLayers/Lang.js * @requires OpenLayers/Console.js + * @requires OpenLayers/Events/buttonclick.js */ /** @@ -130,20 +131,16 @@ OpenLayers.Control.LayerSwitcher = */ destroy: function() { - OpenLayers.Event.stopObservingElement(this.div); - - OpenLayers.Event.stopObservingElement(this.minimizeDiv); - OpenLayers.Event.stopObservingElement(this.maximizeDiv); - //clear out layers info and unregister their events this.clearLayersArray("base"); this.clearLayersArray("data"); this.map.events.un({ - "addlayer": this.redraw, - "changelayer": this.redraw, - "removelayer": this.redraw, - "changebaselayer": this.redraw, + buttonclick: this.onButtonClick, + addlayer: this.redraw, + changelayer: this.redraw, + removelayer: this.redraw, + changebaselayer: this.redraw, scope: this }); @@ -160,10 +157,11 @@ OpenLayers.Control.LayerSwitcher = OpenLayers.Control.prototype.setMap.apply(this, arguments); this.map.events.on({ - "addlayer": this.redraw, - "changelayer": this.redraw, - "removelayer": this.redraw, - "changebaselayer": this.redraw, + buttonclick: this.onButtonClick, + addlayer: this.redraw, + changelayer: this.redraw, + removelayer: this.redraw, + changebaselayer: this.redraw, scope: this }); }, @@ -192,6 +190,20 @@ OpenLayers.Control.LayerSwitcher = return this.div; }, + /** + * Method: onButtonClick + * + * Parameters: + * evt - {Event} + */ + onButtonClick: function(evt) { + if (evt.button === this.minimizeDiv) { + this.minimizeControl(); + } else if (evt.button === this.maximizeDiv) { + this.maximizeControl(); + }; + }, + /** * Method: clearLayersArray * User specifies either "base" or "data". we then clear all the @@ -317,10 +329,11 @@ OpenLayers.Control.LayerSwitcher = 'layer': layer, 'layerSwitcher': this }; - OpenLayers.Event.observe(inputElem, "mouseup", - OpenLayers.Function.bindAsEventListener(this.onInputClick, - context) + var onInputClick = OpenLayers.Function.bindAsEventListener( + this.onInputClick, context ); + OpenLayers.Event.observe(inputElem, "mousedown", onInputClick); + OpenLayers.Event.observe(inputElem, "touchstart", onInputClick); // create span var labelSpan = document.createElement("span"); @@ -331,10 +344,8 @@ OpenLayers.Control.LayerSwitcher = labelSpan.innerHTML = layer.name; labelSpan.style.verticalAlign = (baseLayer) ? "bottom" : "baseline"; - OpenLayers.Event.observe(labelSpan, "click", - OpenLayers.Function.bindAsEventListener(this.onInputClick, - context) - ); + OpenLayers.Event.observe(labelSpan, "click", onInputClick); + OpenLayers.Event.observe(labelSpan, "touchstart", onInputClick); // create line break var br = document.createElement("br"); @@ -500,16 +511,6 @@ OpenLayers.Control.LayerSwitcher = */ loadContents: function() { - //configure main div - - OpenLayers.Event.observe(this.div, "mouseup", - OpenLayers.Function.bindAsEventListener(this.mouseUp, this)); - OpenLayers.Event.observe(this.div, "click", - this.ignoreEvent); - OpenLayers.Event.observe(this.div, "mousedown", - OpenLayers.Function.bindAsEventListener(this.mouseDown, this)); - OpenLayers.Event.observe(this.div, "dblclick", this.ignoreEvent); - // layers list div this.layersDiv = document.createElement("div"); this.layersDiv.id = this.id + "_layersDiv"; @@ -561,11 +562,8 @@ OpenLayers.Control.LayerSwitcher = null, img, "absolute"); - OpenLayers.Element.addClass(this.maximizeDiv, "maximizeDiv"); + OpenLayers.Element.addClass(this.maximizeDiv, "maximizeDiv olButton"); this.maximizeDiv.style.display = "none"; - OpenLayers.Event.observe(this.maximizeDiv, "click", - OpenLayers.Function.bindAsEventListener(this.maximizeControl, this) - ); this.div.appendChild(this.maximizeDiv); @@ -577,53 +575,11 @@ OpenLayers.Control.LayerSwitcher = null, img, "absolute"); - OpenLayers.Element.addClass(this.minimizeDiv, "minimizeDiv"); + OpenLayers.Element.addClass(this.minimizeDiv, "minimizeDiv olButton"); this.minimizeDiv.style.display = "none"; - OpenLayers.Event.observe(this.minimizeDiv, "click", - OpenLayers.Function.bindAsEventListener(this.minimizeControl, this) - ); this.div.appendChild(this.minimizeDiv); }, - /** - * Method: ignoreEvent - * - * Parameters: - * evt - {Event} - */ - ignoreEvent: function(evt) { - OpenLayers.Event.stop(evt); - }, - - /** - * Method: mouseDown - * Register a local 'mouseDown' flag so that we'll know whether or not - * to ignore a mouseUp event - * - * Parameters: - * evt - {Event} - */ - mouseDown: function(evt) { - this.isMouseDown = true; - this.ignoreEvent(evt); - }, - - /** - * Method: mouseUp - * If the 'isMouseDown' flag has been set, that means that the drag was - * started from within the LayerSwitcher control, and thus we can - * ignore the mouseup. Otherwise, let the Event continue. - * - * Parameters: - * evt - {Event} - */ - mouseUp: function(evt) { - if (this.isMouseDown) { - this.isMouseDown = false; - this.ignoreEvent(evt); - } - }, - CLASS_NAME: "OpenLayers.Control.LayerSwitcher" }); diff --git a/lib/OpenLayers/Control/OverviewMap.js b/lib/OpenLayers/Control/OverviewMap.js index 4c92522bb0..ee21cc4b26 100644 --- a/lib/OpenLayers/Control/OverviewMap.js +++ b/lib/OpenLayers/Control/OverviewMap.js @@ -6,7 +6,7 @@ /** * @requires OpenLayers/Control.js * @requires OpenLayers/BaseTypes.js - * @requires OpenLayers/Events.js + * @requires OpenLayers/Events/buttonclick.js */ /** @@ -157,7 +157,7 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { this.handlers.drag.destroy(); } - this.ovmap && this.ovmap.eventsDiv.removeChild(this.extentRectangle); + this.ovmap && this.ovmap.viewPortDiv.removeChild(this.extentRectangle); this.extentRectangle = null; if (this.rectEvents) { @@ -177,20 +177,19 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { this.element = null; if (this.maximizeDiv) { - OpenLayers.Event.stopObservingElement(this.maximizeDiv); this.div.removeChild(this.maximizeDiv); this.maximizeDiv = null; } if (this.minimizeDiv) { - OpenLayers.Event.stopObservingElement(this.minimizeDiv); this.div.removeChild(this.minimizeDiv); this.minimizeDiv = null; } this.map.events.un({ - "moveend": this.update, - "changebaselayer": this.baseLayerDraw, + buttonclick: this.onButtonClick, + moveend: this.update, + changebaselayer: this.baseLayerDraw, scope: this }); @@ -247,11 +246,7 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { img, 'absolute'); this.maximizeDiv.style.display = 'none'; - this.maximizeDiv.className = this.displayClass + 'MaximizeButton'; - OpenLayers.Event.observe(this.maximizeDiv, 'click', - OpenLayers.Function.bindAsEventListener(this.maximizeControl, - this) - ); + this.maximizeDiv.className = this.displayClass + 'MaximizeButton olButton'; this.div.appendChild(this.maximizeDiv); // minimize button div @@ -263,26 +258,8 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { img, 'absolute'); this.minimizeDiv.style.display = 'none'; - this.minimizeDiv.className = this.displayClass + 'MinimizeButton'; - OpenLayers.Event.observe(this.minimizeDiv, 'click', - OpenLayers.Function.bindAsEventListener(this.minimizeControl, - this) - ); - this.div.appendChild(this.minimizeDiv); - - var eventsToStop = ['dblclick','mousedown']; - - for (var i=0, len=eventsToStop.length; i} + */ + setMap: function(map) { + OpenLayers.Control.prototype.setMap.apply(this, arguments); + this.map.events.register("buttonclick", this, this.onButtonClick); + }, + /** * Method: draw * @@ -126,30 +141,9 @@ OpenLayers.Control.PanZoom = OpenLayers.Class(OpenLayers.Control, { btn.style.cursor = "pointer"; //we want to add the outer div this.div.appendChild(btn); - - OpenLayers.Event.observe(btn, "mousedown", - OpenLayers.Function.bindAsEventListener(this.buttonDown, btn)); - OpenLayers.Event.observe(btn, "dblclick", - OpenLayers.Function.bindAsEventListener(this.doubleClick, btn)); - OpenLayers.Event.observe(btn, "click", - OpenLayers.Function.bindAsEventListener(this.doubleClick, btn)); btn.action = id; - btn.map = this.map; + btn.className = "olButton"; - if(!this.slideRatio){ - var slideFactorPixels = this.slideFactor; - var getSlideFactor = function() { - return slideFactorPixels; - }; - } else { - var slideRatio = this.slideRatio; - var getSlideFactor = function(dim) { - return this.map.getSize()[dim] * slideRatio; - }; - } - - btn.getSlideFactor = getSlideFactor; - //we want to remember/reference the outer div this.buttons.push(btn); return btn; @@ -162,9 +156,6 @@ OpenLayers.Control.PanZoom = OpenLayers.Class(OpenLayers.Control, { * btn - {Object} */ _removeButton: function(btn) { - OpenLayers.Event.stopObservingElement(btn); - btn.map = null; - btn.getSlideFactor = null; this.div.removeChild(btn); OpenLayers.Util.removeItem(this.buttons, btn); }, @@ -179,31 +170,14 @@ OpenLayers.Control.PanZoom = OpenLayers.Class(OpenLayers.Control, { }, /** - * Method: doubleClick + * Method: onButtonClick * * Parameters: - * evt - {Event} - * - * Returns: - * {Boolean} + * evt - {Event} */ - doubleClick: function (evt) { - OpenLayers.Event.stop(evt); - return false; - }, - - /** - * Method: buttonDown - * - * Parameters: - * evt - {Event} - */ - buttonDown: function (evt) { - if (!OpenLayers.Event.isLeftClick(evt)) { - return; - } - - switch (this.action) { + onButtonClick: function(evt) { + var btn = evt.button; + switch (btn.action) { case "panup": this.map.pan(0, -this.getSlideFactor("h")); break; @@ -226,8 +200,21 @@ OpenLayers.Control.PanZoom = OpenLayers.Class(OpenLayers.Control, { this.map.zoomToMaxExtent(); break; } - - OpenLayers.Event.stop(evt); + }, + + /** + * Method: getSlideFactor + * + * Parameters: + * dim - {String} "w" or "h" (for width or height). + * + * Returns: + * {Number} The slide factor for panning in the requested direction. + */ + getSlideFactor: function(dim) { + return this.slideRatio ? + this.map.getSize()[dim] * this.slideRatio : + this.slideFactor; }, CLASS_NAME: "OpenLayers.Control.PanZoom" diff --git a/lib/OpenLayers/Control/Panel.js b/lib/OpenLayers/Control/Panel.js index 4c6e7e6183..8b77c5272f 100644 --- a/lib/OpenLayers/Control/Panel.js +++ b/lib/OpenLayers/Control/Panel.js @@ -5,6 +5,7 @@ /** * @requires OpenLayers/Control.js + * @requires OpenLayers/Events/buttonclick.js */ /** @@ -103,6 +104,9 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { * APIMethod: destroy */ destroy: function() { + if (this.map) { + this.map.events.unregister("buttonclick", this, this.onButtonClick); + } OpenLayers.Control.prototype.destroy.apply(this, arguments); for (var ctl, i = this.controls.length - 1; i >= 0; i--) { ctl = this.controls[i]; @@ -112,7 +116,6 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { deactivate: this.iconOff }); } - OpenLayers.Event.stopObservingElement(ctl.panel_div); ctl.panel_div = null; } this.activeState = null; @@ -166,6 +169,12 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { */ draw: function() { OpenLayers.Control.prototype.draw.apply(this, arguments); + if (this.div.parentNode === this.map.viewPortDiv) { + map.events.register("buttonclick", this, this.onButtonClick); + } else { + this.events.element = this.div; + this.events.register("buttonclick", this, this.onButtonClick); + } this.addControlsToMap(this.controls); return this.div; }, @@ -184,7 +193,7 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { } } }, - + /** * APIMethod: activateControl * This method is called when the user click on the icon representing a @@ -244,17 +253,11 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { // since they need to pass through. for (var i=0, len=controls.length; i=0; --i) { + if (controls[i].panel_div === button) { + this.activateControl(controls[i]); + break; + } + } }, /** diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index d3c96ae13e..c6ab5592c9 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -155,13 +155,18 @@ OpenLayers.Event = { * Parameters: * event - {Event} * allowDefault - {Boolean} If true, we stop the event chain but - * still allow the default browser - * behaviour (text selection, radio-button - * clicking, etc) - * Default false + * still allow the default browser behaviour (text selection, + * radio-button clicking, etc). Default is false. + * terminate - {Boolean} If true, no more listeners registered through an + * instance on the same event on the same element + * will receive this event. Extensions that call should set + * this to true. Default is false. */ - stop: function(event, allowDefault) { + stop: function(event, allowDefault, terminate) { + if (terminate) { + event._terminated = true; + } if (!allowDefault) { if (event.preventDefault) { event.preventDefault(); @@ -450,6 +455,26 @@ OpenLayers.Events = OpenLayers.Class({ * the location of the element in the page changes */ includeXY: false, + + /** + * Property: extensions + * {Object} Event extensions registered with this instance. Keys are + * event types, values are extension instances. + * + * Extensions create an event in addition to browser events, which usually + * fires when a sequence of browser events is completed. Extensions are + * automatically instantiated when a listener is registered for an event + * provided by an extension. + * + * Extesions are created in the namespace using + * , and named after the event they provide. + * The constructor recieves the target instance as + * argument. Extensions are expected to have an "observe" method, which is + * called to register its sequence events on the target's dom element, + * using . See + * for a reference implementation. + */ + extensions: null, /** * Method: clearMouseListener @@ -478,6 +503,7 @@ OpenLayers.Events = OpenLayers.Class({ this.object = object; this.fallThrough = fallThrough; this.listeners = {}; + this.extensions = {}; // if a dom element is specified, add a listeners list // for browser events on the element and register them @@ -500,6 +526,12 @@ OpenLayers.Events = OpenLayers.Class({ * APIMethod: destroy */ destroy: function () { + for (var e in this.extensions) { + if (typeof this.extensions[e].destroy === "function") { + this.extensions[e].destroy(); + } + } + this.extensions = null; if (this.element) { OpenLayers.Event.stopObservingElement(this.element); if(this.element.hasScrollEvent) { @@ -531,9 +563,15 @@ OpenLayers.Events = OpenLayers.Class({ * * Parameters: * element - {HTMLDOMElement} a DOM element to attach browser events to + * options - {Object} Additional options for his method. + * + * Valid options: + * keepElement - {Boolean} If set to true, the instance will not stop + * observing events on an element it was previously attached to. */ - attachToElement: function (element) { - if(this.element) { + attachToElement: function (element, options) { + options = options || {}; + if(this.element && !options.keepElement) { OpenLayers.Event.stopObservingElement(this.element); } this.element = element; @@ -547,6 +585,33 @@ OpenLayers.Events = OpenLayers.Class({ OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); }, + /** + * Method: addExtension + * Adds an extension event to this instance. + * + * Parameters: + * type - {String} the name of the extension event type to add + */ + addExtension: function(type) { + if (this.element.attachEvent && !this.element.addEventListener) { + // old IE - last registered, first triggered. No need to + // re-register the events to get them in a working order + this.extensions[type] = new OpenLayers.Events[type](this); + } else { + // Other browsers - last registered, last triggered. We stop + // observing the element, let the extensions register their browser + // events, and then we attach this instance to the element again. + OpenLayers.Event.stopObservingElement(this.element); + for (var t in this.extensions) { + if (typeof this.extensions[t].observe === "function") { + this.extensions[t].observe(); + } + } + this.extensions[type] = new OpenLayers.Events[type](this); + this.attachToElement(this.element, {keepElement: true}); + } + }, + /** * APIMethod: on * Convenience method for registering listeners with a common scope. @@ -612,6 +677,9 @@ OpenLayers.Events = OpenLayers.Class({ * the events queue instead of to the end. */ register: function (type, obj, func, priority) { + if (type in OpenLayers.Events && !this.extensions[type]) { + this.addExtension(type); + } if (func != null) { if (obj == null) { obj = this.object; @@ -784,8 +852,8 @@ OpenLayers.Events = OpenLayers.Class({ */ handleBrowserEvent: function (evt) { var type = evt.type, listeners = this.listeners[type]; - if(!listeners || listeners.length == 0) { - // noone's listening, bail out + if(!listeners || listeners.length == 0 || evt._terminated) { + // noone's listening or event was terminated through , bail out return; } // add clientX & clientY to all events - corresponds to average x, y diff --git a/lib/OpenLayers/Events/buttonclick.js b/lib/OpenLayers/Events/buttonclick.js new file mode 100644 index 0000000000..79b0403bdc --- /dev/null +++ b/lib/OpenLayers/Events/buttonclick.js @@ -0,0 +1,150 @@ +/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for + * full list of contributors). Published under the Clear BSD license. + * See http://svn.openlayers.org/trunk/openlayers/license.txt for the + * full text of the license. */ + +/** + * @requires OpenLayers/Events.js + */ + +/** + * Class: OpenLayers.Events.buttonclick + * Extension event type for handling buttons on top of a dom element. This + * event type fires "buttonclick" on its when a button was + * clicked. Buttons are detected by the "olButton" class. + * + * This event type makes sure that button clicks do not interfer with other + * events that are registered on the same . + */ +OpenLayers.Events.buttonclick = OpenLayers.Class({ + + /** + * APIProperty: target + * {} The events instance that the buttonclick event will + * be triggered on. + */ + target: null, + + /** + * Property: events + * {Array} Events to observe and conditionally stop from propagating when + * an element with the olButton (or its olAlphaImg child) is clicked. + */ + events: [ + 'mousedown', 'mouseup', 'click', 'dblclick', + 'touchstart', 'touchmove', 'touchend' + ], + + /** + * Property: startRegEx + * {RegExp} Regular expression to test Event.type for events that start + * a buttonclick sequence. + */ + startRegEx: /^mousedown|touchstart$/, + + /** + * Property: cancelRegEx + * {RegExp} Regular expression to test Event.type for events that cancel + * a buttonclick sequence. + */ + cancelRegEx: /^touchmove$/, + + /** + * Property: completeRegEx + * {RegExp} Regular expression to test Event.type for events that complete + * a buttonclick sequence. + */ + completeRegEx: /^mouseup|touchend$/, + + /** + * Constructor: OpenLayers.Events.buttonclick + * Construct a buttonclick event type. Applications are not supposed to + * create instances of this class - they are created on demand by + * instances. + * + * Parameters: + * options - {|Object} Target instance of + * or configuration properties for this + * instance. + * + * Required configuration properties: + * target - {} The events instance that the buttonclick + * event will be triggered on. + */ + initialize: function(options) { + if (options instanceof OpenLayers.Events) { + options = {target: options}; + } + OpenLayers.Util.extend(this, options); + + this._buttonClick = OpenLayers.Function.bindAsEventListener( + this.buttonClick, this + ); + this.observe(); + }, + + /** + * Method: observe + */ + observe: function() { + for (var i=this.events.length-1; i>=0; --i) { + OpenLayers.Event.observe( + this.target.element, this.events[i], this._buttonClick + ); + }; + }, + + /** + * Method: stopObserving + */ + stopObserving: function() { + for (var i=this.events.length-1; i>=0; --i) { + OpenLayers.Event.stopObserving( + this.target.element, this.events[i], this._buttonClick + ); + } + }, + + /** + * Method: destroy + */ + destroy: function() { + this.stopObserving() + }, + + /** + * Method: buttonClick + * Check if a button was clicked, and fire the buttonclick event + * + * Parameters: + * evt - {Event} + */ + buttonClick: function(evt) { + if (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse")) { + var element = OpenLayers.Event.element(evt); + if (OpenLayers.Element.hasClass(element, "olAlphaImg")) { + element = element.parentNode; + } + if (OpenLayers.Element.hasClass(element, "olButton")) { + if (this._buttonStarted) { + if (this.completeRegEx.test(evt.type)) { + this.target.triggerEvent("buttonclick", { + button: element + }); + } + if (this.cancelRegEx.test(evt.type)) { + delete this._buttonStarted; + } + OpenLayers.Event.stop(evt, false, true); + } + if (this.startRegEx.test(evt.type)) { + this._buttonStarted = true; + OpenLayers.Event.stop(evt, false, true); + } + } else { + delete this._buttonStarted; + } + } + } + +}); \ No newline at end of file diff --git a/lib/OpenLayers/Handler/Box.js b/lib/OpenLayers/Handler/Box.js index bbefce8679..76aad7386f 100644 --- a/lib/OpenLayers/Handler/Box.js +++ b/lib/OpenLayers/Handler/Box.js @@ -103,10 +103,10 @@ OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, { this.zoomBox.className = this.boxDivClassName; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; - this.map.eventsDiv.appendChild(this.zoomBox); + this.map.viewPortDiv.appendChild(this.zoomBox); OpenLayers.Element.addClass( - this.map.eventsDiv, "olDrawBox" + this.map.viewPortDiv, "olDrawBox" ); }, @@ -154,11 +154,11 @@ OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, { * Remove the zoombox from the screen and nullify our reference to it. */ removeBox: function() { - this.map.eventsDiv.removeChild(this.zoomBox); + this.map.viewPortDiv.removeChild(this.zoomBox); this.zoomBox = null; this.boxOffsets = null; OpenLayers.Element.removeClass( - this.map.eventsDiv, "olDrawBox" + this.map.viewPortDiv, "olDrawBox" ); }, diff --git a/lib/OpenLayers/Handler/Drag.js b/lib/OpenLayers/Handler/Drag.js index 01e539a945..a2adf66ed0 100644 --- a/lib/OpenLayers/Handler/Drag.js +++ b/lib/OpenLayers/Handler/Drag.js @@ -442,7 +442,7 @@ OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, { * {Boolean} Let the event propagate. */ mouseout: function (evt) { - if (this.started && OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) { + if (this.started && OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) { if(this.documentDrag === true) { this.addDocumentEvents(); } else { diff --git a/lib/OpenLayers/Handler/Hover.js b/lib/OpenLayers/Handler/Hover.js index 05eff52e28..b1bf58b860 100644 --- a/lib/OpenLayers/Handler/Hover.js +++ b/lib/OpenLayers/Handler/Hover.js @@ -107,7 +107,7 @@ OpenLayers.Handler.Hover = OpenLayers.Class(OpenLayers.Handler, { * {Boolean} Continue propagating this event. */ mouseout: function(evt) { - if (OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) { + if (OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) { this.clearTimer(); this.callback('move', [evt]); } diff --git a/lib/OpenLayers/Handler/Point.js b/lib/OpenLayers/Handler/Point.js index f0d5c5ff93..0b9ddb9dd4 100644 --- a/lib/OpenLayers/Handler/Point.js +++ b/lib/OpenLayers/Handler/Point.js @@ -545,7 +545,7 @@ OpenLayers.Handler.Point = OpenLayers.Class(OpenLayers.Handler, { * evt - {Event} The browser event */ mouseout: function(evt) { - if(OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) { + if(OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) { this.stoppedDown = this.stopDown; this.mouseDown = false; } diff --git a/lib/OpenLayers/Layer/EventPane.js b/lib/OpenLayers/Layer/EventPane.js index 8358b3f888..ae984356dd 100644 --- a/lib/OpenLayers/Layer/EventPane.js +++ b/lib/OpenLayers/Layer/EventPane.js @@ -108,7 +108,7 @@ OpenLayers.Layer.EventPane = OpenLayers.Class(OpenLayers.Layer, { } if (this.isFixed) { - this.map.eventsDiv.appendChild(this.pane); + this.map.viewPortDiv.appendChild(this.pane); } else { this.map.layerContainerDiv.appendChild(this.pane); } diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js index d440ce6a16..d24bee2882 100644 --- a/lib/OpenLayers/Map.js +++ b/lib/OpenLayers/Map.js @@ -513,17 +513,8 @@ OpenLayers.Map = OpenLayers.Class({ this.viewPortDiv.className = "olMapViewport"; this.div.appendChild(this.viewPortDiv); - // the eventsDiv is where we listen for all map events - var eventsDiv = document.createElement("div"); - eventsDiv.id = this.id + "_events"; - eventsDiv.style.position = "absolute"; - eventsDiv.style.width = "100%"; - eventsDiv.style.height = "100%"; - eventsDiv.style.zIndex = this.Z_INDEX_BASE.Control - 1; - this.viewPortDiv.appendChild(eventsDiv); - this.eventsDiv = eventsDiv; this.events = new OpenLayers.Events( - this, this.eventsDiv, null, this.fallThrough, + this, this.viewPortDiv, null, this.fallThrough, {includeXY: true} ); @@ -534,7 +525,7 @@ OpenLayers.Map = OpenLayers.Class({ this.layerContainerDiv.style.height = '100px'; this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1; - this.eventsDiv.appendChild(this.layerContainerDiv); + this.viewPortDiv.appendChild(this.layerContainerDiv); this.updateSize(); if(this.eventListeners instanceof Object) { diff --git a/lib/OpenLayers/Util.js b/lib/OpenLayers/Util.js index b9f92c6c04..2458a54b67 100644 --- a/lib/OpenLayers/Util.js +++ b/lib/OpenLayers/Util.js @@ -416,6 +416,7 @@ OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL, var div = OpenLayers.Util.createDiv(); var img = OpenLayers.Util.createImage(null, null, null, null, null, null, null, delayDisplay); + img.className = "olAlphaImg"; div.appendChild(img); OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL, position, diff --git a/lib/deprecated.js b/lib/deprecated.js index dd6c0bcf57..c22b849216 100644 --- a/lib/deprecated.js +++ b/lib/deprecated.js @@ -1202,7 +1202,7 @@ OpenLayers.Control.MouseDefaults = OpenLayers.Class(OpenLayers.Control, { this.zoomBox.style.opacity = "0.50"; this.zoomBox.style.fontSize = "1px"; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; - this.map.eventsDiv.appendChild(this.zoomBox); + this.map.viewPortDiv.appendChild(this.zoomBox); } document.onselectstart = OpenLayers.Function.False; OpenLayers.Event.stop(evt); @@ -1275,7 +1275,7 @@ OpenLayers.Control.MouseDefaults = OpenLayers.Class(OpenLayers.Control, { */ defaultMouseOut: function (evt) { if (this.mouseDragStart != null && - OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) { + OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) { if (this.zoomBox) { this.removeZoomBox(); } @@ -1339,7 +1339,7 @@ OpenLayers.Control.MouseDefaults = OpenLayers.Class(OpenLayers.Control, { * Remove the zoombox from the screen and nullify our reference to it. */ removeZoomBox: function() { - this.map.eventsDiv.removeChild(this.zoomBox); + this.map.viewPortDiv.removeChild(this.zoomBox); this.zoomBox = null; }, @@ -1602,7 +1602,7 @@ OpenLayers.Control.MouseToolbar = OpenLayers.Class( this.zoomBox.style.opacity = "0.50"; this.zoomBox.style.fontSize = "1px"; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; - this.map.eventsDiv.appendChild(this.zoomBox); + this.map.viewPortDiv.appendChild(this.zoomBox); this.performedDrag = true; break; case "measure": @@ -1769,7 +1769,7 @@ OpenLayers.Control.MouseToolbar = OpenLayers.Class( */ defaultMouseOut: function (evt) { if (this.mouseDragStart != null - && OpenLayers.Util.mouseLeft(evt, this.map.eventsDiv)) { + && OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) { if (this.zoomBox) { this.removeZoomBox(); if (this.startViaKeyboard) { diff --git a/tests/Control/PanZoom.html b/tests/Control/PanZoom.html index 41eab09deb..2e9a68b388 100644 --- a/tests/Control/PanZoom.html +++ b/tests/Control/PanZoom.html @@ -168,22 +168,26 @@ //up var delta = [0, -50]; var dir = "up"; - control.buttonDown.call(buttons[0], evt); + evt.button = buttons[0]; + control.onButtonClick.call(control, evt); //left var delta = [-125, 0]; var dir = "left"; - control.buttonDown.call(buttons[1], evt); + evt.button = buttons[1]; + control.onButtonClick.call(control, evt); //right var delta = [125, 0]; var dir = "right"; - control.buttonDown.call(buttons[2], evt); + evt.button = buttons[2]; + control.onButtonClick.call(control, evt); //down var delta = [0, 50]; var dir = "down"; - control.buttonDown.call(buttons[3], evt); + evt.button = buttons[3]; + control.onButtonClick.call(control, evt); map.destroy(); } diff --git a/tests/Control/Panel.html b/tests/Control/Panel.html index d74526bda2..d88a7a2abe 100644 --- a/tests/Control/Panel.html +++ b/tests/Control/Panel.html @@ -82,7 +82,7 @@ "activated one tool control, the other one is inactive and the toggle & button controls also."); panel.activateControl(toggleControl); - t.eq(toggleControl.panel_div.className,"mbControlTestToggleItemActive", + t.eq(toggleControl.panel_div.className,"mbControlTestToggleItemActive olButton", "className of icon div for toggle control is active."); t.ok(toolControl.active && !anotherToolControl.active && toggleControl.active, "activated the toggle control, which has no influence on the tool & togggle controls."); @@ -96,9 +96,9 @@ "activated the button control, which has no influence on the tool & togggle controls."); panel.activateControl(anotherToolControl); - t.eq(anotherToolControl.panel_div.className,"mbControlTestToolItemActive", + t.eq(anotherToolControl.panel_div.className,"mbControlTestToolItemActive olButton", "className of icon div for anotherToolControl is active."); - t.eq(toolControl.panel_div.className,"olControlZoomBoxItemInactive", + t.eq(toolControl.panel_div.className,"olControlZoomBoxItemInactive olButton", "className of icon div for toolControl is inactive."); t.ok(!toolControl.active && anotherToolControl.active && toggleControl.active, "activated the other tool control, the first one is inactive and the toggle control still active."); diff --git a/tests/Events.html b/tests/Events.html index e15e8488ff..485c53818f 100644 --- a/tests/Events.html +++ b/tests/Events.html @@ -82,7 +82,7 @@ function test_Events_register_unregister(t) { - t.plan(19); + t.plan(20); var mapDiv = OpenLayers.Util.getElement('map'); var obj = {result: 0}; @@ -165,6 +165,9 @@ } catch (err) { t.fail("unregistering for an event with no registered listeners causes trouble: " + err); } + + events.register("buttonclick", obj, func); + t.ok(events.extensions.buttonclick, "buttonclick extension registered"); } diff --git a/tests/Events/buttonclick.html b/tests/Events/buttonclick.html new file mode 100644 index 0000000000..d03205e68f --- /dev/null +++ b/tests/Events/buttonclick.html @@ -0,0 +1,133 @@ + + + + + + +
+
+ +
+
+ + diff --git a/tests/Handler/Drag.html b/tests/Handler/Drag.html index 533e1bb647..4be1df9e6d 100644 --- a/tests/Handler/Drag.html +++ b/tests/Handler/Drag.html @@ -252,7 +252,7 @@ t.ok(evt.xy.x == testEvents.done.xy.x && evt.xy.y == testEvents.done.xy.y, "mouseout calls Util.mouseLeft with the correct event"); - t.eq(element.id, map.eventsDiv.id, + t.eq(element.id, map.viewPortDiv.id, "mouseout calls Util.mouseLeft with the correct element"); return true; } diff --git a/tests/Layer/EventPane.html b/tests/Layer/EventPane.html index f846614a2b..8d8e180d58 100644 --- a/tests/Layer/EventPane.html +++ b/tests/Layer/EventPane.html @@ -94,9 +94,9 @@ if (document.createEvent) { // Mozilla var evObj = document.createEvent('MouseEvents'); evObj.initEvent('mousemove', true, false); - map.eventsDiv.dispatchEvent(evObj); + map.viewPortDiv.dispatchEvent(evObj); } else if(document.createEventObject) { // IE - map.eventsDiv.fireEvent('onmousemove'); + map.viewPortDiv.fireEvent('onmousemove'); } t.eq(log.length, 1, "got one event"); diff --git a/tests/list-tests.html b/tests/list-tests.html index 196a4d2219..1421c2b6dc 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -46,6 +46,7 @@
  • Control/PanPanel.html
  • Control/SLDSelect.html
  • Events.html
  • +
  • Events/buttonclick.html
  • Extras.html
  • Feature.html
  • Feature/Vector.html
  • From e70569b2bb4c573d6b52ca569230db7fca501c18 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 20 Jan 2012 14:17:56 +0100 Subject: [PATCH 2/6] Use event handling of OpenLayers.Event, not the native one. Also includes some of the fixes suggested by @bartvde. --- lib/OpenLayers/Events.js | 99 ++++++++++------------------ lib/OpenLayers/Events/buttonclick.js | 45 +++++-------- tests/Events.html | 4 ++ tests/Events/buttonclick.html | 3 +- 4 files changed, 55 insertions(+), 96 deletions(-) diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index c6ab5592c9..754e13e975 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -157,16 +157,9 @@ OpenLayers.Event = { * allowDefault - {Boolean} If true, we stop the event chain but * still allow the default browser behaviour (text selection, * radio-button clicking, etc). Default is false. - * terminate - {Boolean} If true, no more listeners registered through an - * instance on the same event on the same element - * will receive this event. Extensions that call should set - * this to true. Default is false. */ - stop: function(event, allowDefault, terminate) { + stop: function(event, allowDefault) { - if (terminate) { - event._terminated = true; - } if (!allowDefault) { if (event.preventDefault) { event.preventDefault(); @@ -466,15 +459,21 @@ OpenLayers.Events = OpenLayers.Class({ * automatically instantiated when a listener is registered for an event * provided by an extension. * - * Extesions are created in the namespace using + * Extensions are created in the namespace using * , and named after the event they provide. - * The constructor recieves the target instance as - * argument. Extensions are expected to have an "observe" method, which is - * called to register its sequence events on the target's dom element, - * using . See - * for a reference implementation. + * The constructor receives the target instance as + * argument. Extensions should register their browser events using + * , with {extension: true} as 4th argument. See + * for a reference implementation. */ extensions: null, + + /** + * Property: extensionCount + * {Object} Keys are event types (like in ), values are the + * number of extension listeners for each event type. + */ + extensionCount: null, /** * Method: clearMouseListener @@ -504,6 +503,7 @@ OpenLayers.Events = OpenLayers.Class({ this.fallThrough = fallThrough; this.listeners = {}; this.extensions = {}; + this.extensionCount = {}; // if a dom element is specified, add a listeners list // for browser events on the element and register them @@ -527,9 +527,7 @@ OpenLayers.Events = OpenLayers.Class({ */ destroy: function () { for (var e in this.extensions) { - if (typeof this.extensions[e].destroy === "function") { - this.extensions[e].destroy(); - } + this.extensions[e].destroy(); } this.extensions = null; if (this.element) { @@ -563,17 +561,8 @@ OpenLayers.Events = OpenLayers.Class({ * * Parameters: * element - {HTMLDOMElement} a DOM element to attach browser events to - * options - {Object} Additional options for his method. - * - * Valid options: - * keepElement - {Boolean} If set to true, the instance will not stop - * observing events on an element it was previously attached to. */ - attachToElement: function (element, options) { - options = options || {}; - if(this.element && !options.keepElement) { - OpenLayers.Event.stopObservingElement(this.element); - } + attachToElement: function (element) { this.element = element; for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { // register the event cross-browser @@ -585,33 +574,6 @@ OpenLayers.Events = OpenLayers.Class({ OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); }, - /** - * Method: addExtension - * Adds an extension event to this instance. - * - * Parameters: - * type - {String} the name of the extension event type to add - */ - addExtension: function(type) { - if (this.element.attachEvent && !this.element.addEventListener) { - // old IE - last registered, first triggered. No need to - // re-register the events to get them in a working order - this.extensions[type] = new OpenLayers.Events[type](this); - } else { - // Other browsers - last registered, last triggered. We stop - // observing the element, let the extensions register their browser - // events, and then we attach this instance to the element again. - OpenLayers.Event.stopObservingElement(this.element); - for (var t in this.extensions) { - if (typeof this.extensions[t].observe === "function") { - this.extensions[t].observe(); - } - } - this.extensions[type] = new OpenLayers.Events[type](this); - this.attachToElement(this.element, {keepElement: true}); - } - }, - /** * APIMethod: on * Convenience method for registering listeners with a common scope. @@ -669,16 +631,20 @@ OpenLayers.Events = OpenLayers.Class({ * Parameters: * type - {String} Name of the event to register * obj - {Object} The object to bind the context to for the callback#. - * If no object is specified, default is the Events's - * 'object' property. + * If no object is specified, default is the Events's 'object' property. * func - {Function} The callback function. If no callback is - * specified, this function does nothing. - * priority - {Boolean} If true, adds the new listener to the *front* of - * the events queue instead of to the end. + * specified, this function does nothing. + * priority - {Boolean|Object} If true, adds the new listener to the + * *front* of the events queue instead of to the end. + * + * Valid options for priority: + * extension - {Boolean} If true, then the event will be registered as + * extension event. Extension events are handled before all other + * events. */ register: function (type, obj, func, priority) { if (type in OpenLayers.Events && !this.extensions[type]) { - this.addExtension(type); + this.extensions[type] = new OpenLayers.Events[type](this); } if (func != null) { if (obj == null) { @@ -688,11 +654,16 @@ OpenLayers.Events = OpenLayers.Class({ if (!listeners) { listeners = []; this.listeners[type] = listeners; + this.extensionCount[type] = 0; } + var listener = {obj: obj, func: func}; if (priority) { - listeners.unshift({obj: obj, func: func}); + listeners.splice(this.extensionCount[type], 0, listener); + if (typeof priority === "object" && priority.extension) { + this.extensionCount[type]++; + } } else { - listeners.push({obj: obj, func: func}); + listeners.push(listener); } } }, @@ -852,8 +823,8 @@ OpenLayers.Events = OpenLayers.Class({ */ handleBrowserEvent: function (evt) { var type = evt.type, listeners = this.listeners[type]; - if(!listeners || listeners.length == 0 || evt._terminated) { - // noone's listening or event was terminated through , bail out + if(!listeners || listeners.length == 0) { + // noone's listening, bail out return; } // add clientX & clientY to all events - corresponds to average x, y diff --git a/lib/OpenLayers/Events/buttonclick.js b/lib/OpenLayers/Events/buttonclick.js index 79b0403bdc..6a9a5442e6 100644 --- a/lib/OpenLayers/Events/buttonclick.js +++ b/lib/OpenLayers/Events/buttonclick.js @@ -77,39 +77,20 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({ } OpenLayers.Util.extend(this, options); - this._buttonClick = OpenLayers.Function.bindAsEventListener( - this.buttonClick, this - ); - this.observe(); - }, - - /** - * Method: observe - */ - observe: function() { for (var i=this.events.length-1; i>=0; --i) { - OpenLayers.Event.observe( - this.target.element, this.events[i], this._buttonClick - ); - }; - }, - - /** - * Method: stopObserving - */ - stopObserving: function() { - for (var i=this.events.length-1; i>=0; --i) { - OpenLayers.Event.stopObserving( - this.target.element, this.events[i], this._buttonClick - ); + this.target.register(this.events[i], this, this.buttonClick, { + extension: true + }); } }, - + /** * Method: destroy */ destroy: function() { - this.stopObserving() + for (var i=this.events.length-1; i>=0; --i) { + this.target.unregister(this.events[i], this, this.buttonClick); + } }, /** @@ -120,8 +101,9 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({ * evt - {Event} */ buttonClick: function(evt) { - if (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse")) { - var element = OpenLayers.Event.element(evt); + var propagate = true, + element = OpenLayers.Event.element(evt); + if (element && (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse"))) { if (OpenLayers.Element.hasClass(element, "olAlphaImg")) { element = element.parentNode; } @@ -135,16 +117,19 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({ if (this.cancelRegEx.test(evt.type)) { delete this._buttonStarted; } - OpenLayers.Event.stop(evt, false, true); + OpenLayers.Event.stop(evt, false); + propagate = false; } if (this.startRegEx.test(evt.type)) { this._buttonStarted = true; - OpenLayers.Event.stop(evt, false, true); + OpenLayers.Event.stop(evt, false); + propagate = false; } } else { delete this._buttonStarted; } } + return propagate; } }); \ No newline at end of file diff --git a/tests/Events.html b/tests/Events.html index 485c53818f..cd3b04d42a 100644 --- a/tests/Events.html +++ b/tests/Events.html @@ -30,6 +30,10 @@ var ev = { 'object': {}, + 'extensionCount': { + 'listenerA': 0, + 'listenerB': 0 + }, 'listeners': { 'listenerA': { 'push': function(options){ diff --git a/tests/Events/buttonclick.html b/tests/Events/buttonclick.html index d03205e68f..ab0c0777d5 100644 --- a/tests/Events/buttonclick.html +++ b/tests/Events/buttonclick.html @@ -13,7 +13,6 @@ button: 1, target: button }); - buttonClick._buttonClick(evt); events.handleBrowserEvent(evt); } function logEvent(evt) { @@ -22,7 +21,7 @@ function test_ButtonClick(t) { t.plan(2); - events = new OpenLayers.Events({}, document.getElementById("map")); + events = new OpenLayers.Events({}, element); buttonClick = new OpenLayers.Events.buttonclick({target: events}); t.ok(buttonClick.target === events, "target set from options argument"); buttonClick = new OpenLayers.Events.buttonclick(events); From e09ee34f2351faecb3c6d8ad33a47e97a30996dd Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 20 Jan 2012 14:18:15 +0100 Subject: [PATCH 3/6] Incorporate remaining review comments from @bartvde. --- lib/OpenLayers/Control/OverviewMap.js | 1 - lib/OpenLayers/Control/Panel.js | 2 +- lib/OpenLayers/Events/buttonclick.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/OpenLayers/Control/OverviewMap.js b/lib/OpenLayers/Control/OverviewMap.js index ee21cc4b26..d3e19003d9 100644 --- a/lib/OpenLayers/Control/OverviewMap.js +++ b/lib/OpenLayers/Control/OverviewMap.js @@ -354,7 +354,6 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, { onButtonClick: function(evt) { if (evt.button === this.minimizeDiv) { this.minimizeControl(); - propagate = false; } else if (evt.button === this.maximizeDiv) { this.maximizeControl(); }; diff --git a/lib/OpenLayers/Control/Panel.js b/lib/OpenLayers/Control/Panel.js index 8b77c5272f..11bc90e52d 100644 --- a/lib/OpenLayers/Control/Panel.js +++ b/lib/OpenLayers/Control/Panel.js @@ -170,7 +170,7 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { draw: function() { OpenLayers.Control.prototype.draw.apply(this, arguments); if (this.div.parentNode === this.map.viewPortDiv) { - map.events.register("buttonclick", this, this.onButtonClick); + this.map.events.register("buttonclick", this, this.onButtonClick); } else { this.events.element = this.div; this.events.register("buttonclick", this, this.onButtonClick); diff --git a/lib/OpenLayers/Events/buttonclick.js b/lib/OpenLayers/Events/buttonclick.js index 6a9a5442e6..775174e87a 100644 --- a/lib/OpenLayers/Events/buttonclick.js +++ b/lib/OpenLayers/Events/buttonclick.js @@ -13,7 +13,7 @@ * event type fires "buttonclick" on its when a button was * clicked. Buttons are detected by the "olButton" class. * - * This event type makes sure that button clicks do not interfer with other + * This event type makes sure that button clicks do not interfere with other * events that are registered on the same . */ OpenLayers.Events.buttonclick = OpenLayers.Class({ From 67eda3e2ae56e969e5f1f772e7e253bbb17e128f Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 20 Jan 2012 15:44:20 +0100 Subject: [PATCH 4/6] Re-adding accidently removed "if" block. --- lib/OpenLayers/Events.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index 754e13e975..ebe8a0b833 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -563,6 +563,9 @@ OpenLayers.Events = OpenLayers.Class({ * element - {HTMLDOMElement} a DOM element to attach browser events to */ attachToElement: function (element) { + if (this.element) { + OpenLayers.Event.stopObservingElement(this.element); + } this.element = element; for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { // register the event cross-browser From 1d4b68af7be6237b7557e021fab7a7dea23568f0 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 20 Jan 2012 15:48:01 +0100 Subject: [PATCH 5/6] Fixing docs. --- lib/OpenLayers/Events/buttonclick.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/OpenLayers/Events/buttonclick.js b/lib/OpenLayers/Events/buttonclick.js index 775174e87a..823586cac3 100644 --- a/lib/OpenLayers/Events/buttonclick.js +++ b/lib/OpenLayers/Events/buttonclick.js @@ -28,7 +28,8 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({ /** * Property: events * {Array} Events to observe and conditionally stop from propagating when - * an element with the olButton (or its olAlphaImg child) is clicked. + * an element with the olButton class (or its olAlphaImg child) is + * clicked. */ events: [ 'mousedown', 'mouseup', 'click', 'dblclick', From d9cc0c08ed8a21d23c225c2bae665fc5203c2619 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 20 Jan 2012 16:08:02 +0100 Subject: [PATCH 6/6] Check for outsideViewport - we may not have a parentNode yet. --- lib/OpenLayers/Control/Panel.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/OpenLayers/Control/Panel.js b/lib/OpenLayers/Control/Panel.js index 11bc90e52d..5dc4db15d7 100644 --- a/lib/OpenLayers/Control/Panel.js +++ b/lib/OpenLayers/Control/Panel.js @@ -169,11 +169,11 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { */ draw: function() { OpenLayers.Control.prototype.draw.apply(this, arguments); - if (this.div.parentNode === this.map.viewPortDiv) { - this.map.events.register("buttonclick", this, this.onButtonClick); - } else { + if (this.outsideViewport) { this.events.element = this.div; this.events.register("buttonclick", this, this.onButtonClick); + } else { + this.map.events.register("buttonclick", this, this.onButtonClick); } this.addControlsToMap(this.controls); return this.div;