JavaScriptの動かないコード (中級編) ラジオボタンとプルダウンのonchangeイベントがおかしい
以下のJavaScriptコードが意図した動作をしないのは,なぜですか。(制限時間1分)
やりたい事:
- ラジオボタンのチェック状態によって,表示文言を切り替える。
<input type="radio" name="msg_type" id="radio1">Aと表示<br> <input type="radio" name="msg_type" id="radio2">Bと表示<br> <br> <div id="div_msg1" style="display:none">A</div> <div id="div_msg2" style="display:none">B</div> <script language="JavaScript"> // onchangeイベントを設定する radio1.onchange = f; radio2.onchange = f; // 表示状態を切り替える function f() { if( radio1.checked ) { div_msg1.style.display = ""; div_msg2.style.display = "none"; } else { div_msg1.style.display = "none"; div_msg2.style.display = ""; } } </script>
答え
Firefoxでは,ラジオボタンのチェック状態が変わった瞬間に,すぐに文言が切りかわる。
IEでは,ラジオボタンのチェック状態が変わっただけでは,onchangeイベントが発生しない。
- ラジオボタンをチェックして
- そのラジオボタンからフォーカスを外す
という所まで行って,初めてonchangeイベントが発生する。
だから,IEでは
- 「Aを表示」をクリックしても何も起こらず
- そのまま「Bを表示」をクリックすると,なぜか「A」と表示され
- そのまま「Aを表示」をクリックすると,なぜか「B」と表示される
という,全く直感的ではない動作をする。
IEでは,onchangeは値の変化だけではなく,それに加えて「ラジオボタンからblurするまで」という解釈になる。
なので,onchangeイベントはいわば「遅延」して発火してしまう。
解決策
onchangeではなく,onclickにすればよい。
// onchangeイベントを設定する radio1.onchange = f; radio2.onchange = f; ↓ // onclickイベントを設定する radio1.onclick = f; radio2.onclick = f;
これなら,値が変わった瞬間にイベントが発生する。
また,キーボードでの操作(TABキー+方向キーによる値変更)にも対応できる。
参考:
IEにおけるラジオボタンのonchange
http://yp.xenophy.com/?p=41HTML ラジオボタンのonchangeイベントのブラウザごとの挙動について
http://www.ko-tan.com/article/1221315...ラジオボタンでのonchangeの挙動
http://low-tech.seesaa.net/article/90...
補足:セレクトボックスの場合
以上はradio要素のonchangeの挙動についてだが,select要素の場合はどうなるか。
<select id="hoge"> <option value="1" id="opt1">Aと表示</option> <option value="2" id="opt2">Bと表示</option> </select> <br> <div id="div_msg1" style="display:none">A</div> <div id="div_msg2" style="display:none">B</div> <script language="JavaScript"> // onchangeイベントを設定する hoge.onchange = f; // 表示状態を切り替える function f() { if( hoge.options.selectedIndex == 0 ) { div_msg1.style.display = ""; div_msg2.style.display = "none"; } else { div_msg1.style.display = "none"; div_msg2.style.display = ""; } } </script>
この場合,IEでもFFでも,マウスで選択肢を選んだその瞬間にすぐに文言が切り替わる。
しかし,Firefoxはキーボードでの操作に対して反応が遅くなる。
上下キーでoptionを選択しただけでは文言が切り替わらず,フォーカスを外して初めて文言が切り替わる。
一方,IEはキーボードで上下を押しただけで瞬間的にonchangeが発生する。
radioの場合とプルダウンの場合とで,事情が逆なのだ。
こちらのほうは,Firefoxのキーボード操作については,onclickにしてもだめ。
各option要素にonclickを設定したりしてもだめ。
かわりに,下記のようにkeyupイベントを追加してやればうまくいく。
hoge.onchange = f; ↓ hoge.onchange = f; hoge.onkeyup = f;
こうすれば,ラジオボタン/セレクトボックスのいずれの場合も,選択値に応じてリアルタイムに処理を発生させることができる。