skip to Main Content

I want to implement a drag effect on an element, so I used setPointerCapture in its pointerdown event handler like this:

ele.addEventListener('pointerdown', (e)=>{
  e.currentTarget.onpointermove = dosomething()
  e.currentTarget.setPointerCapture(e.pointerId)
})
ele.addEventListener('pointerup', (e)=>{
  e.currentTarget.onpointermove = null
  e.currentTarget.releasePointerCapture(e.pointerId)
})

However, I run into problems when I’m dealing with events on its child elements:

let parent1 = document.querySelector('#parent1') 
let child1 = document.querySelector('#child1')
document.querySelectorAll('.log').forEach(ele => {
  ele.addEventListener('pointerdown', e => console.log(ele.id + " pointerdown"))
  ele.addEventListener('pointerup', e => console.log(ele.id + " pointerup"))
  ele.addEventListener('click', e => console.log(ele.id + " click"))
})
parent1.addEventListener('pointerdown', (e) => {
  e.currentTarget.setPointerCapture(e.pointerId)
})
parent1.addEventListener('pointerup', (e) => {
  e.currentTarget.releasePointerCapture(e.pointerId)
})
<div id='parent1' class='log'><div id='child1' class='log'>click me</div></div>

When I click at the child element, I get the following console logs:

child1 pointerdown
parent1 pointerdown
parent1 pointerup
parent1 click

Where child1 pointerup and child1 click is missing, compared to the following example

document.querySelectorAll('.log').forEach(ele => {
  ele.addEventListener('pointerdown', e => console.log(ele.id + " pointerdown"))
  ele.addEventListener('pointerup', e => console.log(ele.id + " pointerup"))
  ele.addEventListener('click', e => console.log(ele.id + " click"))
})
<div id='parent2' class='log'><div id='child2' class='log'>click me</div></div>

Is this behavior expected? If so, is it possible to capture the mouseup/click event on the child element?

2

Answers


  1. Chosen as BEST ANSWER

    Inspired by @Yogi's comments, I found a way to make it:

    let parent1 = document.querySelector('#parent1') 
    let child1 = document.querySelector('#child1')
    document.querySelectorAll('.log').forEach(ele => {
      ele.addEventListener('pointerdown', e => console.log(ele.id + " pointerdown"))
      ele.addEventListener('pointerup', e => console.log(ele.id + " pointerup"))
      ele.addEventListener('click', e => console.log(ele.id + " click"))
    })
    function dragHandler(e){
      // handling drag move event
      console.log('move')
    }
    parent1.addEventListener('pointerdown', (e) => {
      e.target.setPointerCapture(e.pointerId)
      e.target.addEventListener('mousemove', dragHandler)
      e.target.onlostpointercapture = (e) => {
        e.currentTarget.removeEventListener('mousemove', dragHandler)
        e.currentTarget.onlostpointercapture = null
      }
    })
    <div id='parent1' class='log'><div id='child1' class='log'>click me</div></div>

    It seems that a pointer capture set on the parent element do prevent mouseup events from being fired on the child element, so I need to set the pointer capture on the child element (target) instead of the parent element (currentTarget).

    The mouseup event of the parent element can be triggered normally through the bubbling.


  2. let parent1 = document.querySelector('#parent1') 
    let child1 = document.querySelector('#child1')
    document.querySelectorAll('.log').forEach(ele => {
      ele.addEventListener('pointerdown', e => console.log(ele.id + " pointerdown"))
      ele.addEventListener('pointerup', e => console.log(ele.id + " pointerup"))
      ele.addEventListener('click', e => console.log(ele.id + " click"))
    })
    parent1.addEventListener('pointerdown', (e) => {
      e.currentTarget.setPointerCapture(e.pointerId)
    })
    parent1.addEventListener('pointerup', (e) => {
      e.currentTarget.releasePointerCapture(e.pointerId)
    })
    <div id='parent1' class='log'><div id='child1' class='log'>click me</div></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search