This content originally appeared on Jake Archibald's blog and was authored by Jake Archibald's blog
I've been working on the web since I was a small child all the way through to the haggard old man I am to day. However, the web still continues to surprise me.
Turns out, mouse events don't fire when the pointer is over disabled form elements, except in Firefox.
Serious?
Serious. Give it a go. Move the mouse from the blue area below into the disabled button:
Misc | Mouse | Touch | Pointer |
---|---|---|---|
It's not like the disabled button element is stopping the event propagating either, it prevents capturing listeners on parent elements too.
The spec says:
A form control that is disabled must prevent any click events that are queued on the user interaction task source from being dispatched on the element.
— The HTML Spec
…but it seems like most browsers are applying this behaviour to all mouse events. I imagine this is an ancient oddity, but given that Firefox doesn't do it, I hope other browsers can drop this weird behaviour. If not, it should be added to the spec (issue).
This kind of thing is especially painful when implementing drag & drop, as you suddenly lose the ability to track the pointer.
Touch events vs pointer events
The weird disabled-element behaviour doesn't happen with touch events. I guess this is because they're a new set of events, so they were able to break away from the legacy of mouse events.
Unfortunately, the weird behaviour is duplicated in pointer events. It's a little sad that this new set of events is taking on legacy behaviour from day one. However, it isn't explicitly part of the spec, so maybe it can change. I've filed an issue to see what can be done about it.
Capturing pointer events
With touch events, all of the touchmove
and touchend
events fire on the same element that received the corresponding touchstart
event. Whereas with mouse/pointer events, events fire on the element under the pointer.
However, pointer events allow you to switch to the touch events model:
element.addEventListener('pointerdown', event => { element.setPointerCapture(event.pointerId); }); element.addEventListener('pointerup', event => { element.releasePointerCapture(event.pointerId); });
Once you do this, events will continue to fire on the captured element, even if you move across a disabled form element.
This works in Edge & Chrome, although Chrome stops firing events when you move across an iframe (issue).
Firefox supports a similar method, setCapture
, which is an old non-standard IE API, but achieves roughly the same thing.
Unfortunately these methods don't fix the problem entirely. You still lose pointerdown
/pointerup
events that start on a disabled form element.
Workaround
input[disabled], button[disabled] { pointer-events: none; }
This means disabled form elements cannot be interacted with, but it also solves the event issue.
Additionally, for drag & drop interactions, you may want to set pointer-events: none
on all iframes during the drag interaction. This means you'll continue to get move events across the whole page.
This content originally appeared on Jake Archibald's blog and was authored by Jake Archibald's blog
Jake Archibald's blog | Sciencx (2017-02-17T12:56:00+00:00) Events and disabled form fields. Retrieved from https://www.scien.cx/2017/02/17/events-and-disabled-form-fields/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.