| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /* Copyright (c) 2006-2011 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/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: mousePosition
- * {<OpenLayers.Pixel>} mousePosition is necessary because
- * evt.clientX/Y is buggy in Moz on wheel events, so we cache and use the
- * value from the last mousemove.
- */
- mousePosition: 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
- // * one of our layer divs
- // * the map div
- //
- var overScrollableDiv = false;
- var overLayerDiv = false;
- var overMapDiv = false;
-
- var elem = OpenLayers.Event.element(e);
- while((elem != null) && !overMapDiv && !overScrollableDiv) {
- if (!overScrollableDiv) {
- try {
- if (elem.currentStyle) {
- overflow = elem.currentStyle["overflow"];
- } else {
- var style =
- document.defaultView.getComputedStyle(elem, null);
- var overflow = style.getPropertyValue("overflow");
- }
- overScrollableDiv = ( overflow &&
- (overflow == "auto") || (overflow == "scroll") );
- } catch(err) {
- //sometimes when scrolling in a popup, this causes
- // obscure browser error
- }
- }
- if (!overLayerDiv) {
- 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)
- if (elem == this.map.layers[i].div
- || elem == this.map.layers[i].pane) {
- overLayerDiv = 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:
- // * 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 (overLayerDiv) {
- var delta = 0;
- if (!e) {
- e = window.event;
- }
- if (e.wheelDelta) {
- delta = e.wheelDelta/120;
- if (window.opera && window.opera.version() < 9.2) {
- delta = -delta;
- }
- } else if (e.detail) {
- delta = -e.detail / 3;
- }
- this.delta = this.delta + delta;
- if(this.interval) {
- window.clearTimeout(this._timeoutId);
- this._timeoutId = window.setTimeout(
- OpenLayers.Function.bind(function(){
- this.wheelZoom(e);
- }, 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) {
- // add the mouse position to the event because mozilla has
- // a bug with clientX and clientY (see
- // https://bugzilla.mozilla.org/show_bug.cgi?id=352179)
- // getLonLatFromViewPortPx(e) returns wrong values
- if (this.mousePosition) {
- e.xy = this.mousePosition;
- }
- if (!e.xy) {
- // If the mouse hasn't moved over the map yet, then
- // we don't have a mouse position (in FF), so we just
- // act as if the mouse was at the center of the map.
- // Note that we can tell we are in the map -- and
- // this.map is ensured to be true above.
- e.xy = this.map.getPixelFromLonLat(
- this.map.getCenter()
- );
- }
- if (delta < 0) {
- this.callback("down", [e, this.cumulative ? delta : -1]);
- } else {
- this.callback("up", [e, this.cumulative ? delta : 1]);
- }
- }
- },
-
- /**
- * Method: mousemove
- * Update the stored mousePosition on every move.
- *
- * Parameters:
- * evt - {Event} The browser event
- *
- * Returns:
- * {Boolean} Allow event propagation
- */
- mousemove: function (evt) {
- this.mousePosition = evt.xy;
- },
- /**
- * 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"
- });
|