diff --git a/doc/authors.txt b/doc/authors.txt index 53ac985d11..f5babe54be 100644 --- a/doc/authors.txt +++ b/doc/authors.txt @@ -13,6 +13,7 @@ Tim Schaub Christopher Schmidt Cameron Shorter Paul Spencer +James Stembridge Erik Uzureau Bill Woodall Steve Woodbridge diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index d43911a16f..90426416f4 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -55,23 +55,40 @@ OpenLayers.Event = { return element; }, + /** A hashtable cach of the event observers, keyed by element.id + * + * @type Object + */ observers: false, _observeAndCache: function(element, name, observer, useCapture) { - if (!this.observers) this.observers = []; + if (!this.observers) this.observers = new Object(); + + //if there is not yet a hash entry for this element, add one + if (!this.observers[element.id]) { + this.observers[element.id] = new Array(); + } + //add a new observer to this element's list + this.observers[element.id].push([name, observer, useCapture]); + + //add the actual browser event listener if (element.addEventListener) { - this.observers.push([element, name, observer, useCapture]); element.addEventListener(name, observer, useCapture); } else if (element.attachEvent) { - this.observers.push([element, name, observer, useCapture]); element.attachEvent('on' + name, observer); } }, unloadCache: function() { if (!OpenLayers.Event.observers) return; - for (var i = 0; i < OpenLayers.Event.observers.length; i++) { - OpenLayers.Event.stopObserving.apply(this, OpenLayers.Event.observers[i]); + for (var elementId in OpenLayers.Event.observers) { + var elementObservers = OpenLayers.Event.observers[elementId]; + if (elementObservers) { + for (var i = 0; i < elementObservers.length; i++) { + var args = new Array(elementId).concat(elementObservers[i]); + OpenLayers.Event.stopObserving.apply(this, args); + } + } } OpenLayers.Event.observers = false; }, @@ -90,6 +107,8 @@ OpenLayers.Event = { stopObserving: function(elementParam, name, observer, useCapture) { var element = OpenLayers.Util.getElement(elementParam); + if (!element) return; + useCapture = useCapture || false; if (name == 'keypress' && @@ -97,28 +116,37 @@ 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++) { + // find element's entry in this.observers cache and remove it + var elementObservers = OpenLayers.Event.observers[element.id]; + if (elementObservers) { + var entry = [name, observer, useCapture]; - //compare all 4 elements of entry with observer - var sameEntry = true; - for (var j = 0; j < entry.length; j++) { - if (entry[j] != observers[i][j]) { - sameEntry = false; - break; + // find the specific event type in the element's list + for (var i = 0; i < elementObservers.length; i++) { + var cacheEntry = elementObservers[i]; + + //compare all 3 elements of entry with observer + var sameEntry = true; + for (var j = 0; j < entry.length; j++) { + if (entry[j] != cacheEntry[j]) { + sameEntry = false; + break; + } + } + + //if we've found it, remove it from the observers array + if (sameEntry) { + elementObservers.splice(i--, 1); + if (elementObservers.length == 0) { + OpenLayers.Event.observers[element.id] = null; + } + break; } - } - - //if we've found it, remove it from the observers array - if (sameEntry) { - observers.splice(i--, 1); - break; } } - if (element && element.removeEventListener) { + //actually remove the event listener from browser + if (element.removeEventListener) { element.removeEventListener(name, observer, useCapture); } else if (element && element.detachEvent) { element.detachEvent('on' + name, observer); diff --git a/tests/test_Events.html b/tests/test_Events.html index 2582942090..baf0f5ace7 100644 --- a/tests/test_Events.html +++ b/tests/test_Events.html @@ -204,18 +204,19 @@ 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"); + t.eq(OpenLayers.Event.observers["test"].length, + OpenLayers.Events.prototype.BROWSER_EVENTS.length + 1, + "construction creates new arrayin hash, registers appropriate events"); + events.destroy(); events = null; - t.eq(OpenLayers.Event.observers.length, start, - "destruction restores the number of event observers"); + t.eq(OpenLayers.Event.observers["test"], null, + "destruction removes the event observer from hash"); } // -->