html
html copied to clipboard
Autofocus attribute doesn't work reliably
What I expect: The input is focussed any time it it appears on screen. What happens: The input is focussed on page load, but not after 'Hide input' then 'Show input' are pressed in succession.
Seen on MacOS Chrome Version 71.0.3578.98 (Official Build) (64-bit).
Elm 0.19.
I presume it's due to this:
autofocus is defined to work reliably only on page load. It is not really suited for situations where you are swapping, or opening, or unhiding DOM elements such as in a single-page application framework. You are likely to have to resort to handling the autofocusing yourself.
If that's the case them I think Elm should either manage the autofocus in
situations where you are swapping, or opening, or unhiding DOM elements
..., or it should not provide autofocus
in HTML.Attributes
.
I don't know if it's due to some shadow DOM magic, but I just tried this JS workaround and it doesn't work either, leaving me with no way to get an input to autofocus? 😱
Array.from(document.getElementsByTagName("input")).find(function(i) { return i.autofocus }).focus()
As mentioned here there is a solution using Dom.focus
as shown here.
I'm going to make a PR to update the docs to at least call that out (although I still think it'd be nice if the autofocus
attribute took care of it.
The HTML spec defines the behavior that autofocus
will set the focus only on page load. I think it would be strange if Elm deviated from that behavior.
It wouldn't hurt to be added to the docs I guess, although everything in the Html
module just works how HTML works in general.
Thanks for the link @ChristophP.
I didn't know this:
The
autofocus
content attribute allows the author to indicate that a control is to be focused [...] as soon as thedialog
within which it finds itself is shown
I don't see a dialog
in Html
, but using a dialog
and adding/removing open
certainly seems more appealing than having to use events (namely Dom.focus
).
I tried to implement ⬆️ here using:
node "dialog" [property "open" (bool model.inputVisible)]
[ input [autofocus True] []]
It works insomuch as the dialog
(and input
) appear and disappear, but the autofocus
still doesn't work. Maybe some shadow DOM shenanigans? 😞
I also tried ⬆️ here using attribute
instead:
node "dialog" (if model.inputVisible then [attribute "open" ""] else [])
[ input [autofocus True] []]
Same behavior 😞
I am guessing it could be related to two things.
- Some timing issue: Maybe when the page loads the input isn't quite painted yet, so
autofocus
has no effect, because anyautofocus
that gets drawn after page load doesn't do anything. - Ellie runs your code in an
iframe
. Maybe yourautofocus
isn't the only one on the page, or there are some scripts which "steal" away the focus from your element. Even in a situation with iframes (where there's multiplewindow
s on the page), you can still only have one focused element to my knowledge. Otherwise, how would the browser know where to put the characters when you type.
I would try to debug it by running it on a page that you control, not inside ellie.
I also tried arrow_up here using
attribute
instead:node "dialog" (if model.inputVisible then [attribute "open" ""] else []) [ input [autofocus True] []]
Same behavior disappointed
Can confirm that this doesn't work, even in a plain web app (i.e. no Ellie, <iframe>
etc). :crying_cat_face:
If I run document.querySelector("dialog").show()
in the console, then the input is focused, but if I do document.querySelector("dialog").setAttribute("open", "")
, then the input isn't focused (but the dialog is shown).