Fix box zoom race condition (#5452)

* Fix box zoom race condition

The deferred call to `_resetState` can interrupt the next box zoom if
the user initiates it before the timeout fires. This causes the mouse
move handler to create a second box zoom element, orphaning the first
one and leaving it in the DOM.

* Extract duplicate code into private method
This commit is contained in:
Patrick Paskaris 2017-04-20 09:57:17 -04:00 committed by Iván Sánchez Ortega
parent 1318b999ef
commit 8e96ac476d

View File

@ -25,6 +25,7 @@ export var BoxZoom = Handler.extend({
this._map = map;
this._container = map._container;
this._pane = map._panes.overlayPane;
this._resetStateTimeout = 0;
map.on('unload', this._destroy, this);
},
@ -46,12 +47,23 @@ export var BoxZoom = Handler.extend({
},
_resetState: function () {
this._resetStateTimeout = 0;
this._moved = false;
},
_clearDeferredResetState: function () {
if (this._resetStateTimeout !== 0) {
clearTimeout(this._resetStateTimeout);
this._resetStateTimeout = 0;
}
},
_onMouseDown: function (e) {
if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
// Clear the deferred resetState if it hasn't executed yet, otherwise it
// will interrupt the interaction and orphan a box element in the container.
this._clearDeferredResetState();
this._resetState();
DomUtil.disableTextSelection();
@ -113,7 +125,8 @@ export var BoxZoom = Handler.extend({
if (!this._moved) { return; }
// Postpone to next JS tick so internal click event handling
// still see it as "moved".
setTimeout(Util.bind(this._resetState, this), 0);
this._clearDeferredResetState();
this._resetStateTimeout = setTimeout(Util.bind(this._resetState, this), 0);
var bounds = new LatLngBounds(
this._map.containerPointToLatLng(this._startPoint),