Fixing PanZoomBar and Panel issues after #164.

For PanZoomBar, this fixes the slider behavior. Now the buttonclick listener argument also includes a buttonXY property, and PanZoomPanel does not need an Events instance for the zoombarDiv any more.
For Panel, this fixes events for panels outside the map. Just setting the element on the Events instance was no longer enough after e70569b2bb. Events::attachToElement is now used, and it needed to be modified to also work if the Events instance had no element previously.
Finally, I renamed the button property of the buttonclick listener argument to buttonElement, to not confuse it with the browser event button property, and added some more tests and documentation.
This commit is contained in:
ahocevar
2012-01-21 19:11:08 +01:00
parent 469005dead
commit e7107b96cb
11 changed files with 87 additions and 79 deletions

View File

@@ -197,9 +197,9 @@ OpenLayers.Control.LayerSwitcher =
* evt - {Event}
*/
onButtonClick: function(evt) {
if (evt.button === this.minimizeDiv) {
if (evt.buttonElement === this.minimizeDiv) {
this.minimizeControl();
} else if (evt.button === this.maximizeDiv) {
} else if (evt.buttonElement === this.maximizeDiv) {
this.maximizeControl();
};
},

View File

@@ -352,9 +352,9 @@ OpenLayers.Control.OverviewMap = OpenLayers.Class(OpenLayers.Control, {
* evt - {Event}
*/
onButtonClick: function(evt) {
if (evt.button === this.minimizeDiv) {
if (evt.buttonElement === this.minimizeDiv) {
this.minimizeControl();
} else if (evt.button === this.maximizeDiv) {
} else if (evt.buttonElement === this.maximizeDiv) {
this.maximizeControl();
};
},

View File

@@ -176,7 +176,7 @@ OpenLayers.Control.PanZoom = OpenLayers.Class(OpenLayers.Control, {
* evt - {Event}
*/
onButtonClick: function(evt) {
var btn = evt.button;
var btn = evt.buttonElement;
switch (btn.action) {
case "panup":
this.map.pan(0, -this.getSlideFactor("h"));

View File

@@ -239,18 +239,9 @@ OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
imgLocation);
}
div.style.cursor = "pointer";
div.className = "olButton";
this.zoombarDiv = div;
this.divEvents = new OpenLayers.Events(this, div, null, true,
{includeXY: true});
this.divEvents.on({
"touchmove": this.passEventToSlider,
"mousedown": this.divClick,
"mousemove": this.passEventToSlider,
"dblclick": this.doubleClick,
"click": this.doubleClick
});
this.div.appendChild(div);
this.startTop = parseInt(div.style.top);
@@ -277,15 +268,6 @@ OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
});
this.sliderEvents.destroy();
this.divEvents.un({
"touchmove": this.passEventToSlider,
"mousedown": this.divClick,
"mousemove": this.passEventToSlider,
"dblclick": this.doubleClick,
"click": this.doubleClick
});
this.divEvents.destroy();
this.div.removeChild(this.zoombarDiv);
this.zoombarDiv = null;
this.div.removeChild(this.slider);
@@ -295,34 +277,19 @@ OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
},
/**
* Method: passEventToSlider
* This function is used to pass events that happen on the div, or the map,
* through to the slider, which then does its moving thing.
*
* Parameters:
* evt - {<OpenLayers.Event>}
* Method: onButtonClick
*/
passEventToSlider:function(evt) {
this.sliderEvents.handleBrowserEvent(evt);
},
/**
* Method: divClick
* Picks up on clicks directly on the zoombar div
* and sets the zoom level appropriately.
*/
divClick: function (evt) {
if (!OpenLayers.Event.isLeftClick(evt)) {
return;
}
var levels = evt.xy.y / this.zoomStopHeight;
onButtonClick: function(evt) {
OpenLayers.Control.PanZoom.prototype.onButtonClick.apply(this, arguments);
if (evt.buttonElement === this.zoombarDiv) {
var levels = evt.buttonXY.y / this.zoomStopHeight;
if(this.forceFixedZoomLevel || !this.map.fractionalZoom) {
levels = Math.floor(levels);
}
var zoom = (this.map.getNumZoomLevels() - 1) - levels;
zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1);
this.map.zoomTo(zoom);
OpenLayers.Event.stop(evt);
}
},
/*

View File

@@ -170,7 +170,7 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, {
draw: function() {
OpenLayers.Control.prototype.draw.apply(this, arguments);
if (this.outsideViewport) {
this.events.element = this.div;
this.events.attachToElement(this.div);
this.events.register("buttonclick", this, this.onButtonClick);
} else {
this.map.events.register("buttonclick", this, this.onButtonClick);
@@ -322,7 +322,7 @@ OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, {
*/
onButtonClick: function (evt) {
var controls = this.controls,
button = evt.button || OpenLayers.Event.element(evt);
button = evt.buttonElement;
for (var i=controls.length-1; i>=0; --i) {
if (controls[i].panel_div === button) {
this.activateControl(controls[i]);

View File

@@ -551,16 +551,6 @@ OpenLayers.Events = OpenLayers.Class({
// if a dom element is specified, add a listeners list
// for browser events on the element and register them
if (element != null) {
// keep a bound copy of handleBrowserEvent() so that we can
// pass the same function to both Event.observe() and .stopObserving()
this.eventHandler = OpenLayers.Function.bindAsEventListener(
this.handleBrowserEvent, this
);
// to be used with observe and stopObserving
this.clearMouseListener = OpenLayers.Function.bind(
this.clearMouseCache, this
);
this.attachToElement(element);
}
},
@@ -610,6 +600,17 @@ OpenLayers.Events = OpenLayers.Class({
attachToElement: function (element) {
if (this.element) {
OpenLayers.Event.stopObservingElement(this.element);
} else {
// keep a bound copy of handleBrowserEvent() so that we can
// pass the same function to both Event.observe() and .stopObserving()
this.eventHandler = OpenLayers.Function.bindAsEventListener(
this.handleBrowserEvent, this
);
// to be used with observe and stopObserving
this.clearMouseListener = OpenLayers.Function.bind(
this.clearMouseCache, this
);
}
this.element = element;
for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {

View File

@@ -15,6 +15,12 @@
*
* This event type makes sure that button clicks do not interfere with other
* events that are registered on the same <element>.
*
* Event types provided by this extension:
* - *buttonclick* Triggered when a button is clicked. Listeners receive an
* object with a *buttonElement* property referencing the dom element of
* the clicked button, and an *buttonXY* property with the click position
* relative to the button.
*/
OpenLayers.Events.buttonclick = OpenLayers.Class({
@@ -57,6 +63,11 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({
*/
completeRegEx: /^mouseup|touchend$/,
/**
* Property: startEvt
* {Event} The event that started the click sequence
*/
/**
* Constructor: OpenLayers.Events.buttonclick
* Construct a buttonclick event type. Applications are not supposed to
@@ -100,25 +111,30 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({
element = element.parentNode;
}
if (OpenLayers.Element.hasClass(element, "olButton")) {
if (this._buttonStarted) {
if (this.startEvt) {
if (this.completeRegEx.test(evt.type)) {
var pos = OpenLayers.Util.pagePosition(element);
this.target.triggerEvent("buttonclick", {
button: element
buttonElement: element,
buttonXY: {
x: this.startEvt.clientX - pos[0],
y: this.startEvt.clientY - pos[1]
}
});
}
if (this.cancelRegEx.test(evt.type)) {
delete this._buttonStarted;
delete this.startEvt;
}
OpenLayers.Event.stop(evt);
propagate = false;
}
if (this.startRegEx.test(evt.type)) {
this._buttonStarted = true;
this.startEvt = evt;
OpenLayers.Event.stop(evt);
propagate = false;
}
} else {
delete this._buttonStarted;
delete this.startEvt;
}
}
return propagate;

View File

@@ -159,7 +159,6 @@
};
var delta, dir;
var evt = {which: 1}; // a fake left click
var buttons = control.buttons;
map.pan = function(dx, dy){
t.eq([dx,dy],delta,"Panning " + dir + " sets right delta with slideRatio");
@@ -168,25 +167,25 @@
//up
var delta = [0, -50];
var dir = "up";
evt.button = buttons[0];
var evt = {buttonElement: buttons[0]};
control.onButtonClick.call(control, evt);
//left
var delta = [-125, 0];
var dir = "left";
evt.button = buttons[1];
evt.buttonElement = buttons[1];
control.onButtonClick.call(control, evt);
//right
var delta = [125, 0];
var dir = "right";
evt.button = buttons[2];
evt.buttonElement = buttons[2];
control.onButtonClick.call(control, evt);
//down
var delta = [0, 50];
var dir = "down";
evt.button = buttons[3];
evt.buttonElement = buttons[3];
control.onButtonClick.call(control, evt);
map.destroy();

View File

@@ -50,7 +50,7 @@
t.eq(control.zoombarDiv, null, "zoombar div nullified.")
}
function test_Control_PanZoomBar_divClick (t) {
function test_Control_PanZoomBar_onButtonClick (t) {
t.plan(2);
map = new OpenLayers.Map('map', {controls:[]});
var layer = new OpenLayers.Layer.WMS("Test Layer",
@@ -59,16 +59,16 @@
map.addLayer(layer);
control = new OpenLayers.Control.PanZoomBar();
map.addControl(control);
control.divClick({'xy': {'x': 0, 'y': 50}, which: 1});
control.onButtonClick({'buttonXY': {'x': 0, 'y': 50}, buttonElement: control.zoombarDiv});
t.eq(map.zoom, 11, "zoom is correct on standard map");
map.fractionalZoom = true;
control.divClick({'xy': {'x': 0, 'y': 49}, which: 1});
control.onButtonClick({'buttonXY': {'x': 0, 'y': 49}, buttonElement: control.zoombarDiv});
t.eq(map.zoom.toFixed(3), '10.545', "zoom is correct on fractional zoom map");
}
function test_Control_PanZoomBar_forceFixedZoomLevel_divClick(t){
function test_Control_PanZoomBar_forceFixedZoomLevel_onButtonClick(t){
t.plan(1);
map = new OpenLayers.Map('map', {
controls: [],
@@ -84,12 +84,12 @@
});
map.addControl(control);
control.divClick({
'xy': {
control.onButtonClick({
'buttonXY': {
'x': 0,
'y': 49
},
which: 1
buttonElement: control.zoombarDiv
});
t.eq(map.zoom, 11, "forceFixedZoomLevel makes sure that after a div click only fixed zoom levels are used even if the map has fractionalZoom");
}

View File

@@ -322,6 +322,21 @@
map.destroy();
}
function test_buttonclick(t) {
t.plan(4);
var map = new OpenLayers.Map('map');
var panel1 = new OpenLayers.Control.Panel();
var div = document.createElement("div");
var panel2 = new OpenLayers.Control.Panel({div: div});
map.addControls([panel1, panel2]);
t.ok(map.events.listeners.buttonclick, "buttonclick event registered on map's Events instance for panel inside map");
t.ok(!panel1.events.element, "Panel inside map has no element on its Events instance");
t.ok(panel2.events.listeners.buttonclick, "buttonclick event registered on panel's Events instance if outside map")
t.ok(panel2.events.element === div, "Panel outside map has the panel's div as element on its Events instance");
}
</script>
</head>
<body>

View File

@@ -314,6 +314,16 @@
t.eq(evt.clientY, 1.5, "evt.clientY value is correct");
}
function test_Events_attachToElement(t) {
t.plan(3);
var events = new OpenLayers.Events({}, null);
var element = document.createElement("div");
events.attachToElement(element);
t.ok(events.eventHandler, "eventHandler method bound");
t.ok(events.clearMouseListener, "clearMouseListener method bound");
t.ok(events.element === element, "element set");
}
function test_Events_destroy (t) {
t.plan(2);