Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handles firing closeOnClick before another listener #10926

Merged
merged 9 commits into from Aug 12, 2021
12 changes: 12 additions & 0 deletions src/ui/events.js
Expand Up @@ -43,6 +43,7 @@ export class MapMouseEvent extends Event {
*/
type: 'mousedown'
| 'mouseup'
| 'preclick'
| 'click'
| 'dblclick'
| 'mousemove'
Expand Down Expand Up @@ -575,6 +576,17 @@ export type MapEvent =
*/
| 'mousemove'

/**
* Triggered when a click event occurs and is fired before the click event.
* Primarily implemented to ensure closeOnClick for pop-ups is fired before any other listeners.
*
* @event preclick
* @memberof Map
* @instance
* @type {MapMouseEvent}
*/
| 'preclick'

/**
* Fired when a pointing device (usually a mouse) is pressed and released at the same point on the map.
*
Expand Down
8 changes: 8 additions & 0 deletions src/ui/handler/map_event.js
@@ -1,5 +1,6 @@
// @flow

import {extend} from '../../util/util.js';
import {MapMouseEvent, MapTouchEvent, MapWheelEvent} from '../events.js';
import type Map from '../map.js';

Expand Down Expand Up @@ -38,8 +39,15 @@ export class MapEventHandler {
this._map.fire(new MapMouseEvent(e.type, this._map, e));
}

preclick(e: MouseEvent) {
const synth = extend({}, e);
synth.type = 'preclick';
this._map.fire(new MapMouseEvent(synth.type, this._map, synth));
}

click(e: MouseEvent, point: Point) {
if (this._mousedownPos && this._mousedownPos.dist(point) >= this._clickTolerance) return;
this.preclick(e);
this._map.fire(new MapMouseEvent(e.type, this._map, e));
}

Expand Down
3 changes: 2 additions & 1 deletion src/ui/map.js
Expand Up @@ -1088,6 +1088,7 @@ class Map extends Camera {
* | [`mousemove`](#map.event:mousemove) | yes |
* | [`mouseenter`](#map.event:mouseenter) | yes (required) |
* | [`mouseleave`](#map.event:mouseleave) | yes (required) |
* | [`preclick`](#map.event:preclick) | |
* | [`click`](#map.event:click) | yes |
* | [`dblclick`](#map.event:dblclick) | yes |
* | [`contextmenu`](#map.event:contextmenu) | yes |
Expand Down Expand Up @@ -1196,7 +1197,7 @@ class Map extends Camera {
* Adds a listener that will be called only once to a specified event type,
* optionally limited to events occurring on features in a specified style layer.
*
* @param {string} type The event type to listen for; one of `'mousedown'`, `'mouseup'`, `'click'`, `'dblclick'`,
* @param {string} type The event type to listen for; one of `'mousedown'`, `'mouseup'`, `'preclick'`, `'click'`, `'dblclick'`,
* `'mousemove'`, `'mouseenter'`, `'mouseleave'`, `'mouseover'`, `'mouseout'`, `'contextmenu'`, `'touchstart'`,
* `'touchend'`, or `'touchcancel'`. `mouseenter` and `mouseover` events are triggered when the cursor enters
* a visible portion of the specified layer from outside that layer or outside the map canvas. `mouseleave`
Expand Down
4 changes: 2 additions & 2 deletions src/ui/popup.js
Expand Up @@ -140,7 +140,7 @@ export default class Popup extends Evented {

this._map = map;
if (this.options.closeOnClick) {
this._map.on('click', this._onClose);
this._map.on('preclick', this._onClose);
}

if (this.options.closeOnMove) {
Expand Down Expand Up @@ -215,7 +215,7 @@ export default class Popup extends Evented {
if (this._map) {
this._map.off('move', this._update);
this._map.off('move', this._onClose);
this._map.off('click', this._onClose);
this._map.off('preclick', this._onClose);
this._map.off('remove', this.remove);
this._map.off('mousemove', this._onMouseMove);
this._map.off('mouseup', this._onMouseUp);
Expand Down
1 change: 1 addition & 0 deletions src/util/evented.js
Expand Up @@ -124,6 +124,7 @@ export class Evented {

// make sure adding or removing listeners inside other listeners won't cause an infinite loop
const listeners = this._listeners && this._listeners[type] ? this._listeners[type].slice() : [];

for (const listener of listeners) {
listener.call(this, event);
}
Expand Down