スポンサーリンク

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構造を調べると,出力はfirefoxIEの両者で,

1回目のアラート:

<tbody>
<tr>
	<td>1行目です。</td>
</tr>
</tbody>



2回目のアラート:

<tbody>
<tr>
	<td>1行目です。</td>
</tr>
</tbody>
<tr><td>2行目です。</td></tr>

となる。つまり,

  • 地のHTMLに<tbody>タグを書かなかった場合であっても,DOMツリー構築時には<tbody>が自動で付加される。 (IE・FF
  • <tbody>を無視して,<table>タグの直下に行を追加しようとすると,行は<tbody>の外にはみ出てしまうため,有効なテーブル構造ではなくなる。 (IE・FF)
  • 動的に追加することによって<tbody>からはみ出た行は,
    • Firefoxでは画面上で表示されたように見える。 (FF)
    • IEでは,表示されない。 (IE)

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行目が表示されているのである。

知っているかどうかでかなり悩む点。