タイトルを換言すると、
ページ表示直後、autocompleteされた値はJavaScriptで取得できない。
何の話をしているのか
たとえば、よくあるログインページ。
メールアドレスとパスワードでログインするフォームだが、
以前ログインしたことがあれば、ブラウザが自動でメールアドレスとパスワードを入力してくれる。これがautocompleteだ。
上の画像は、Google Chromeでログインページを開いた直後に、autocompleteしてくれたときのスクリーンショットだ。
この状態で、input要素にはすでに値が入力されているようにみえるが、実はまだ入力されていない。
何を言っているのかわからねーと思うが、おれも何が起きているのかわからなかった…
<label>メールアドレス<input type="email" name="email"></label>
<label>パスワード<input type="password" name="password"></label>
console.log(document.forms[0].email.value);
// -> 空
ちなみに、ページのどこか(フォーム要素じゃなくてもどこでもいい)をクリックすれば、
(この瞬間に、フォントサイズが変わるなど目に見える変化が起こる)
きちんと値が入力されるらしく、JavaScriptでも取得できるようになる。
何が困るのか
上記の例で言えば、ログインボタンの活性化制御をしている場合だ。
メールアドレスとパスワードの入力値をチェックして問題ない場合のみ、ログインボタンのdisabled属性を除去する機能を実装するなど。
autocompleteされているので、値は入力済み。しかし、JavaScriptでは値が取得できないので未入力、ログインボタンは非活性。
何が起こっているのか
日本語では見つけられなかったが、英語で議論されている記事を見つけた。
https://stackoverflow.com/questions/35049555/chrome-autofill-autocomplete-no-value-for-password
どうも、ページ表示直後は、autocompleteされた値は入力されておらず、ただのサジェスト(入力候補)を表示しているだけのようなのだ。そのときのDOMの状態を開発ツールでみると以下のようになっていた。-internal-input-suggested という文字列が見える。
ユーザーの目には入力されているっぽく見えるけれど、実際には値はまだ入力されてないのだから、JavaScriptで値を取得しようとしても空なのも納得がいく。
そして、ページ内のどこかをクリックするなど、ブラウザに対しユーザが何らかのアクションを起こすと、そこではじめて値がinputに入力されることになる。そのDOM状態が以下。
こうなれば、JavaScriptで値を取得できるようになる。
なぜこのような動作なのか
一見バグのようにも思えるが、ユーザーのアクションがあってはじめてinputに値を入力するというのは、セキュリティ上の理由があるのかもしれない。よう知らんけど。
どうやって克服するのか
状況は分かったが、どうやってこの問題を乗り越えるのか。
値が入力されているように見えるけど、実は入力されてない。でも、ユーザーのアクションひとつでオートフィルされる状態なのだから、この状態でログインボタンを活性化しておきたい。だが、入力されていることを確認できない。
引用した記事では、回答者はautocompleteされたinput要素の背景色をチェックして、値がオートフィルされているか(されつつあるか)を判断すればいいと言っている。
たしかに、それで値が入力されつつあることを判断できなくはないが、私は好ましくない実装だと思う。autocomplete時に背景色を変えているのは今のブラウザの仕様に過ぎず、今後変わるかもしれないものに依存した判定は回避すべきだろう。
じゃあ、どうすべきなのか。
私の結論としては、何もしない、というのでいいと思う。
ユーザーが何かアクションを起こせば、そのときに値が入力され、意図した状態に納まるのだ。それでいいではないか。