3

While moving my application from mouse to touch events I noticed some strange behaviour. Basically, touchmove stops working after DOM changes. Mouse events work fine in the same situation. I tested it with chrome developer tools as well as firefox's. They seem to agree on results. Is it a bug or am I missing something?

I created very simple code example to demonstrate that the problem is not connected to any frameworks or libs I use. I also found seemingly related question which unfortunately contains no solution.

Touch demo:

window.addEventListener("touchmove", onTouchMove, {passive: false})

document.addEventListener('DOMContentLoaded', function(){ 
  var elem = document.getElementById("nice");
  console.log(elem)
  elem.addEventListener("touchstart", onTouchStart)
})

function onTouchMove(event) {
  console.log("touch move")
}

function onTouchStart(event) {
  console.log("touch start")
  var elem = document.getElementById("nice")
  elem.remove()
}
<!DOCTYPE html>
<html>
<body style="width: 100%; height: 100%; background-color: yellow">
  <div style="position: absolute; width: 100px; height: 100px; background-color: red; left: 100px; top: 100px" id="nice"></div>
</body>
</html>

Mouse demo:

window.addEventListener("mousemove", onMouseMove, {passive: false})

document.addEventListener('DOMContentLoaded', function(){ 
  var elem = document.getElementById("nice");
  console.log(elem)
  elem.addEventListener("mousedown", onMouseDown)
})

function onMouseMove(event) {
  console.log("mouse move")
}

function onMouseDown(event) {
  console.log("mouse start")
  var elem = document.getElementById("nice")
  elem.remove()
}
<!DOCTYPE html>
<html>
<body style="width: 100%; height: 100%; background-color: yellow">
  <div style="position: absolute; width: 100px; height: 100px; background-color: red; left: 100px; top: 100px" id="nice"></div>
</body>
</html>

One continuous drag gesture starting from red square should cause 1) 'start' message in the log, 2) disappiaring of that square, which is the DOM change in this case 3) sequence of 'move' messages in the log. It is so in mouse demo, but in touch demo there are no 'move' events after square disappears.

dareka
  • 168
  • 7
  • How do you drag the square? As soon as you click it, it disappears. – Barmar Jun 18 '19 at 16:36
  • I still see the "touch move" messages after I tap on the red square and it disappears. – Barmar Jun 18 '19 at 16:38
  • 1
    It is intended behavior. It should write the message and disappear. That is the DOM change I refer to. Sorry, if I was not clear. – dareka Jun 18 '19 at 16:40
  • 1
    OK, now I see the difference. With touch I have to let go and touch again to start seeing the messages. With mouse I don't have to release the button. – Barmar Jun 18 '19 at 16:43
  • So the event doesn't stop working completely. – Barmar Jun 18 '19 at 16:46
  • Yes. It only stops working during one continuous drag gesture. That is if I want to swap dragging object with something else. Thank you for your input, I will update the question. – dareka Jun 18 '19 at 17:57

1 Answers1

2

This is an intended behaviour if your element is deleted.

According to the docs, if you delete an element, the events will still be targeted at it, and hence won't necessarily bubble up to the window or document anymore.

So there are two solutions if you want to delete the element. You can modify the "remove" method so that it would only hide the element until the touch process ends, or you can attach events to the target itself.

Here is an example, you can see the window touchmove events do not appear, while the element touchmove events appear even after the element's removal.

window.addEventListener("touchmove", onTouchMoveWindow, {passive: false})

document.addEventListener('DOMContentLoaded', function(){ 
  var elem = document.getElementById("nice");
  console.log(elem)
  elem.addEventListener("touchstart", onTouchStart)
  elem.addEventListener("touchmove", onTouchMoveElement)
})

function onTouchMoveWindow(event) {
  console.log("touch move window")
}

function onTouchMoveElement(event) {
  console.log("touch move element")
}

function onTouchStart(event) {
  console.log("touch start")
  var elem = document.getElementById("nice")
  elem.remove()
}
<!DOCTYPE html>
<html>
<body style="width: 100%; height: 100%; background-color: yellow">
  <div style="position: absolute; width: 100px; height: 100px; background-color: red; left: 100px; top: 100px" id="nice"></div>
</body>
</html>

Related questions:

  • i recently ran into -- what im assuming is -- a bug in my own script whereby i added a `touchmove` event with the `passive: false` option to `body` in order to `preventDefault` and then removed it. once i removed it, it prevented CSS classes with `active`. i spent hours trying to fix it and what worked was adding a new, ***"empty"*** or ***"blank"*** function to the `touchmove` event immediately after removing the first function. super bizarre. id really love to understand why this is happening – oldboy Dec 30 '20 at 10:10
  • @oldboy can you please elaborate more on this – سعيد Mar 25 '22 at 11:02