merge #1141 and clean it up

This commit is contained in:
Vladimir Agafonkin 2013-01-31 17:29:40 +02:00
commit ef02f60387

View File

@ -10,9 +10,10 @@ L.Mixin.Events = {
addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object]) addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object])
var events = this[key] = this[key] || {}, var events = this[key] = this[key] || {},
type, i, len; type, i, len, evt,
contextId, objKey, objLenKey, eventsObj;
// Types can be a map of types/handlers // types can be a map of types/handlers
if (typeof types === 'object') { if (typeof types === 'object') {
for (type in types) { for (type in types) {
if (types.hasOwnProperty(type)) { if (types.hasOwnProperty(type)) {
@ -23,26 +24,50 @@ L.Mixin.Events = {
return this; return this;
} }
// types can be a string of space-separated words
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]] || []; evt = {
events[types[i]].push({
action: fn, action: fn,
context: context || this context: context || this
}); };
contextId = context && context._leaflet_id;
if (contextId) {
// store listeners of a particular context in a separate hash (if it has an id)
// gives a major performance boost when removing thousands of map layers
objKey = types[i] + '_idx',
objLenKey = objKey + '_len',
eventsObj = events[objKey] = events[objKey] || {};
if (eventsObj[contextId]) {
eventsObj[contextId].push(evt);
} else {
eventsObj[contextId] = [evt];
events[objLenKey] = (events[objLenKey] || 0) + 1;
}
} 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); return (key in this) &&
(((type in this[key]) && this[key][type].length > 0) ||
(this[key][type + '_idx_len'] > 0));
}, },
removeEventListener: function (types, fn, context) { // (String[, Function, Object]) or (Object[, Object]) removeEventListener: function (types, fn, context) { // (String[, Function, Object]) or (Object[, Object])
var events = this[key], var events = this[key],
type, i, len, listeners, j; type, i, len, listeners, j,
contextId, objKey, objLenKey;
if (typeof types === 'object') { if (typeof types === 'object') {
for (type in types) { for (type in types) {
@ -50,25 +75,35 @@ 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 an id, use it to find the listeners
contextId = context && context._leaflet_id;
objKey = types[i] + '_idx';
if (contextId && events[objKey]) {
listeners = events[objKey][contextId] || [];
} 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) && (!context || (listeners[j].context === context))) {
(!fn || listeners[j].action === fn) &&
(!context || (listeners[j].context === context))
) {
listeners.splice(j, 1); listeners.splice(j, 1);
} }
} }
if (contextId && listeners.length === 0) {
objLenKey = objKey + '_len';
delete events[objKey][contextId];
events[objLenKey] = (events[objLenKey] || 1) - 1;
}
} }
} }
@ -80,15 +115,36 @@ 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);
var listeners = this[key][type].slice(); var listeners, i, len, eventsObj, contextId;
for (var i = 0, len = listeners.length; i < len; i++) { if (this[key][type]) {
listeners[i].action.call(listeners[i].context || this, event); listeners = this[key][type].slice();
for (i = 0, len = listeners.length; i < len; i++) {
listeners[i].action.call(listeners[i].context || this, event);
}
}
// fire event for the context-indexed listeners as well
eventsObj = this[key][type + '_idx'];
if (eventsObj) {
for (contextId in eventsObj) {
if (eventsObj.hasOwnProperty(contextId)) {
listeners = eventsObj[contextId];
if (listeners) {
for (i = 0, len = listeners.length; i < len; i++) {
listeners[i].action.call(listeners[i].context || this, event);
}
}
}
}
} }
return this; return this;