スマホで Web サイトの入力フォームに入力する際にうっかり画面をスクロールしてしまい、どこの入力フォームだったか分からないって経験ありますか。僕はないです。気にしたことがないってのが正しいかもしれません。
でも、気になる人もいるみたいで、その時に対応したことをせっかくなので書いてみます。
コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<div> <input type="text" id="search-word" class="form-control" /> </div> @section Scripts { <script> window.onload = function () { var text = document.getElementById('search-word'); var scrollOff = function (event) { event.preventDefault(); } text.addEventListener('focusin', function (event) { document.addEventListener('touchmove', scrollOff, { passive: false }); }, false); text.addEventListener('focusout', function (event) { document.removeEventListener('touchmove', scrollOff); }, false); }; </script> } |
focusin イベント発火時に addEventListener の引数 options で、passive = false を明示的に指定しています。指定しないと、Chrome のデベロッパーツールのコンソールで ↓ 警告が表示されます。
なぜ??という理由は ↓ に説明してくれています。
touchmove イベント発火時に scrollOff 関数で preventDefault() を呼んでいます。
preventDefault()
Event インターフェースの preventDefault() メソッドは、イベントが明示的に処理されない場合に user agent に、そのデフォルトアクションを通常どおりに行うべきではないと伝えます。このイベントは通常、イベントリスナーの1つが stopPropagation() または stopImmediatePropagation() を呼び出し、いずれかが一度に伝播を終了しない限り、伝播し続けます。
つまり、ここでは touchmove デフォルトアクションを止めて、スクロールしないということです。
せっかくなので addEventListener の引数 useCapture もついでに。
useCapture
デフォルトは false で省略可能です。何を制御しているかというと、イベント伝播です。イベントハンドラがキャプチャフェーズかバブリングフェーズのどちらで処理されるかを制御します。
個人的に一番分かりやすいイベント伝播の説明(図)が下です。
最近だとブラウザバックの関係で history オブジェクト をごにょごにょ試しましたが、DOM API、javascript ってまだまだ知らないことが多くて面白い。