cleaner DOM event handling in Map

This commit is contained in:
Vladimir Agafonkin 2014-11-18 20:16:33 +02:00
parent 34bc7fa4ea
commit 43c3f01a1a

View File

@ -220,7 +220,7 @@ L.Map = L.Evented.extend({
remove: function () { remove: function () {
this._initEvents('off'); this._initEvents(true);
try { try {
// throws error in IE6-8 // throws error in IE6-8
@ -546,19 +546,18 @@ L.Map = L.Evented.extend({
} }
}, },
// map events // DOM event handling
_initEvents: function (onOff) { _initEvents: function (remove) {
if (!L.DomEvent) { return; } if (!L.DomEvent) { return; }
onOff = onOff || 'on';
L.DomEvent[onOff](this._container,
'click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress',
this._handleMouseEvent, this);
this._targets = {}; this._targets = {};
var onOff = remove ? 'off' : 'on';
L.DomEvent[onOff](this._container, 'click dblclick mousedown mouseup ' +
'mouseover mouseout mousemove contextmenu keypress', this._handleDOMEvent, this);
if (this.options.trackResize) { if (this.options.trackResize) {
L.DomEvent[onOff](window, 'resize', this._onResize, this); L.DomEvent[onOff](window, 'resize', this._onResize, this);
} }
@ -570,66 +569,51 @@ L.Map = L.Evented.extend({
function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container); function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container);
}, },
_handleMouseEvent: function (e) { _handleDOMEvent: function (e) {
if (!this._loaded) { return; } if (!this._loaded || L.DomEvent._skipped(e)) { return; }
var target = this._targets[L.stamp(e.target || e.srcElement)]; // find the layer the event is propagating from
var target = this._targets[L.stamp(e.target || e.srcElement)],
type = e.type === 'keypress' && e.keyCode === 13 ? 'click' : e.type;
var type = // special case for map mouseover/mouseout events so that they're actually mouseenter/mouseleave
e.type === 'mouseenter' ? 'mouseover' : if (!target && (type === 'mouseover' || type === 'mouseout') &&
e.type === 'mouseleave' ? 'mouseout' : e.type; !L.DomEvent._checkMouse(this._container, e)) { return; }
if (e.type === 'keypress' && e.keyCode === 13) { // prevents outline when clicking on keyboard-focusable element
type = 'click';
}
// to prevent outline when clicking on keyboard-focusable element
if (type === 'mousedown') { if (type === 'mousedown') {
L.DomEvent.preventDefault(e); L.DomEvent.preventDefault(e);
} }
// special case for map mouseover/mouseout events so that they're actually mouseenter/mouseleave target = target || this;
if (!target && (e.type === 'mouseover' || e.type === 'mouseout') &&
!L.DomEvent._checkMouse(this._container, e)) { return; }
this._fireMouseEvent(target || this, e, type, true); if (!target.listens(type, true) && (type !== 'click' || !target.listens('preclick', true))) { return; }
},
_fireMouseEvent: function (obj, e, type, propagate, latlng) {
type = type || e.type;
if (L.DomEvent._skipped(e)) { return; }
if (type === 'click') {
var draggableObj = obj.options.draggable === true ? obj : this;
if (!e._simulated && ((draggableObj.dragging && draggableObj.dragging.moved()) ||
(this.boxZoom && this.boxZoom.moved()))) {
L.DomEvent.stopPropagation(e);
return;
}
obj.fire('preclick');
}
if (!obj.listens(type, propagate)) { return; }
if (type === 'contextmenu') { if (type === 'contextmenu') {
L.DomEvent.preventDefault(e); L.DomEvent.preventDefault(e);
} }
if (type === 'click' || type === 'dblclick' || type === 'contextmenu') {
L.DomEvent.stopPropagation(e); // prevents firing click after you just dragged an object
} if (e.type === 'click' && !e._simulated && this._draggableMoved(target)) { return; }
var data = { var data = {
originalEvent: e originalEvent: e
}; };
if (e.type !== 'keypress') { if (e.type !== 'keypress') {
// TODO latlng isn't used, wrong latlng for markers // TODO latlng isn't used, wrong latlng for markers
data.containerPoint = this.mouseEventToContainerPoint(e); data.containerPoint = this.mouseEventToContainerPoint(e);
data.layerPoint = this.containerPointToLayerPoint(data.containerPoint); data.layerPoint = this.containerPointToLayerPoint(data.containerPoint);
data.latlng = latlng || this.layerPointToLatLng(data.layerPoint); data.latlng = this.layerPointToLatLng(data.layerPoint);
} }
if (type === 'click') {
target.fire('preclick', data, true);
}
target.fire(type, data, true);
},
obj.fire(type, data, propagate); _draggableMoved: function (obj) {
obj = obj.options.draggable ? obj : this;
return (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved());
}, },
_clearHandlers: function () { _clearHandlers: function () {