JavaScriptの動かないコード (中級編) cloneNodeで選択状態が変わるエラー
以下のJavaScriptコードが意図した動作をしないのは,なぜですか。(制限時間1分)
<input type="button" onClick="f()" value="「cが選択済みでチェック有りの状態」をコピー" > <div id="div0"> <div id="div1"> <!-- セレクトボックス --> <select id="select1"> <option>a</option> <option>b</option> <option selected>c</option> </select> <!-- チェックボックス --> <input type="checkbox" id="check1" checked="checked"> </div> </div> <script language="JavaScript"> function f() { // trueを指定して,子ノードごとコピーする var e_div = div1.cloneNode(true); e_div.id = "div2"; e_div.getElementsByTagName("select")[0].id = "select2"; e_div.getElementsByTagName("input")[0].id = "check2"; // コピーしたノードを追加 div0.appendChild( e_div ); // 「2」と表示 alert( select2.selectedIndex ] ); // 「c」と表示 alert( select2.options[ select2.selectedIndex ].value ); // 「true」と表示 alert( check2.checked ); } </script>
答え
IEでは 「0」,「」(空白),「true」 と表示され,
Firefoxでは 「2」,「c」,「true」 と表示される。
しかも,もし事前に操作を行なって選択状態を変化させた場合,セレクトボックスの挙動は上記の通りのままだが,チェックボックスについては,FFでは直前の選択状態がそのままコピーされる。
挙動をまとめると,下記のようになる。
// FF:事前操作にかかわらず2(デフォルト値) // IE:事前操作にかかわらず0(一番上にリセット) alert( select2.selectedIndex ); // FF:事前操作に依存して直前の状態をコピー // IE:事前操作にかかわらずtrue(デフォルト値) alert( check2.checked );
セレクトボックスについては,コピー前に何を選択していようと,コピー後の状態には影響しない。
一方チェックボックスの方は,FFの場合,コピー前の状態がコピー後に影響する。(このあたり,一貫性が欠けているようにも思える。)
こういったブラウザ間での挙動の違いを吸収するためには,コピー時に選択状態を含めて初期化・指定しておくしかない。
下記URLを参照。
cloneNodeでコピーすると選択状態がデフォルトに戻ってしまう対策 [JavaScript, Tips]
http://programming-magic.com/?id=59
なおIEでは,冒頭のコードでセレクトボックスのvalueを出そうとすると 「」(空白)になる。
こうなる原因は,option 要素の属性で value="〜" の指定を省略しているためだ。
この場合,FFはoption要素の内容をvalueとみなすのに対し,IEはvalue無しとみなす。
しかし,HTML4.01のドキュメントを見ると,本来はFirefoxの挙動が正しいという事が分かる。
HTML 4.01 仕様書邦訳概説
http://www.asahi-net.or.jp/~SD5A-UCD/...
OPTION要素の属性定義
value = cdata [CS]
この属性は、当該コントロールの初期値を指定する。この属性が設定されていない場合、初期値はOPTION要素の内容となる。
対策としては,option要素には明示的にvalue属性をセットするように心がける事になるだろう。