JavaScriptの動かないコード (中級編) テーブルに行追加できない
以下のJavaScriptコードが意図した動作をしないのは,なぜですか。(制限時間1分)
<table border="1" id="my_table"> <tr> <td>1行目です。</td> </tr> </table> <input type="button" onClick="f()" value="行を追加"> <script language="JavaScript"> function f() { //alert( my_table.innerHTML ); // 行要素を作成 var e_tr = document.createElement("tr"); var e_td = document.createElement("td"); var e_text = document.createTextNode("2行目です。"); // テーブルに行を追加 e_td.appendChild( e_text ); e_tr.appendChild( e_td ); my_table.appendChild( e_tr ); //alert( my_table.innerHTML ); } </script>
発生する不具合
これだと,Firefoxでは画面上で行が追加されたように見えるが,IEでは何も起こらない。
しかも,どちらのブラウザでも,テーブルのDOM構造が崩壊する。
上のコードの最初と最後に,2回 alert( my_table.innerHTML ); がある。
これを実行してテーブルの内部のDOM構造を調べると,出力はfirefox・IEの両者で,
1回目のアラート: <tbody> <tr> <td>1行目です。</td> </tr> </tbody> 2回目のアラート: <tbody> <tr> <td>1行目です。</td> </tr> </tbody> <tr><td>2行目です。</td></tr>
となる。つまり,
HTMLとして根本的に間違っている
動的追加の場合の両ブラウザの挙動の違いを取り上げて,よく
「Firefoxではtbodyがなくても appendChild() できる。IEはtbodyが必要なので厳格だ」
などと言われる。
これは画面表示のみに着目した場合のコメントだ。
Firefoxでは,画面上では正常に動いているように見える。
あたかも「tbodyの不足を自動で補ってくれた」かのように感じられる。
しかし,DOM構造の点でいえば,どちらのブラウザでもtbodyがないとおかしくなる,という点を覚えておくべきだろう。
firefoxでも,DOMアクセスを行なう段階になってエラーに気付くかもしれない。
修正案
上記の事態を避けるためには,もともとテーブルに<tbody>を用意しておいて,tbodyに行を追加するように修正すればよい。
また,テーブル全体を動的に作成している場合には,tbodyエレメントの作成を忘れないようにする必要がある。
要は,常にtbodyを省かないような記法を心掛ければ,DOMでの不具合を避けられるだろう。
ただし,上記のようなIEとFFでの画面表示の相違は,テーブルに要素を動的に追加した場合に限る。
tbodyからはみ出た行が存在するようなテーブルを静的に構成した場合,HTMLとしては
<table border="1"> <tbody> <tr> <td>1行目です。</td> </tr> </tbody> <tr> <td>2行目です。</td> </tr> </table>
のようになるが,この場合は両ブラウザでちゃんと2行目が表示されているのである。
知っているかどうかでかなり悩む点。