- 1列目に見出し
- 2列目にデータ
- 3列目は結合されたセルで、中にボタン
- ボタンを押すごとに特定の行が「表示」「非表示」と切り替わる
という動的テーブルを作りました。すなわち、特定の行を2行目としたとき、こんなテーブル↓
最初は、さほど難しくないと思って取りかかったものの、IEがらみでつまづき、でも得るものが多かったので書き留めておきます。
ちなみに、不本意ながらIEに優しいページを作るようにしているので、こんな手順でした。
まず、罫線のためのスタイルを
table {
border-collapse:collapse;
}
th,td {
border:1px solid #000;
}
とし、
<table>
<tr>
<th>1行目見出し</th>
<td>1行目データ</td>
<td rowspan="3">
<input type="button" value="2行目を非表示" />
<input type="button" value="2行目を表示" />
</td>
</tr>
<tr>
<th>2行目見出し</th>
<td>2行目データ</td>
</tr>
<tr>
<th>3行目見出し</th>
<td>3行目データ</td>
</tr>
</table>
というのを用意し、(以下、「2行目を非表示」ボタンを「非表示」ボタン、「2行目を表示」ボタンを「表示」ボタンと略す)
あらかじめ「表示ボタン」を非表示とさせておき、
「非表示ボタン」が押されたら、「非表示ボタン」と2行目を非表示にして「表示」ボタンを表示、
「表示ボタン」が押されたら、「非表示ボタン」と2行目を表示させ「表示ボタン」を非表示にする
というつもりで作ったのがこれ↓
サンプルA(IE以外はテーブルが崩れる
css↓
#addAbtn {
display:none;
}
JavaScript↓
function delA() {
document.getElementById('delAbtn').style.display="none";
document.getElementById('addAbtn').style.display="block";
document.getElementById('row2A').style.display="none";
}
function addA() {
document.getElementById('delAbtn').style.display="block";
document.getElementById('addAbtn').style.display="none";
document.getElementById('row2A').style.display="block";
}
html↓
<table>
<tr id="row1A">
<th>1行目見出し</th>
<td>1行目データ</td>
<td rowspan="3">
<input type="button" value="2行目を非表示" onclick="delA()" id="delAbtn" />
<input type="button" value="2行目を表示" onclick="addA()"id="addAbtn" />
</td>
</tr>
<tr id="row2A">
<th>2行目見出し</th>
<td>2行目データ</td>
</tr>
<tr id="row3A">
<th>3行目見出し</th>
<td>3行目データ</td>
</tr>
</table>
IEではうまく行くのに、IE以外ではテーブルが崩れるのはなぜか、調べてみた結果、<tr>を表示させるために「display:block;」としていたことが原因でした。
<tr>のデフォルトは、IEでは「block」、それ以外では「table-row」
ということですが、IEではテーブルに関するdisplayプロパティがことごとく対応していないと理解すべきようです。
詳細は
にある通りですが、この投稿の一番下にdisplayプロパティの値について、引用させてもらいました。
そこで、以前学んだことを利用して、IEのときは「block」それ以外は「table-row」にする、という風に書き換えたのがこれ↓
サンプルB(これでもIE以外はいまひとつ)
css↓
#addBbtn {
display:none;
}
JavaScript↓
function delB() {
document.getElementById('delBbtn').style.display="none";
document.getElementById('addBbtn').style.display="block";
document.getElementById('row2B').style.display="none";
}
function addB() {
document.getElementById('delBbtn').style.display="block";
document.getElementById('addBbtn').style.display="none";
userAgent = window.navigator.userAgent.toLowerCase();
if (userAgent.indexOf("msie") > -1) {
document.getElementById('row2B').style.display="block";
}
else {
document.getElementById('row2B').style.display="table-row";
}
}
html↓
<table>
<tr id="row1B">
<th>1行目見出し</th>
<td>1行目データ</td>
<td rowspan="3">
<input type="button" value="2行目を非表示" onclick="delB()" id="delBbtn" />
<input type="button" value="2行目を表示" onclick="addB()"id="addBbtn" />
</td>
</tr>
<tr id="row2B">
<th>2行目見出し</th>
<td>2行目データ</td>
</tr>
<tr id="row3B">
<th>3行目見出し</th>
<td>3行目データ</td>
</tr>
</table>
これでIEもIE以外もうまくいったかな?と思いましたが、2行目を非表示にしたとき、よく見るとFirefoxで(実はLunascapeでも)ボタンの下の罫線が消えてしまっています。
考えてみた結果、htmlにおける、テーブル1行目の「<td rowspan="3">」が原因かな?うん、たぶんそうです。Firefox、Lunaspcape以外でうまく見えていても、構造的に、2行目を非表示にしたら「<td rowspan="2">」とすべきではないか、と。そこで、html構造を書き換えてくれる「innerHTML」を使用(参考:特定の要素の中身をごっそり書き換える – JavaScript TIPSふぁくとりー)。ついでに、「表示」「非表示」ボタンも1行にまとめられる(あらかじめ「表示ボタン」を非表示にするCSSも不要になる)ぞ!と、こうしてみました↓
サンプルC(今度はIEがダメ)
CSSは無し
JavaScript↓
function delC() {
document.getElementById('row2C').style.display="none";
document.getElementById('row1C').innerHTML=
'<th>1行目見出し</th>'+
'<td>1行目データ</td>'+
'<td rowspan="2">'+
'<input type="button" value="2行目を表示" onclick="addC()" />'+
'</td>'
}
function addC() {
userAgent = window.navigator.userAgent.toLowerCase();
if (userAgent.indexOf("msie") > -1) {
document.getElementById('row2C').style.display="block";
}
else {
document.getElementById('row2C').style.display="table-row";
}
document.getElementById('row1C').innerHTML=
'<th>1行目見出し</th>'+
'<td>1行目データ</td>'+
'<td rowspan="3">'+
'<input type="button" value="2行目を非表示" onclick="delC()" />'+
'</td>'
}
html↓
<table>
<tr id="row1C">
<th>1行目見出し</th>
<td>1行目データ</td>
<td rowspan="3">
<input type="button" value="2行目を非表示" onclick="delC()" />
</td>
</tr>
<tr id="row2C">
<th>2行目見出し</th>
<td>2行目データ</td>
</tr>
<tr id="row3C">
<th>3行目見出し</th>
<td>3行目データ</td>
</tr>
</table>
このようにrowspanの値を変えることによって、Firefox, Lunascapeでも罫線消失を免れ、動作もうまく行くことが確認されましたが、今度はIEに問題が発生しました。
1回目の押下はうまくいくのですが、そこでエラーとなってしまいます。「表示」→「非表示」とならないのです。どうやら、innerHTMLの使用がおかしいらしいです。試しに2行目を消す前にHTMLの書き換えをしたら(jsの記述の順序を変えたら)、1回目の押下でエラー(2行目が非表示にならずに、その前で止まってしまう)となりました。
ということでここがクサイ、と「IEにおけるinnerHTMLの記述ミス? – JavaScript – 教えて!goo」に質問したところ、
IE (少なくとも IE8-) の innerHTML は "table, tFoot, tHead, and tr elements" の書き換えに対応して
おらず、
IEでは、TABLE、TR、TDなんかのinnerHTMLは読み取り専用
だそうです。
ということで、また「表示」「非表示」ボタンをあらかじめ用意し、HTMLの書き換えはIE以外に適用(IEでは書き換えなくてもうまくいっていたし)ということで、以下のように(JavaScript内の記述の順番に注意して[htmlを書き換えてからボタンのスタイルのプロパティを変えるように])修正したところ、ようやくうまくいきました。
サンプルD(IEもIE以外もOK)
css↓
#addDbtn {
display:none;
}
JavaScript↓
function delD() {
userAgent = window.navigator.userAgent.toLowerCase();
if (userAgent.indexOf("msie") == -1) {
document.getElementById('row1D').innerHTML=
'<th>1行目見出し</th>'+
'<td>1行目データ</td>'+
'<td rowspan="2">'+
'<input type="button" value="2行目を非表示" onclick="delD()" id="delDbtn" />'+
'<input type="button" value="2行目を表示" onclick="addD()"id="addDbtn" />'+
'</td>'
}
document.getElementById('delDbtn').style.display="none";
document.getElementById('addDbtn').style.display="block";
document.getElementById('row2D').style.display="none";
}
function addD() {
if (userAgent.indexOf("msie") > -1) {
document.getElementById('row2D').style.display="block";
}
else {
document.getElementById('row2D').style.display="table-row";
document.getElementById('row1D').innerHTML=
'<th>1行目見出し</th>'+
'<td>1行目データ</td>'+
'<td rowspan="3">'+
'<input type="button" value="2行目を非表示" onclick="delD()" id="delDbtn" />'+
'<input type="button" value="2行目を表示" onclick="addD()"id="addDbtn" />'+
'</td>'
}
document.getElementById('delDbtn').style.display="block";
document.getElementById('addDbtn').style.display="none";
}
html↓
<table>
<tr id="row1D">
<th>1行目見出し</th>
<td>1行目データ</td>
<td rowspan="3">
<input type="button" value="2行目を非表示" onclick="delD()" id="delDbtn" />
<input type="button" value="2行目を表示" onclick="addD()"id="addDbtn" />
</td>
</tr>
<tr id="row2D">
<th>2行目見出し</th>
<td>2行目データ</td>
</tr>
<tr id="row3D">
<th>3行目見出し</th>
<td>3行目データ</td>
</tr>
</table>
ちなみにinnerHTMLのソースの書き方は、「innerHTML内では改行は禁止? – JavaScript – 教えて!goo」の
JavaScriptでは、1つのコードの途中に改行を入れるとエラーになってしまいます。
なので、指定した文字列などを分割したい場合は、それぞれを+で繋げて分割すればOKです。
を参考にしました。
ということで、まとめ。
displayプロパティの値は、以下のものが取れます。
「displayプロパティ – CSSリファレンス」より
| inherit |
一番近い上位要素で指定された値を継承します。 |
| none |
当該要素を非表示にします。レイアウト上、当該要素は存在していないかのように扱われます。
また、この値を与えられた要素の下位要素は、それらに与えられたdisplayプロパティの値に拘らず表示されなくなります。
|
| inline |
インラインボックスの表示となります(デフォルト)。
HTMLでは、インライン要素となっている要素にはデフォルトでこのスタイルが当てられております。
|
| block |
ブロックレヴェルボックスの表示となります。
HTMLでは、ブロックレヴェル要素となっている要素にはデフォルトでこのスタイルが当てられております。
|
| list-item |
ブロックレヴェルボックスの表示となりますが、リストアイテムの表示方式になります。
HTMLでは<li>要素にのみデフォルトでこのスタイルが当てられております。
|
| run-in |
ラン・インボックスの表示となります。
HTMLには該当する要素は無いようです。
|
| compact |
コンパクトボックスの表示となります。
HTMLでは、compact属性値を附与した<dl>要素直下の<dt>要素にのみデフォルトでこのスタイルが当てられているようです。
|
| table |
表(テーブル)の表示スタイル(基本的にはブロックレヴェルボックス)となります。
|
| inline-table |
インライン表(テーブル)の表示スタイル(基本的にはインラインボックス)となります。
HTMLには実在しませんが、前後で改行しない表(テーブル)の表示スタイルです。
|
| table-row-group |
表(テーブル)の行グループの表示スタイルとなります。HTMLでは<tbody>要素のスタイルとなります。
|
| table-header-group |
表(テーブル)のヘッダグループの表示スタイル(HTMLでは<thead>要素のスタイル)となります。具体的にはこのプロパティ値を与えられていない全ての行の前、表題が表の上にある場合にはその直後(すなわち、表の上にある表題とこのプロパティ値を与えられていない全ての行の間)に表示されます。
※プリンタに対するスタイルシートに於いては、表が複数ページに跨る場合には、二ページ目以降の表にもこのプロパティ値を与えられた要素を一番上に表示するようにしても良い事となっております。
|
| table-footer-group |
表(テーブル)のフッタグループの表示スタイル(HTMLでは<tfoot>要素のスタイル)となります。具体的にはこのプロパティ値を与えられていない全ての行の後、表題が表の下にある場合には園直前(すなわち、このプロパティ値を与えられていない全ての行と表の下にある表題の間)に表示されます。
※プリンタに対するスタイルシートに於いては、表が複数ページに跨る場合には、最終ページより前の表にもこのプロパティ値を与えられた要素を一番下に表示するようにしても良い事となっております。
|
| table-row |
表(テーブル)の行成分の表示スタイルとなります。HTMLでは<tr>要素のスタイルとなります。
|
| table-column-group |
表(テーブル)の列グループの表示スタイルとなります。HTMLでは<colgroup>要素のスタイルとなります。
|
| table-column |
表(テーブル)の列の表示スタイルとなります。HTMLでは<col>要素のスタイルとなります。
|
| table-cell |
表(テーブル)のコマの表示スタイル(基本的にはブロックレヴェルボックス)となります。HTMLでは<th>要素及び<td>要素のスタイルとなります。
|
| table-caption |
表(テーブル)の表題の表示スタイルとなります。HTMLでは<caption>要素のスタイルとなります。
※caption-sideプロパティもご参照下さい。
|
table関連のdisplayプロパティデフォルト値
「displayプロパティ – CSSリファレンス」より
| <table>要素 |
display: table; 但し、表そのものをインライン表示したい場合には display: inline-table; とします。 |
| <tbody>要素 |
display: table-row-group; |
| <thead>要素 |
display: table-header-group; |
| <tfoot>要素 |
display: table-footer-group; |
| <tr>要素 |
display: table-row; |
| <colgroup>要素 |
display: table-column-group; |
| <col>要素 |
display: table-column; |
| <th>要素/<td>要素 |
display: table-cell; |
| <caption>要素 |
display: table-caption; |
所感:IE用に作ろうとするとそれ以外でおかしくなり、IE以外用に作ろうとするとIEでおかしく表示される。つまり、IEが諸悪の根源。