diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index fca2c6edf0..3e69d3c090 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -10,7 +10,8 @@ */ OpenLayers.Event = { - /** A hashtable cache of the event observers, keyed by element.id + /** A hashtable cache of the event observers. + * Keyed by element._eventCacheID * * @type Object */ @@ -118,14 +119,25 @@ OpenLayers.Event = { if (!this.observers) { this.observers = new Object(); } - + + //if not already assigned, make a new unique cache ID + if (!element._eventCacheID) { + var idPrefix = "eventCacheID_"; + if (element.id) { + idPrefix = element.id + "_" + idPrefix; + } + element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix); + } + + var cacheID = element._eventCacheID; + //if there is not yet a hash entry for this element, add one - if (!this.observers[element.id]) { - this.observers[element.id] = new Array(); + if (!this.observers[cacheID]) { + this.observers[cacheID] = new Array(); } //add a new observer to this element's list - this.observers[element.id].push({ + this.observers[cacheID].push({ 'element': element, 'name': name, 'observer': observer, @@ -147,23 +159,28 @@ OpenLayers.Event = { * @param {DOMElement || String} elementParam */ stopObservingElement: function(elementParam) { + var element = OpenLayers.Util.getElement(elementParam); + var cacheID = element._eventCacheID; - var elementId = (typeof elementParam == "string") ? elementParam - : OpenLayers.Util.getElement(elementParam).id; + this._removeElementObservers(OpenLayers.Event.observers[cacheID]); + }, - var elementObservers = OpenLayers.Event.observers[elementId]; + /** + * @private + * + * @param {Array(Object)} elementObservers Array of (element, name, + * observer, usecapture) objects, + * taken directly from hashtable + */ + _removeElementObservers: function(elementObservers) { if (elementObservers) { - var i=0; - while(i < elementObservers.length) { - var entry = elementObservers[0]; + for(var i = elementObservers.length-1; i >= 0; i--) { + var entry = elementObservers[i]; var args = new Array(entry.element, entry.name, entry.observer, entry.useCapture); var removed = OpenLayers.Event.stopObserving.apply(this, args); - if (!removed) { - i++; - } } } }, @@ -181,8 +198,7 @@ OpenLayers.Event = { useCapture = useCapture || false; var element = OpenLayers.Util.getElement(elementParam); - var elementId = (typeof elementParam == "string") ? elementParam - : element.id; + var cacheID = element._eventCacheID; if (name == 'keypress') { if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) || @@ -193,7 +209,7 @@ OpenLayers.Event = { // find element's entry in this.observers cache and remove it var foundEntry = false; - var elementObservers = OpenLayers.Event.observers[elementId]; + var elementObservers = OpenLayers.Event.observers[cacheID]; if (elementObservers) { // find the specific event type in the element's list @@ -207,7 +223,7 @@ OpenLayers.Event = { elementObservers.splice(i, 1); if (elementObservers.length == 0) { - delete OpenLayers.Event.observers[element.id]; + delete OpenLayers.Event.observers[cacheID]; } foundEntry = true; break; @@ -230,8 +246,10 @@ OpenLayers.Event = { */ unloadCache: function() { if (OpenLayers.Event.observers) { - for (var elementId in OpenLayers.Event.observers) { - OpenLayers.Event.stopObservingElement.apply(this, [elementId]); + for (var cacheID in OpenLayers.Event.observers) { + var elementObservers = OpenLayers.Event.observers[cacheID]; + OpenLayers.Event._removeElementObservers.apply(this, + [elementObservers]); } OpenLayers.Event.observers = false; } diff --git a/tests/test_Events.html b/tests/test_Events.html index baf0f5ace7..1f84922626 100644 --- a/tests/test_Events.html +++ b/tests/test_Events.html @@ -202,14 +202,15 @@ 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) { + function test_05_Events_destroy (t) { t.plan(2); 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["test"].length, + t.eq(OpenLayers.Event.observers[div._eventCacheID].length, OpenLayers.Events.prototype.BROWSER_EVENTS.length + 1, "construction creates new arrayin hash, registers appropriate events"); @@ -218,6 +219,92 @@ t.eq(OpenLayers.Event.observers["test"], null, "destruction removes the event observer from hash"); } + + function test_06_Event(t) { + t.plan(24); + + var div = OpenLayers.Util.getElement('test'); + var name = "mouseover"; + var func = function() {}; + + //1st elem 1st listener + OpenLayers.Event.observe(div, name, func); + + var cacheID = div._eventCacheID; + t.ok(cacheID, "element given new cache id"); + + var elementObservers = OpenLayers.Event.observers[cacheID]; + + t.ok(elementObservers, "new cache bucket made for event"); + t.eq(elementObservers.length, 1, "one listener registered"); + + var listener = elementObservers[0]; + + t.ok(listener.element == div, "element registered"); + t.eq(listener.name, name, "name registered"); + t.ok(listener.observer == func, "function registered"); + t.eq(listener.useCapture, false, "useCapture defaults to false"); + + //1st elem 2nd listener + name = "mouseout"; + var newFunc = function() {}; + + OpenLayers.Event.observe(div, name, newFunc, true); + var newCacheID = div._eventCacheID; + t.eq(newCacheID, cacheID, "element's cache id not overridden"); + + t.eq(elementObservers.length, 2, "listener added to existing bucket"); + + var listener = elementObservers[1]; + + t.ok(listener.element == div, "element registered"); + t.eq(listener.name, name, "name registered"); + t.ok(listener.observer == newFunc, "function registered"); + t.eq(listener.useCapture, true, "useCapture correctly registered"); + + //2st elem 1st listener + div = OpenLayers.Util.getElement('test2'); + OpenLayers.Event.observe(div, name, func); + + var cacheID = div._eventCacheID; + t.ok(cacheID, "new element given new cache id"); + t.ok(cacheID != newCacheID, "new cache id is unique"); + + elementObservers = OpenLayers.Event.observers[cacheID]; + + t.ok(elementObservers, "new cache bucket made for event"); + t.eq(elementObservers.length, 1, "one listener registered"); + + var listener = elementObservers[0]; + + t.ok(listener.element == div, "element registered"); + t.eq(listener.name, name, "name registered"); + t.ok(listener.observer == func, "function registered"); + t.eq(listener.useCapture, false, "useCapture defaults to false"); + + //stopObservingElement by element + OpenLayers.Event.stopObservingElement(div); + elementObservers = OpenLayers.Event.observers[cacheID]; + t.ok(elementObservers == null, "stopObservingElement by elem works"); + + //stopObservingElement by id + OpenLayers.Event.stopObservingElement("test"); + elementObservers = OpenLayers.Event.observers[newCacheID]; + t.ok(elementObservers == null, "stopObservingElement by id works"); + + + //unloadCache by element + OpenLayers.Event.observe(div, name, func); + + OpenLayers.Event.unloadCache(); + + elementObservers = OpenLayers.Event.observers[cacheID]; + t.ok(elementObservers == null, "stopObservingElement by elem works"); + + + } + + // --> @@ -225,5 +312,6 @@
+