課題:DOMを直接書き換えると反映されない
DOMでValueを書き換えても、反映されないJSのフレームワークが幾つかある。Angularとか。あのあたりをつかったログインフォームをかんたんに入力したい。
方法1 html のイベントをトリガーして文字列を突っ込む
最近は、domを直接書き換えないでJSでオブジェクトをObserveしていることが多いので、イベントを発火させて文字列を入力する。
inputElement = document.querySelector('input[name=nationalId]') var event = new Event('input', { 'bubbles': true, 'cancelable': true }); inputElement.value = '12345678' inputElement.dispatchEvent(event);
めっちゃ単純ですね。通常通りDOMを書き換えたあとに、dispatchEvent
で new Event('input')
を発行してやるだけです。
これで、擬似的にフォームの入力をprogrammatically に試行できます。
方法2 execCommand
いにしえの手法 focus/ execCommand を使うともっと楽ちん。
document.querySelector('#tel001').focus() document.execCommand('insertText', false, "090123456");
こちらは、focus
したうえで、 execCommand
を発行する。
focus
したうえでイベントを発行するなら、他イベントも行けそうです。ただイベントを調べたりサポート状況が曖昧なので、execCommandという枯れた物を使います。
昔のやつ
https://takuya-1st.hatenablog.jp/entry/2014/11/12/162008
AngularJSのやつ
https://takuya-1st.hatenablog.jp/entry/2021/12/15/015820
Angular/AngularJSの場合は、スコープを取り出せば入力ができますが、フレームワークに特化すると後々が面倒そうなのでイベントを発火するほうが無難だと思う。
追記:パスワード自動入力ソフトの場合。
パスワード入力をするChrome のExtensionではどういう実装になっているのかというと、Bitwardenのソースコードを覗いてみました。
しつこくイベントを発行してました。
var event1 = el.ownerDocument.createEvent('HTMLEvents'), event2 = el.ownerDocument.createEvent('HTMLEvents'); el.dispatchEvent(doEventOnElement(el, 'keydown')); el.dispatchEvent(doEventOnElement(el, 'keypress')); el.dispatchEvent(doEventOnElement(el, 'keyup')); event2.initEvent('input', true, true); el.dispatchEvent(event2); event1.initEvent('change', true, true); el.dispatchEvent(event1);
https://github.com/bitwarden/browser/blob/master/src/content/autofill.js
ちなみに、bitwarden がこれだけイベント発火しても、一部のサイト(TP-Linkのルータログインページなど)では入力がうまくJS側に拾われないんですよねぇ。