Because this method is called by OpenLayers.Function.bindAsEventListener, which conditionally assigns window.event already, e cannot be null or undefined here.
255 lines
8.6 KiB
JavaScript
255 lines
8.6 KiB
JavaScript
/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
|
|
* full list of contributors). Published under the 2-clause BSD license.
|
|
* See license.txt in the OpenLayers distribution or repository for the
|
|
* full text of the license. */
|
|
|
|
/**
|
|
* @requires OpenLayers/Handler.js
|
|
*/
|
|
|
|
/**
|
|
* Class: OpenLayers.Handler.MouseWheel
|
|
* Handler for wheel up/down events.
|
|
*
|
|
* Inherits from:
|
|
* - <OpenLayers.Handler>
|
|
*/
|
|
OpenLayers.Handler.MouseWheel = OpenLayers.Class(OpenLayers.Handler, {
|
|
/**
|
|
* Property: wheelListener
|
|
* {function}
|
|
*/
|
|
wheelListener: null,
|
|
|
|
/**
|
|
* Property: interval
|
|
* {Integer} In order to increase server performance, an interval (in
|
|
* milliseconds) can be set to reduce the number of up/down events
|
|
* called. If set, a new up/down event will not be set until the
|
|
* interval has passed.
|
|
* Defaults to 0, meaning no interval.
|
|
*/
|
|
interval: 0,
|
|
|
|
/**
|
|
* Property: delta
|
|
* {Integer} When interval is set, delta collects the mousewheel z-deltas
|
|
* of the events that occur within the interval.
|
|
* See also the cumulative option
|
|
*/
|
|
delta: 0,
|
|
|
|
/**
|
|
* Property: cumulative
|
|
* {Boolean} When interval is set: true to collect all the mousewheel
|
|
* z-deltas, false to only record the delta direction (positive or
|
|
* negative)
|
|
*/
|
|
cumulative: true,
|
|
|
|
/**
|
|
* Constructor: OpenLayers.Handler.MouseWheel
|
|
*
|
|
* Parameters:
|
|
* control - {<OpenLayers.Control>}
|
|
* callbacks - {Object} An object containing a single function to be
|
|
* called when the drag operation is finished.
|
|
* The callback should expect to recieve a single
|
|
* argument, the point geometry.
|
|
* options - {Object}
|
|
*/
|
|
initialize: function(control, callbacks, options) {
|
|
OpenLayers.Handler.prototype.initialize.apply(this, arguments);
|
|
this.wheelListener = OpenLayers.Function.bindAsEventListener(
|
|
this.onWheelEvent, this
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Method: destroy
|
|
*/
|
|
destroy: function() {
|
|
OpenLayers.Handler.prototype.destroy.apply(this, arguments);
|
|
this.wheelListener = null;
|
|
},
|
|
|
|
/**
|
|
* Mouse ScrollWheel code thanks to http://adomas.org/javascript-mouse-wheel/
|
|
*/
|
|
|
|
/**
|
|
* Method: onWheelEvent
|
|
* Catch the wheel event and handle it xbrowserly
|
|
*
|
|
* Parameters:
|
|
* e - {Event}
|
|
*/
|
|
onWheelEvent: function(e){
|
|
|
|
// make sure we have a map and check keyboard modifiers
|
|
if (!this.map || !this.checkModifiers(e)) {
|
|
return;
|
|
}
|
|
|
|
// Ride up the element's DOM hierarchy to determine if it or any of
|
|
// its ancestors was:
|
|
// * specifically marked as scrollable (CSS overflow property)
|
|
// * one of our layer divs or a div marked as scrollable
|
|
// ('olScrollable' CSS class)
|
|
// * the map div
|
|
//
|
|
var overScrollableDiv = false;
|
|
var allowScroll = false;
|
|
var overMapDiv = false;
|
|
|
|
var elem = OpenLayers.Event.element(e);
|
|
while((elem != null) && !overMapDiv && !overScrollableDiv) {
|
|
|
|
if (!overScrollableDiv) {
|
|
try {
|
|
var overflow;
|
|
if (elem.currentStyle) {
|
|
overflow = elem.currentStyle["overflow"];
|
|
} else {
|
|
var style =
|
|
document.defaultView.getComputedStyle(elem, null);
|
|
overflow = style.getPropertyValue("overflow");
|
|
}
|
|
overScrollableDiv = ( overflow &&
|
|
(overflow == "auto") || (overflow == "scroll") );
|
|
} catch(err) {
|
|
//sometimes when scrolling in a popup, this causes
|
|
// obscure browser error
|
|
}
|
|
}
|
|
|
|
if (!allowScroll) {
|
|
allowScroll = OpenLayers.Element.hasClass(elem, 'olScrollable');
|
|
if (!allowScroll) {
|
|
for (var i = 0, len = this.map.layers.length; i < len; i++) {
|
|
// Are we in the layer div? Note that we have two cases
|
|
// here: one is to catch EventPane layers, which have a
|
|
// pane above the layer (layer.pane)
|
|
var layer = this.map.layers[i];
|
|
if (elem == layer.div || elem == layer.pane) {
|
|
allowScroll = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
overMapDiv = (elem == this.map.div);
|
|
|
|
elem = elem.parentNode;
|
|
}
|
|
|
|
// Logic below is the following:
|
|
//
|
|
// If we are over a scrollable div or not over the map div:
|
|
// * do nothing (let the browser handle scrolling)
|
|
//
|
|
// otherwise
|
|
//
|
|
// If we are over the layer div or a 'olScrollable' div:
|
|
// * zoom/in out
|
|
// then
|
|
// * kill event (so as not to also scroll the page after zooming)
|
|
//
|
|
// otherwise
|
|
//
|
|
// Kill the event (dont scroll the page if we wheel over the
|
|
// layerswitcher or the pan/zoom control)
|
|
//
|
|
if (!overScrollableDiv && overMapDiv) {
|
|
if (allowScroll) {
|
|
var delta = 0;
|
|
|
|
if (e.wheelDelta) {
|
|
delta = e.wheelDelta;
|
|
if (delta % 160 === 0) {
|
|
// opera have steps of 160 instead of 120
|
|
delta = delta * 0.75;
|
|
}
|
|
delta = delta / 120;
|
|
} else if (e.detail) {
|
|
// detail in Firefox on OS X is 1/3 of Windows
|
|
// so force delta 1 / -1
|
|
delta = - (e.detail / Math.abs(e.detail));
|
|
}
|
|
this.delta = this.delta + delta;
|
|
|
|
if(this.interval) {
|
|
window.clearTimeout(this._timeoutId);
|
|
// store e because window.event might change during delay
|
|
var evt = OpenLayers.Util.extend({}, e);
|
|
this._timeoutId = window.setTimeout(
|
|
OpenLayers.Function.bind(function(){
|
|
this.wheelZoom(evt);
|
|
}, this),
|
|
this.interval
|
|
);
|
|
} else {
|
|
this.wheelZoom(e);
|
|
}
|
|
}
|
|
OpenLayers.Event.stop(e);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Method: wheelZoom
|
|
* Given the wheel event, we carry out the appropriate zooming in or out,
|
|
* based on the 'wheelDelta' or 'detail' property of the event.
|
|
*
|
|
* Parameters:
|
|
* e - {Event}
|
|
*/
|
|
wheelZoom: function(e) {
|
|
var delta = this.delta;
|
|
this.delta = 0;
|
|
|
|
if (delta) {
|
|
e.xy = this.map.events.getMousePosition(e);
|
|
if (delta < 0) {
|
|
this.callback("down", [e, this.cumulative ? delta : -1]);
|
|
} else {
|
|
this.callback("up", [e, this.cumulative ? delta : 1]);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Method: activate
|
|
*/
|
|
activate: function (evt) {
|
|
if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
|
|
//register mousewheel events specifically on the window and document
|
|
var wheelListener = this.wheelListener;
|
|
OpenLayers.Event.observe(window, "DOMMouseScroll", wheelListener);
|
|
OpenLayers.Event.observe(window, "mousewheel", wheelListener);
|
|
OpenLayers.Event.observe(document, "mousewheel", wheelListener);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Method: deactivate
|
|
*/
|
|
deactivate: function (evt) {
|
|
if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
|
|
// unregister mousewheel events specifically on the window and document
|
|
var wheelListener = this.wheelListener;
|
|
OpenLayers.Event.stopObserving(window, "DOMMouseScroll", wheelListener);
|
|
OpenLayers.Event.stopObserving(window, "mousewheel", wheelListener);
|
|
OpenLayers.Event.stopObserving(document, "mousewheel", wheelListener);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
CLASS_NAME: "OpenLayers.Handler.MouseWheel"
|
|
});
|