Preact: onTouchStart event handler does not work properly on custom elements with display: block

Created on 12 Nov 2019  路  3Comments  路  Source: preactjs/preact

After upgrading to Preact X onTouchStart event handler stopped working on custom elements with display: block.
Here is code sample:
<custom style={{display: 'block'}} onTouchStart={() => {console.warn('onTouchStart!');}}>Hello, World!</custom>

In devtools Event Listeners I noticed strange event name TouchStart (with capital T and S)
image

If i change event name to ontouchstart it all works fine.
example:
<custom style={{display: 'block'}} ontouchstart={() => {console.warn('onTouchStart!');}}>Hello, World!</custom>

What is strange is that such behavior only occurs in Chrome on my desktop pc. On actual touch devices handler works as intended.

So here is the question. Is it expected behavior?
And if it is, should I change event name for all my components?

bug

Most helpful comment

I did some investigations in a codesandbox. It is clear that the issue of adding a handler for TouchStart instead of touchstart comes from 'ontouchstart' in <any dom element> resulting in false on chrome desktop (without touch input device).

Repro: Open https://codesandbox.io/s/touchstart-ycofm in chrome, it will say that ontouchstart is not in document.body

Once you go into mobile (touch) emulation mode using the devtools the event handler for touchstart will start to fire, the event handler for TouchStart or handlers added using <dom element>.ontouchstart = () => {} won't.

Repro: Open https://codesandbox.io/s/touchstart-ycofm in chrome (with devtools closed), open devtools/start mobile (touch) emulation mode and click on the viewport. You'll see the event handle for touchstart will fire.

When you load a page with the devtools/mobile (touch) emulation open beforehand, the check for 'ontouchstart' in document.body will suddenly become true. Also the handlers for touchstart and document.body.ontouchstart = () => {} will trigger (the TouchStart still does not)

Repro: Open devtools, start mobile (touch) emulation and then open https://codesandbox.io/s/touchstart-ycofm

That means that the issue is related to switching from non-touch-input to touch-input after some content was rendered. For sure adding TouchStart instead of touchstart makes no sense anyways.

A quick fix I can think of is to always use lowercase event handlers for touch(start|end|cancel|move) but that will definitely add some bytes and perf overhead to core. Maybe we can come up with a smarter solution

All 3 comments

I did some investigations in a codesandbox. It is clear that the issue of adding a handler for TouchStart instead of touchstart comes from 'ontouchstart' in <any dom element> resulting in false on chrome desktop (without touch input device).

Repro: Open https://codesandbox.io/s/touchstart-ycofm in chrome, it will say that ontouchstart is not in document.body

Once you go into mobile (touch) emulation mode using the devtools the event handler for touchstart will start to fire, the event handler for TouchStart or handlers added using <dom element>.ontouchstart = () => {} won't.

Repro: Open https://codesandbox.io/s/touchstart-ycofm in chrome (with devtools closed), open devtools/start mobile (touch) emulation mode and click on the viewport. You'll see the event handle for touchstart will fire.

When you load a page with the devtools/mobile (touch) emulation open beforehand, the check for 'ontouchstart' in document.body will suddenly become true. Also the handlers for touchstart and document.body.ontouchstart = () => {} will trigger (the TouchStart still does not)

Repro: Open devtools, start mobile (touch) emulation and then open https://codesandbox.io/s/touchstart-ycofm

That means that the issue is related to switching from non-touch-input to touch-input after some content was rendered. For sure adding TouchStart instead of touchstart makes no sense anyways.

A quick fix I can think of is to always use lowercase event handlers for touch(start|end|cancel|move) but that will definitely add some bytes and perf overhead to core. Maybe we can come up with a smarter solution

Opened a PR to fix this at least in compat as we there also fix the animation/transition events in a similar way. We should discuss whether we want to have a similar fix in core as well. I think it will introduce perf overhead though as every event handler needs to be checked against the regex...

This was fixed in #2120 for /compat

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matthewmueller picture matthewmueller  路  3Comments

jasongerbes picture jasongerbes  路  3Comments

rajaraodv picture rajaraodv  路  3Comments

nopantsmonkey picture nopantsmonkey  路  3Comments

paulkatich picture paulkatich  路  3Comments