All Articles

How to handle touch move event in multiple elements?

Rampage mode for the mouse and touchscreens

I’ve added something called “rampage mode” to recursiveButtons. In this mode, buttons are being clicked as soon as the user hovers a cursor over them. You can see below that for mouse events it requires just one change:

Then I tried to enable it also for touch events - I was thinking that it will be equally easy. But it wasn’t. Solving it took me two days.

First, it turned out that Touch events capture the element on which touch action has started. To visualize it, I’ve created the example below:

  • first, try to click and “drag” over multiple buttons with mouse cursor - you will be painting all the buttons along the way
  • then open devtools (f12), enter “responsive design mode” and try to repeat the same (browser will simulate touch events instead of mouse). You will see that only first button is being colored

Although surprisingly inconsistent for developers, it’s justified for typical mobile usage - when user drags something on small screen (let’s say, a slider input), he doesn’t want to accidentally touch other things on the way - the browser assumes that until user releases his finger, he doesn’t want to touch anything else.

Unfortunately, I am at this unique situation in which I need it to touch other elements. It took me a lot of searching to finally get to some stack overflow page, on which someone suggested such a solution in which I have to read x and y posiotions from the touch event and then use a document.elementFromPoint() function to get the real element under the touch pointer Then I can invoke a “click” event on it and it will trigger a click handler installed in a react component for this element. And it worked:

Prolonging the event for an element that is being unmounted

I had yet one more problem to solve - event target is the element that I touch, not the element that has the handler (in my case handler is attached to the parent of all buttons). If the target is being unmounted during the touch event, the touchMove event stops being fired.

Luckily, I’ve found another workaround for this issue on stack overflow. It suggested to “programatically” add the touchmove and touchend (this one just for cleanup) events to a target when the click starts. I don’t know exactly why, but it’s enough to have this event living loner than a target that it’s initially attached to.

And that’s how I’ve finally made it:

Happy button popping 😊

Sincerely yours,
~Marek

Discuss on twitterEdit on GitHub