Added new configuration flag and default behavior that prevents pointer click events which might lead to conflicts in touch applications.

This commit is contained in:
Uwe Oestermeier 2023-02-15 15:11:12 +01:00
parent 7f1a3aae8e
commit 4da99ef04b
2 changed files with 41 additions and 25 deletions

View File

@ -553,7 +553,8 @@ export class InteractionDelegate {
useCapture = true, useCapture = true,
capturePointerEvents = true, capturePointerEvents = true,
cancelOnWindowOut = true, cancelOnWindowOut = true,
debug = false, preventPointerClicks = true,
debug = false
} = {} } = {}
) { ) {
this.debug = debug this.debug = debug
@ -564,6 +565,7 @@ export class InteractionDelegate {
this.useCapture = useCapture this.useCapture = useCapture
this.capturePointerEvents = capturePointerEvents this.capturePointerEvents = capturePointerEvents
this.cancelOnWindowOut = cancelOnWindowOut this.cancelOnWindowOut = cancelOnWindowOut
this.preventPointerClicks = preventPointerClicks
this.setupInteraction() this.setupInteraction()
} }
@ -589,14 +591,14 @@ export class InteractionDelegate {
if (this.debug) console.log('Pointer API' + window.PointerEvent) if (this.debug) console.log('Pointer API' + window.PointerEvent)
element.addEventListener( element.addEventListener(
'pointerdown', 'pointerdown',
(e) => { e => {
if (this.debug) console.log('pointerdown', e.pointerId) if (this.debug) console.log('pointerdown', e.pointerId)
if (this.capture(e)) { if (this.capture(e)) {
if (this.capturePointerEvents) { if (this.capturePointerEvents) {
try { try {
element.setPointerCapture(e.pointerId) element.setPointerCapture(e.pointerId)
} catch (e) { } catch (e) {
console.warn('Cannot setPointerCapture') console.warn('Cannot setPointerCapture', e.setPointerCapture)
} }
} }
this.onStart(e) this.onStart(e)
@ -606,7 +608,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'pointermove', 'pointermove',
(e) => { e => {
if (this.debug) console.log('pointermove', e.pointerId, e.pointerType) if (this.debug) console.log('pointermove', e.pointerId, e.pointerType)
if (e.pointerType == 'touch' || (e.pointerType == 'mouse' && Events.isPointerDown(e))) { if (e.pointerType == 'touch' || (e.pointerType == 'mouse' && Events.isPointerDown(e))) {
@ -619,7 +621,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'pointerup', 'pointerup',
(e) => { e => {
if (this.debug) console.log('pointerup', e.pointerId, e.pointerType) if (this.debug) console.log('pointerup', e.pointerId, e.pointerType)
this.onEnd(e) this.onEnd(e)
if (this.capturePointerEvents) { if (this.capturePointerEvents) {
@ -634,7 +636,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'pointercancel', 'pointercancel',
(e) => { e => {
if (this.debug) console.log('pointercancel', e.pointerId, e.pointerType) if (this.debug) console.log('pointercancel', e.pointerId, e.pointerType)
this.onEnd(e) this.onEnd(e)
if (this.capturePointerEvents) element.releasePointerCapture(e.pointerId) if (this.capturePointerEvents) element.releasePointerCapture(e.pointerId)
@ -645,7 +647,7 @@ export class InteractionDelegate {
if (!this.capturePointerEvents) { if (!this.capturePointerEvents) {
element.addEventListener( element.addEventListener(
'pointerleave', 'pointerleave',
(e) => { e => {
if (this.debug) console.log('pointerleave', e.pointerId, e.pointerType) if (this.debug) console.log('pointerleave', e.pointerId, e.pointerType)
if (e.target == element) this.onEnd(e) if (e.target == element) this.onEnd(e)
}, },
@ -656,7 +658,7 @@ export class InteractionDelegate {
if (!this.capturePointerEvents) { if (!this.capturePointerEvents) {
element.addEventListener( element.addEventListener(
'pointerout', 'pointerout',
(e) => { e => {
if (this.debug) console.log('pointerout', e.pointerId, e.pointerType) if (this.debug) console.log('pointerout', e.pointerId, e.pointerType)
if (e.target == element) this.onEnd(e) if (e.target == element) this.onEnd(e)
}, },
@ -667,7 +669,7 @@ export class InteractionDelegate {
if (this.cancelOnWindowOut) { if (this.cancelOnWindowOut) {
window.addEventListener( window.addEventListener(
'pointerout', 'pointerout',
(e) => { e => {
if (this.debug) console.log('pointerout', e.pointerId, e.pointerType, e.target) if (this.debug) console.log('pointerout', e.pointerId, e.pointerType, e.target)
if (e.target == element) { if (e.target == element) {
this.onEnd(e) this.onEnd(e)
@ -680,7 +682,7 @@ export class InteractionDelegate {
if (this.debug) console.log('Touch API') if (this.debug) console.log('Touch API')
element.addEventListener( element.addEventListener(
'touchstart', 'touchstart',
(e) => { e => {
if (this.debug) console.log('touchstart', this.touchPoints(e)) if (this.debug) console.log('touchstart', this.touchPoints(e))
if (this.capture(e)) { if (this.capture(e)) {
for (let touch of e.changedTouches) { for (let touch of e.changedTouches) {
@ -692,7 +694,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'touchmove', 'touchmove',
(e) => { e => {
if (this.debug) console.log('touchmove', this.touchPoints(e), e) if (this.debug) console.log('touchmove', this.touchPoints(e), e)
for (let touch of e.changedTouches) { for (let touch of e.changedTouches) {
this.onMove(touch) this.onMove(touch)
@ -705,7 +707,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'touchend', 'touchend',
(e) => { e => {
if (this.debug) console.log('touchend', this.touchPoints(e)) if (this.debug) console.log('touchend', this.touchPoints(e))
for (let touch of e.changedTouches) { for (let touch of e.changedTouches) {
this.onEnd(touch) this.onEnd(touch)
@ -715,7 +717,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'touchcancel', 'touchcancel',
(e) => { e => {
if (this.debug) console.log('touchcancel', e.targetTouches.length, e.changedTouches.length) if (this.debug) console.log('touchcancel', e.targetTouches.length, e.changedTouches.length)
for (let touch of e.changedTouches) { for (let touch of e.changedTouches) {
this.onEnd(touch) this.onEnd(touch)
@ -728,7 +730,7 @@ export class InteractionDelegate {
element.addEventListener( element.addEventListener(
'mousedown', 'mousedown',
(e) => { e => {
if (this.debug) console.log('mousedown', e) if (this.debug) console.log('mousedown', e)
if (this.capture(e)) { if (this.capture(e)) {
this.onStart(e) this.onStart(e)
@ -738,7 +740,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'mousemove', 'mousemove',
(e) => { e => {
// Dow we only use move events if the mouse is down? // Dow we only use move events if the mouse is down?
// HOver effects have to be implemented by other means // HOver effects have to be implemented by other means
// && Events.isMouseDown(e)) // && Events.isMouseDown(e))
@ -752,7 +754,7 @@ export class InteractionDelegate {
) )
element.addEventListener( element.addEventListener(
'mouseup', 'mouseup',
(e) => { e => {
if (this.debug) console.log('mouseup', e) if (this.debug) console.log('mouseup', e)
this.onEnd(e) this.onEnd(e)
}, },
@ -762,7 +764,7 @@ export class InteractionDelegate {
if (!this.capturePointerEvents) { if (!this.capturePointerEvents) {
element.addEventListener( element.addEventListener(
'mouseout', 'mouseout',
(e) => { e => {
if (e.target == element) { if (e.target == element) {
this.onEnd(e) this.onEnd(e)
console.warn("Shouldn't happen: mouseout ends interaction") console.warn("Shouldn't happen: mouseout ends interaction")
@ -774,7 +776,7 @@ export class InteractionDelegate {
if (this.cancelOnWindowOut) { if (this.cancelOnWindowOut) {
window.addEventListener( window.addEventListener(
'mouseout', 'mouseout',
(e) => { e => {
if (e.target == element) { if (e.target == element) {
this.onEnd(e) this.onEnd(e)
} }
@ -783,6 +785,20 @@ export class InteractionDelegate {
) )
} }
} }
if (this.preventPointerClicks) {
window.addEventListener(
'click',
e => {
if (e instanceof PointerEvent) {
console.warn('Prevented pointer click')
e.preventDefault()
e.stopImmediatePropagation()
}
},
true
)
}
} }
isDescendant(parent, child) { isDescendant(parent, child) {
@ -968,7 +984,7 @@ export class InteractionMapper extends InteractionDelegate {
useCapture = true, useCapture = true,
capturePointerEvents = true, capturePointerEvents = true,
mouseWheelElement = null, mouseWheelElement = null,
logInteractionsAbove = 12, logInteractionsAbove = 12
} = {} } = {}
) { ) {
super(element, target, { super(element, target, {
@ -976,7 +992,7 @@ export class InteractionMapper extends InteractionDelegate {
useCapture, useCapture,
capturePointerEvents, capturePointerEvents,
longPressTime, longPressTime,
mouseWheelElement, mouseWheelElement
}) })
this.logInteractionsAbove = logInteractionsAbove this.logInteractionsAbove = logInteractionsAbove
} }
@ -1132,7 +1148,7 @@ export class InteractionMapper extends InteractionDelegate {
hammer.get('tap').set(opts) hammer.get('tap').set(opts)
} }
hammer.on(type, (event) => { hammer.on(type, event => {
cb(event) cb(event)
}) })
@ -1146,7 +1162,7 @@ export class InteractionMapper extends InteractionDelegate {
} }
} else { } else {
for (let j = 0; j < elements.length; j++) { for (let j = 0; j < elements.length; j++) {
Hammer.on(elements[j], type, (event) => { Hammer.on(elements[j], type, event => {
cb(event) cb(event)
}) })
} }
@ -1177,7 +1193,7 @@ export class InteractionMapper extends InteractionDelegate {
if (Hammer.__hammers.has(element)) { if (Hammer.__hammers.has(element)) {
const elementHammers = Hammer.__hammers.get(element) const elementHammers = Hammer.__hammers.get(element)
elementHammers.forEach((it) => it.destroy()) elementHammers.forEach(it => it.destroy())
Hammer.__hammers.delete(element) Hammer.__hammers.delete(element)
} }
} }

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "iwmlib", "name": "iwmlib",
"version": "2.0.0-beta.0", "version": "2.0.0-beta.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "iwmlib", "name": "iwmlib",
"version": "2.0.0-beta.0", "version": "2.0.0-beta.1",
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"dependencies": { "dependencies": {
"gsap": "^2.1.3", "gsap": "^2.1.3",