From 8e96ac476dbcdc614c580dfada247450e718416f Mon Sep 17 00:00:00 2001 From: Patrick Paskaris Date: Thu, 20 Apr 2017 09:57:17 -0400 Subject: [PATCH] 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 --- src/map/handler/Map.BoxZoom.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/map/handler/Map.BoxZoom.js b/src/map/handler/Map.BoxZoom.js index aae1b92b..297a20a6 100644 --- a/src/map/handler/Map.BoxZoom.js +++ b/src/map/handler/Map.BoxZoom.js @@ -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),