フォームに文字を入力する際、フォームをクリックしたりキーボードのTabキーを押します。
この操作はフォーカスと呼ばれるアクションで、フォームがフォーカスを受け取ることで発生するイベントです。
今回は、フォーカスイベントについて解説していきます。
focusとblur
focusとは、要素がフォーカスを受け取った時に発生するイベントのことです。
blurは、その反対に一度フォーカスを受け取った要素がフォーカスを失った時に発生するイベントです。
どのような場面でフォーカスイベントが発生するのか具体的にイメージしてみましょう。
focusには、多くの場合データを受け入れる準備を行う役割があります。
これには、例えばパスワードやEメールを入力することができる瞬間のことを指します。
blurは、データの受け入れが完了した際の役割です。
パスワードの入力完了後、それをチェックしたりチェック後にサーバーに送信したりするための処理などを行います。
次のコードを見てください。
- focus:入力欄にフォーカスが当てられている間、背景色をピンクにする
- blur:入力欄からフォーカスが外れた時に背景色を白に戻す
<p>Your email:</p>
<form>
  <input type="email" id="email">
</form>
<script>
  let email = document.getElementById('email');
  
  email.addEventListener('focus', (e) => {
    e.target.style.background = 'pink';
  });
  email.addEventListener('blur', (e) => {
    e.target.style.background = "";
  });
</script>
メールアドレスを入力している間は、入力欄の背景色がピンクに変わります。

入力完了後、入力欄の外をクリックすると背景色が白に戻ります。

イベント移譲
focusとblurは、デフォルトではバブリングは起こりません。またデフォルト動作のキャンセルも不可となります。
| イベント | バブリング | キャンセル | 
|---|---|---|
| focus | なし | 不可 | 
| blur | なし | 不可 | 
そのため以下の例は機能しません。
<form id="form">
  <input type="text" value="Name" id="name">
  <input type="email" value="Email" id="email">
</form>
<script>
  let form = document.getElementById('form');
  
  form.addEventListener('focus', (e) => {
    e.target.style.background = 'pink';
  });
  form.addEventListener('blur', (e) => {
    e.target.style.background = "";
  });
</script>

理由は、focusとblurがバブリングしないことから、<form>に当てられたイベントは<form>でのみ起こるためです。
しかし、<input id="name">と<input id="email">それぞれにイベントを割り当てるのは手間です。
それを解決するために二つの方法があります。
一つ目は、キャプチャリングフェーズでイベント伝搬を有効にする方法です。
addEventListener()の第三引数にtrueを記述します。
<form id="form">
  <input type="text" value="Name" id="name">
  <input type="email" value="Email" id="email">
</form>
<script>
  let form = document.getElementById('form');
  
  // 第三引数にtrueを指定する
  form.addEventListener('focus', (e) => {
    e.target.style.background = 'pink';
  }, true);
  // 同じく
  form.addEventListener('blur', (e) => {
    e.target.style.background = "";
  }, true);
</script>

もう一つは、focusinとfocusoutイベントを使う方法です。
focusとblurと同じように使用できますが、focusinとfocusoutはバブリングが発生します。
この場合、onfocusinやonfocusoutは使用できません。addEventListener()で割り当てることが必要です。
<form id="form">
  <input type="text" value="Name" id="name">
  <input type="email" value="Email" id="email">
</form>
<script>
  let form = document.getElementById('form');
  
  // focusinイベント
  form.addEventListener('focusin', (e) => {
    e.target.style.background = 'pink';
  });
  // focusoutイベント
  form.addEventListener('focusout', (e) => {
    e.target.style.background = "";
  });
</script>

tabindex
フォーカスイベントは、<a>, <button>, <input>, <textarea>, <select>などの対話型要素に使うことができます。
一方、<div>, <p>, <table>などの対話型要素でないものは、デフォルトではフォーカスされません。
任意の要素にもフォーカスを当てるには、要素の属性値にtabindexを使用します。
また、Tabキーによる順次ナビゲーションを指定することも可能です。
<style>
  li { cursor: pointer; }
    :focus { font-weight: bold; }
</style>
<ul>
  <li tabindex="1">Tabindex 1</li>
  <li tabindex="0">Tabindex 0</li>
  <li tabindex="2">Tabindex 2</li>
  <li tabindex="3">Tabindex 3</li>
  <li tabindex="-1">Tabindex -1</li>
</ul>
各リストをクリックするとフォーカスが当たり文字が太くなります。
また、最初のリストをクリックした後、Tabキーを押すと、Tabindex 1 → 2 → 3 → 0の順で、フォーカスが移動していきます。




どの要素もtablindexを持っていればフォーカスは有効となりますが、0と負の数は他の値と少し異なります。
tabindex="0"の順次ナビゲーションは有効ですが、順序は常に最後です。
tabindex="-1"のように負の数を指定した場合、フォーカスを持つことはできますが、順次ナビゲーションは到達しません。そのため、Tabキーを押しても無視されます。
まとめ
今回は、フォーカスイベントについて解説しました。
// ポイント
* focus:要素がフォーカスを受け取った時に発生するイベント
* blur:一度フォーカスを受け取った要素がフォーカスを失った時に発生するイベント
* キャプチャリングフェーズを有効にするか、focusin/focusoutイベントを使ってバブリングさせることができる
* tabindexで対話型要素以外にもフォーカスを当てることができる合わせて読みたいイベント詳細シリーズ
第1回:マウスイベント -ボタン操作
第2回:マウスイベント -カーソル移動
第3回:マウスイベント -座標とキー
第4回:キーボードイベント
第5回:フォーカスイベント(当記事)
第6回:データの更新
第7回:フォームの送信
第8回:ページのロードとアンロード
 
       
      
      
      
      
      
      
      
      
      
      
      
      
       
       
       
       
       
       
       
       
     
     


 
       
       
       
       
       
      

 
    
    
    
    
    
    
    
    
    
    
    
    
    
   
 
   
   
   
  
コメント