This works for me. In callbacks I just need the element; not the mouse/touch event and not the context (don't use 'this' in callback).
pointer.ts
/**
* Simulate touchenter and touchleave by tracking touchmove. See https://stackoverflow.com/questions/23111671/touchenter-and-touchleave-events-support
*/
const touchEventSimulator = {
// enterElementCallback stores element as key and callback as value
enterElementCallback: new Map(),
leaveElementCallback: new Map(),
previousElement: null,
init: function() {
window.addEventListener('touchmove', event => {
var currentElement = document.elementFromPoint(event.touches[0].clientX, event.touches[0].clientY)
if (currentElement !== this.previousElement) {
// touch leave
const leaveCallback = this.leaveElementCallback.get(this.previousElement)
if (leaveCallback) {
leaveCallback.call(null, this.previousElement)
}
// touch enter
const enterCallback = this.enterElementCallback.get(currentElement)
if (enterCallback) {
enterCallback.call(null, currentElement)
}
// Current element will be the previous one, next time we check.
this.previousElement = currentElement;
}
});
},
onEnter(element, callback) {
this.enterElementCallback.set(element, callback);
},
onLeave(element, callback) {
this.leaveElementCallback.set(element, callback);
}
}
const mouseAvailable = matchMedia('(pointer:fine)').matches;
/**
* Pointer is a wrapper for mouse and (simulated) touch events
*/
export const pointer = {
mouseAvailable,
init() {
if (!mouseAvailable) {
touchEventSimulator.init()
}
},
onEnter: (element, callback) => {
if (mouseAvailable) {
element.addEventListener('mouseenter', ()=>callback.call(null, element))
} else {
touchEventSimulator.onEnter(element, callback)
}
},
onLeave: (element, callback) => {
if (mouseAvailable) {
element.addEventListener('mouseleave', ()=>callback.call(null, element))
} else {
touchEventSimulator.onLeave(element, callback)
}
}
}
example.ts
import {pointer} from './pointer';
pointer.init();
const element = document.getElementById('test');
pointer.onEnter(anchor, element=>{
console.log('enter', element)
})
pointer.onLeave(anchor, element=>{
console.log('leave', element)
})