[DOM3Events] Identifying mouse events derived from touch events

Hi,
Web developers have long struggled to reliably identify which mouse events
are actually derived from touch events.  Sites need to know this to avoid
double handling (eg. on both a touchend and click event), and have often
just ignored all mouse events on a browser that supports touch events -
seriously breaking functionality on devices with both a mouse and
touchscreen.

We (blink team) have tried for over a year to address this problem through
evangelism (eg. encouraging
<http://www.html5rocks.com/en/mobile/touchandmouse/> calling
<https://www.youtube.com/watch?v=DujfpXOKUp8> preventDefault on handled
touch events to suppress the generated mouse events).  The situation has
improved, but it's still a major problem (eg. it's the reason we haven't
yet been able to rationalize Chrome's support for TouchEvents
<https://code.google.com/p/chromium/issues/detail?id=392584> across
devices, and the reason the IE team says
<http://lists.w3.org/Archives/Public/public-touchevents/2014Jul/0025.html> they
implement touch events only on phones, not laptops).

I recognize now that avoiding
<https://code.google.com/p/chromium/issues/detail?id=115475#c13> adding a
new simple API for this was a *big mistake*.  There are legitimate reasons
why the available workarounds are inadequate. For example, you may want to
suppress/ignore mouse events without disabling browser behavior like
focusing, activating links, etc.  Or some listeners may want to ignore
certain mouse events whose handling is redundant with that for touch events
without affecting other listeners (perhaps in other components written by
other developers).

After considering a number of more general alternatives
<https://docs.google.com/a/chromium.org/document/d/1-ZUtS3knhJP4RbWC74fUZbNp6cbytG6Wen7hewdCtdo/edit#>,
I'd like to propose a very simple and targeted *addition to MouseEvent:* *a
boolean 'derivedFromTouchEvent' property*.  Note that this intentionally
says the event represents input that was already reported via some other
event, NOT that the event represents input from a touchscreen device (eg.
browsers on Android send touch events for mouse and stylus, not just touch
input).  With this we could encourage sites to trivially transform this
common broken pattern:

if (‘ontouchstart’ in window)
  document.addEventListener(‘touchstart’, doStuff);
else
  document.addEventListener(‘mousedown’, doStuff);


Into this:

document.addEventListener(‘touchstart’, doStuff);
document.addEventListener(‘mousedown’, function(e) {
if (!e.derivedFromTouchEvent) doStuff(e);
});


This new API can be trivially polyfilled on browsers (like Safari) which
never support mouse and touch input at the same time with just:

if (!('derivedFromTouchEvent' in MouseEvent.prototype))

    MouseEvent.prototype.derivedFromTouchEvent = ‘ontouchstart’ in window;


See this document
<https://docs.google.com/a/chromium.org/document/d/1-ZUtS3knhJP4RbWC74fUZbNp6cbytG6Wen7hewdCtdo/edit#>
for more details and other alternative proposals.

Thanks,
   Rick

Received on Wednesday, 27 August 2014 14:27:38 UTC