I am having trouble getting event listeners to fire when the actual event occurs. I have created a drag-and-drop system that sets a variable hoveringOverTarget = true
on pointerover
of the target, listens for pointerdown
on an image, and then calls a function on pointerup
to check if it’s been released over the target.
let hoveringOverTarget = false; const target = document.querySelector('.dragtarget'); if(target) { target.addEventListener('pointerover', ()=>{ hoveringOverTarget = true; console.log(hoveringOverTarget); }); target.addEventListener('pointerleave', ()=>{ hoveringOverTarget = false; console.log(hoveringOverTarget); }); } function beginItemDrag(e) { console.log('beginItemDrag called'); const item = e.target; if(target) { item.addEventListener('pointerup', ()=>{ console.log('pointerup'); releaseItem(); }); } else { console.log('No .dragtarget on page'); } } function releaseItem(e) { const item = e.target; if(hoveringOverTarget) { console.log('YES!!!'); readcard(item); } } document.querySelectorAll('.item').forEach(item=>item.addEventListener('pointerdown', beginItemDrag));
However, during dragging of the image, no other event listeners respond. The pointerover
and pointerleave
event listeners from lines 4 and 8 no longer fire when dragging the image in and out of the target zone (despite working fine when not dragging the image), and pointerup
function does not fire on pointerup. Rather, nothing happens at all when I release the item, unless the mouse is then moved, even by one pixel, at which point the pointerover
event finally fires (hoveringOverTarget
is logged as true) and the pointerup
event never fires at all.
Through various searching I have seen some people’s problems solved by adding e.preventDefault()
to event listeners. When I do this, neither event is ever fired at all.
What is going on?
Advertisement
Answer
Since nobody else was able to figure this one out, I’ll post the changes I made that eventually worked. I tried a whirlwind of different things, but I think my eventual success was mostly due to:
- attaching the
pointerup
event listener to the entire document rather than the individual item - identifying the dragged item via a document-wide variable, so all functions can reliably access it (rather than hoping
e.target
was the right item when callingreleaseItem(e)
from a pointerup listener on an individual item) - adding
e.preventDefault()
tobeginItemDrag()
which stops the browser’s default image dragging behavior (different than standard element dragging behavior!!!) which selfishly blocks other event listeners during the course of its drag.
tl:dr; I hoisted variables out of the functions and made my event listeners more broad until finally I caught the right events.
let hoveringOverTarget = false; let draggedItem = null; const target = document.querySelector('.dragtarget'); if(target) { target.addEventListener('pointerover', ()=>{ hoveringOverTarget = true; console.log(hoveringOverTarget); }); target.addEventListener('pointerleave', ()=>{ hoveringOverTarget = false; console.log(hoveringOverTarget); }); } function beginItemDrag(e) { e.preventDefault(); // this is CRUCIAL! Disables default image "draggable" functionality draggedItem = e.target; document.addEventListener('pointerup', releaseItem); if(target) target.style.boxShadow = '0 0 20px white, 0 0 40px white'; } function releaseItem() { if(target) target.style.boxShadow = 'none'; if(hoveringOverTarget) { readcard(draggedItem); } document.removeEventListener('pointerup', releaseItem); } document.querySelectorAll('.toolboxitem').forEach(item=>item.addEventListener('pointerdown', beginItemDrag));