diff --git a/lib/OpenLayers/Control/Navigation.js b/lib/OpenLayers/Control/Navigation.js index 4d449f234f..4301b46369 100644 --- a/lib/OpenLayers/Control/Navigation.js +++ b/lib/OpenLayers/Control/Navigation.js @@ -59,20 +59,35 @@ OpenLayers.Control.Navigation.prototype = return false; }, + wheelChange: function(evt, deltaZ) { + console.log("wheel " + deltaZ); + var newZoom = this.map.getZoom() + deltaZ; + if (!this.map.isValidZoomLevel(newZoom)) return; + + var size = this.map.getSize(); + var deltaX = size.w/2 - evt.xy.x; + var deltaY = size.h/2 - evt.xy.y; + var newRes = map.baseLayer.resolutions[newZoom]; + var zoomPoint = this.map.getLonLatFromPixel(evt.xy); + var newCenter = new OpenLayers.LonLat( + zoomPoint.lon + deltaX * newRes, + zoomPoint.lat - deltaY * newRes ); + console.log(newCenter.toString()); + this.map.setCenter( newCenter, newZoom ); + }, + /** User spun scroll wheel up * */ wheelUp: function(evt) { - this.map.setCenter(this.map.getLonLatFromPixel(evt.xy), - this.map.getZoom() + 1); + this.wheelChange(evt, 1); }, /** User spun scroll wheel down * */ wheelDown: function(evt) { - this.map.setCenter(this.map.getLonLatFromPixel(evt.xy), - this.map.getZoom() - 1); + this.wheelChange(evt, -1); }, /** @final @type String */ diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index 4f7d7dbddd..1ae3b15315 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -72,7 +72,6 @@ OpenLayers.Event = { if (!OpenLayers.Event.observers) return; for (var i = 0; i < OpenLayers.Event.observers.length; i++) { OpenLayers.Event.stopObserving.apply(this, OpenLayers.Event.observers[i]); - OpenLayers.Event.observers[i][0] = null; } OpenLayers.Event.observers = false; }, @@ -98,6 +97,28 @@ OpenLayers.Event = { || element.detachEvent)) name = 'keydown'; + // find entry in this.observers cache array and remove it + var observers = OpenLayers.Event.observers; + var entry = [element, name, observer, useCapture]; + for (var i = 0; i < observers.length; i++) { + var observer = observers[i]; + + //compare all 4 elements of entry with observer + var sameEntry = true; + for (var j = 0; j < entry.length; j++) { + if (entry[j] != observer[j]) { + sameEntry = false; + break; + } + } + + //if we've found it, remove it from the observers array + if (sameEntry) { + observers.splice(i--, 1); + break; + } + } + if (element && element.removeEventListener) { element.removeEventListener(name, observer, useCapture); } else if (element && element.detachEvent) { @@ -114,8 +135,6 @@ if (window.Event) { var Event = OpenLayers.Event; } - - /** * @class */ @@ -143,6 +162,15 @@ OpenLayers.Events.prototype = { /** @type Array: list of support application events */ eventTypes: null, + /** + * @type Function: bound event handler attached to elements + * @private + */ + eventHandler: null, + + /** @type Boolean */ + fallThrough: null, + /** * @constructor * @@ -160,6 +188,10 @@ OpenLayers.Events.prototype = { this.fallThrough = fallThrough; this.listeners = new Object(); + // keep a bound copy of handleBrowserEvent() so that we can + // pass the same function to both Event.observe() and .stopObserving() + this.eventHandler = this.handleBrowserEvent.bindAsEventListener(this); + // if eventTypes is specified, create a listeners list for each // custom application event. if (this.eventTypes != null) @@ -172,6 +204,22 @@ OpenLayers.Events.prototype = { this.attachToElement(element); }, + /** + * + */ + destroy: function () { + if (this.element) { + this.detachFromElement(); + } + this.element = null; + + this.listeners = null; + this.object = null; + this.eventTypes = null; + this.fallThrough = null; + this.eventHandler = null; + }, + /** * @param {HTMLDOMElement} element a DOM element to attach browser events to */ @@ -185,12 +233,27 @@ OpenLayers.Events.prototype = { this.listeners[eventType] = new Array(); // use Prototype to register the event cross-browser - OpenLayers.Event.observe(element, eventType, - this.handleBrowserEvent.bindAsEventListener(this)); + OpenLayers.Event.observe(element, eventType, this.eventHandler); } // disable dragstart in IE so that mousedown/move/up works normally OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); }, + + /** + * @private + */ + detachFromElement: function () { + for (var i = 0; i < this.BROWSER_EVENTS.length; i++) { + var eventType = this.BROWSER_EVENTS[i]; + + OpenLayers.Event.stopObserving( + this.element, eventType, this.eventHandler); + } + + // re-enable dragstart in IE + OpenLayers.Event.stopObserving( + this.element, "dragstart", OpenLayers.Event.stop); + }, /** * @param {String} type Name of the event to register @@ -227,9 +290,18 @@ OpenLayers.Events.prototype = { } } }, - // TODO: get rid of this in 3.0 - // Decide whether listeners should be called in the order they were - // registered or in reverse order. + + /** + * TODO: get rid of this in 3.0 - Decide whether listeners should be + * called in the order they were registered or in reverse order. + * + * @param {String} type Name of the event to register + * @param {Object} obj The object to bind the context to for the callback#. + * If no object is specified, default is the Events's + * 'object' property. + * @param {Function} func The callback function. If no callback is + * specified, this function does nothing. + */ registerPriority: function (type, obj, func) { if (func != null) { diff --git a/tests/test_Events.html b/tests/test_Events.html index 4cc29db864..65c79241d3 100644 --- a/tests/test_Events.html +++ b/tests/test_Events.html @@ -201,11 +201,27 @@ t.eq(a, 5, "if Events has no object set and an event is registered also with no object, triggerEvent() calls it without trying to set the context to null"); } + + function test_05_Event_destroy (t) { + t.plan(2); + var start = OpenLayers.Event.observers.length; + var div = OpenLayers.Util.getElement('test'); + var obj = {}; + var events = new OpenLayers.Events(obj, div); + // +1 because of blocking dragstart in attachToElement() + t.eq(OpenLayers.Event.observers.length, + start + OpenLayers.Events.prototype.BROWSER_EVENTS.length + 1, + "construction increases the number of event observers"); + events = events.destroy(); + t.eq(OpenLayers.Event.observers.length, start, + "destruction restores the number of event observers"); + } // -->
+