From db8056df454ea2924a21034ce8ef61cbf59220d0 Mon Sep 17 00:00:00 2001 From: jfgirard Date: Mon, 12 Nov 2012 11:10:03 -0500 Subject: [PATCH] store the event listeners using a hash if the context have a leaflet_id. When removing a layer,the slowest part was to remove the event from the map. For each event, the removeEventListener method had to loop the whole list. With thousand of layers, it become very slow to do. With a hash used has an index to find event listeners for a given leaflet id, its no more an issue. --- src/core/Events.js | 76 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/src/core/Events.js b/src/core/Events.js index 70cb4789..0a8b15fd 100644 --- a/src/core/Events.js +++ b/src/core/Events.js @@ -26,18 +26,44 @@ L.Mixin.Events = { types = L.Util.splitWords(types); for (i = 0, len = types.length; i < len; i++) { - events[types[i]] = events[types[i]] || []; - events[types[i]].push({ + var evt = { action: fn, context: context || this - }); + }; + if (context && context._leaflet_id) { + var tIndex = types[i] + '_idx', leafletId = context._leaflet_id; + events[tIndex] = events[tIndex] || {}; + if (events[tIndex][leafletId]) { + events[tIndex][leafletId].push(evt); + } else { + events[tIndex][leafletId] = [evt]; + } + } else { + events[types[i]] = events[types[i]] || []; + events[types[i]].push(evt); + } } return this; }, hasEventListeners: function (type) { // (String) -> Boolean - return (key in this) && (type in this[key]) && (this[key][type].length > 0); + if ((key in this)) { + if ((type in this[key]) && this[key][type].length > 0) { + return true; + } else { + var typeIdx = type + '_idx'; + if (typeIdx in this[key]) { + for (var leafletId in this[key][typeIdx]) { + if (this[key][typeIdx].hasOwnProperty(leafletId)) { + //atleast one id + return true; + } + } + } + } + } + return false; }, removeEventListener: function (types, fn, context) { // (String[, Function, Object]) or (Object[, Object]) @@ -50,25 +76,27 @@ L.Mixin.Events = { this.removeEventListener(type, types[type], fn); } } - return this; } - types = L.Util.splitWords(types); - for (i = 0, len = types.length; i < len; i++) { - if (this.hasEventListeners(types[i])) { - listeners = events[types[i]]; + //if the context has a leaflet id, use it to find the listeners + if (context && context._leaflet_id) { + listeners = events[types[i] + '_idx'][context._leaflet_id] || []; + } else { + listeners = events[types[i]]; + } for (j = listeners.length - 1; j >= 0; j--) { if ( - (!fn || listeners[j].action === fn) && - (!context || (listeners[j].context === context)) - ) { + (!fn || listeners[j].action === fn) && (!context || (listeners[j].context === context))) { listeners.splice(j, 1); } } + if (context && context._leaflet_id && listeners.length === 0) { + delete events[types[i] + '_idx'][context._leaflet_id]; + } } } @@ -80,15 +108,31 @@ L.Mixin.Events = { return this; } - var event = L.extend({ + var event = L.Util.extend({ type: type, target: this }, data); - var listeners = this[key][type].slice(); + if (this[key][type]) { + var listeners = this[key][type].slice(); - for (var i = 0, len = listeners.length; i < len; i++) { - listeners[i].action.call(listeners[i].context || this, event); + for (var i = 0, len = listeners.length; i < len; i++) { + listeners[i].action.call(listeners[i].context || this, event); + } + } + //fire event for the indexed listeners as well + var listenersIndex = this[key][type + '_idx'], listenerList; + if (listenersIndex) { + for (var leafletId in listenersIndex) { + if (listenersIndex.hasOwnProperty(leafletId)) { + listenerList = listenersIndex[leafletId]; + if (listenerList) { + for (var j = 0, lenList = listenerList.length; j < lenList; j++) { + listenerList[j].action.call(listenerList[j].context || this, event); + } + } + } + } } return this;