スポンサーリンク

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=41

HTML ラジオボタンの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;

こうすれば,ラジオボタン/セレクトボックスのいずれの場合も,選択値に応じてリアルタイムに処理を発生させることができる。