UNPKG

leaflet

Version:

JavaScript library for mobile-friendly interactive maps

92 lines (80 loc) 2.63 kB
import * as DomEvent from './DomEvent'; /* * Extends the event handling code with double tap support for mobile browsers. * * Note: currently most browsers fire native dblclick, with only a few exceptions * (see https://github.com/Leaflet/Leaflet/issues/7012#issuecomment-595087386) */ function makeDblclick(event) { // in modern browsers `type` cannot be just overridden: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only var newEvent = {}, prop, i; for (i in event) { prop = event[i]; newEvent[i] = prop && prop.bind ? prop.bind(event) : prop; } event = newEvent; newEvent.type = 'dblclick'; newEvent.detail = 2; newEvent.isTrusted = false; newEvent._simulated = true; // for debug purposes return newEvent; } var delay = 200; export function addDoubleTapListener(obj, handler) { // Most browsers handle double tap natively obj.addEventListener('dblclick', handler); // On some platforms the browser doesn't fire native dblclicks for touch events. // It seems that in all such cases `detail` property of `click` event is always `1`. // So here we rely on that fact to avoid excessive 'dblclick' simulation when not needed. var last = 0, detail; function simDblclick(e) { if (e.detail !== 1) { detail = e.detail; // keep in sync to avoid false dblclick in some cases return; } if (e.pointerType === 'mouse' || (e.sourceCapabilities && !e.sourceCapabilities.firesTouchEvents)) { return; } // When clicking on an <input>, the browser generates a click on its // <label> (and vice versa) triggering two clicks in quick succession. // This ignores clicks on elements which are a label with a 'for' // attribute (or children of such a label), but not children of // a <input>. var path = DomEvent.getPropagationPath(e); if (path.some(function (el) { return el instanceof HTMLLabelElement && el.attributes.for; }) && !path.some(function (el) { return ( el instanceof HTMLInputElement || el instanceof HTMLSelectElement ); }) ) { return; } var now = Date.now(); if (now - last <= delay) { detail++; if (detail === 2) { handler(makeDblclick(e)); } } else { detail = 1; } last = now; } obj.addEventListener('click', simDblclick); return { dblclick: handler, simDblclick: simDblclick }; } export function removeDoubleTapListener(obj, handlers) { obj.removeEventListener('dblclick', handlers.dblclick); obj.removeEventListener('click', handlers.simDblclick); }