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.
This commit is contained in:
jfgirard 2012-11-12 11:10:03 -05:00
parent c82d023dde
commit db8056df45

View File

@ -26,18 +26,44 @@ L.Mixin.Events = {
types = L.Util.splitWords(types); types = L.Util.splitWords(types);
for (i = 0, len = types.length; i < len; i++) { for (i = 0, len = types.length; i < len; i++) {
events[types[i]] = events[types[i]] || []; var evt = {
events[types[i]].push({
action: fn, action: fn,
context: context || this 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; return this;
}, },
hasEventListeners: function (type) { // (String) -> Boolean 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]) removeEventListener: function (types, fn, context) { // (String[, Function, Object]) or (Object[, Object])
@ -50,25 +76,27 @@ L.Mixin.Events = {
this.removeEventListener(type, types[type], fn); this.removeEventListener(type, types[type], fn);
} }
} }
return this; return this;
} }
types = L.Util.splitWords(types); types = L.Util.splitWords(types);
for (i = 0, len = types.length; i < len; i++) { for (i = 0, len = types.length; i < len; i++) {
if (this.hasEventListeners(types[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--) { for (j = listeners.length - 1; j >= 0; j--) {
if ( if (
(!fn || listeners[j].action === fn) && (!fn || listeners[j].action === fn) && (!context || (listeners[j].context === context))) {
(!context || (listeners[j].context === context))
) {
listeners.splice(j, 1); listeners.splice(j, 1);
} }
} }
if (context && context._leaflet_id && listeners.length === 0) {
delete events[types[i] + '_idx'][context._leaflet_id];
}
} }
} }
@ -80,16 +108,32 @@ L.Mixin.Events = {
return this; return this;
} }
var event = L.extend({ var event = L.Util.extend({
type: type, type: type,
target: this target: this
}, data); }, data);
if (this[key][type]) {
var listeners = this[key][type].slice(); var listeners = this[key][type].slice();
for (var i = 0, len = listeners.length; i < len; i++) { for (var i = 0, len = listeners.length; i < len; i++) {
listeners[i].action.call(listeners[i].context || this, event); 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; return this;
} }