JavaScriptでテーブルを操作する
テーブルを操作するプロパティやらメソッド。-1がデフォルトで最後の行。
| 命令 | プロパティ | メソッド | オブジェクト |
|---|---|---|---|
| 列の取得 | rows | table,thead,tbody,tfoot | |
| セルの取得 | cells | tr,th,rows[i] | |
| 列の追加 | insertRow | table,thead,tbody,tfoot | |
| セルの追加 | insertCell | tr,th,rows[i] | |
| 列の削除 | deleteRow | table,thead,tbody,tfoot | |
| セルの削除 | deleteCell | tr,th,rows[i] | |
| セルの番号取得 | cellIndex | td,cells[i] | |
| テーブル全体での列の番号取得 | rowIndex | table | |
| 列の番号取得 | sectionRowIndex | tr,th,row[i] |
cellIndexでは、同じ列のセルは同じ番号が振られる。
0 1 2
0 1 2
columnが列、rowが行という意味らしいが、日本語で考えたら横の行がcolumnで、縦の列がrowですから上手く整理しないとごちゃごちゃになります。
rowIndexとsectionRowIndexは、特定のtrとかの列番号を返すのは同じだけど、テーブル全体から数えて何番目か、そのtrのセクション(thead,tfoot,tbody)タグから数えて何番目かの違い。
テーブル追加・削除サンプルを読み解く
こちらのページで紹介されているスクリプトを考えて見ます。
<table id="sample" border="1">
<thead id="samplethead">
<tr>
<th>名前A</th>
<th>名前B</th>
<th>名前C</th>
</tr>
</thead>
<tbody id="sampleTbodyA">
<tr>
<td>1行目1列目</td>
<td>1行目2列目</td>
<td>1行目3列目</td>
</tr>
</tbody>
<tbody id="sampleTbodyB">
<tr>
<td>2行目1列目</td>
<td>2行目2列目</td>
<td>2行目3列目</td>
</tr>
<tr>
<td>3行目1列目</td>
<td>3行目2列目</td>
<td>3行目3列目</td>
</tr>
</tbody>
</table>
このサンプルスクリプトではsrcElementを使用しているので、Firefoxでは動きません。そこで、Firefoxに対応させるためのイベントリスナを先に実行しておきます。
//srcElementをtargetに関連付ける
if (window.addEventListener){ //IE以外に適用(IE8以下はattachEvent)
window.addEventListener("click",function(e){ //クリックイベントが起こったら
window.event = e; //発火したイベントはwindow.eventと同じ
window.event.srcElement = e.target; //firefox用のイベントを起した要素を、非対応のwindow.event.srcElementに対応させる。
},true); //trueはキャプチャーフェーズでIEだけ非対応
}
function sample(){
var bt = window.event.srcElement;//この場合押されたボタンのinput要素
if(bt.nodeName != 'INPUT') return;//ボタン以外(inputでなければ)なら抜け出す
//if(bt.parentNode.cellIndex>0) return;//押されたボタンのinputの親のtd、thのcellが1以上(+ーのボタンでなければ)なら抜け出す
var tr = bt.parentNode.parentNode;//押されたボタンのinputの親の親すなわちtr
//var thF = (tr.parentNode.nodeName == 'THEAD');//trの親の要素はthead→題名欄thの親を指定
var tbod = tr.parentNode;
//var tbod = (thF)?tr.parentNode.parentNode.tBodies[0]:tr.parentNode;//theadならtbod=tBodies[0]、tbodyならtbod=押されたボタンの属するtbody
if(bt.value == '削除'){//マイナスボタンなら
//if(thF)return;
/*if(tbod.rows.length<1){
alert("こんなことないけどエラーだよ");
return;
}*/
tbod.deleteRow(tr.sectionRowIndex);//sectionRowIndexはtrのtbodyから数えて何番目か。
}
}
変数btに値を代入。もしbt.event.srcElement(クリックイベントが起こったinput要素)のノード名が、inputじゃなかったら、undefinedを返す。function内だからforとかのようなbreakとはちょっと違う。
もしbt.bt.parentNode.cellIndex>1(inputの親であるtdのセル番号が1より大きい=+とーボタンが入ったセル行でない)ならreturn。
変数trにイベントが起こったinputの親(td)の親(tr)を代入。その変数trの親(theadかtbody)のノード名がtheadという比較文自体をthFという変数に代入。
tbodという変数に、P=A?B:C;(PはAが真ならB、偽ならC文)を利用して、theadつまり1行目だったら、tbodはtrの親(thead)の親(table)の最初のtbodyまでを代入、違う(tbodyだった)なら、trの親(tbody)までを代入。
var newt = document.getElementById("sample").tBodies[0];//tbodyがなければtableの最後の行
var newtr = newt.insertRow(-1);//引数:新しい行の行番号( 0 が一行目)index に -1 または行数に等しい場合、行は最後の行として追加される。
var newtd0 = newtr.insertCell(0);
var newtd1 = newtr.insertCell(1);//row、th、trオブジェクトのメソッド
var newtd2 = newtr.insertCell(2);
var newtd3 = newtr.insertCell(3);
var newtd4 = newtr.insertCell(4);
var newtd5 = newtr.insertCell(5);
var newtd6 = newtr.insertCell(6);
var newtd7 = newtr.insertCell(7);
var newtd8 = newtr.insertCell(8);
newtd0.innerHTML = "";
newtd1.innerHTML = "1";
newtd2.innerHTML = "2";
newtd3.innerHTML = "3";
newtd4.innerHTML = "4";
newtd5.innerHTML = "5";
newtd6.innerHTML = "6";
newtd7.innerHTML = "7";
newtd8.innerHTML = "8";
*/
DOMで行を追加するtbodyを選んで、insertRow()で追加する。これを変数にいれるんで、それ以下のinsertCell()は、その追加した行に対して追加される。
以下の様な形にすると、行がその都度追加されてしまって、追加したセルが横一列に並ばない。同じindex番号のセルは縦並びになる。
var newt = document.getElementById("sample").tBodies[0];//tbodyがなければtableの最後の行
newt.insertRow(-1).insertCell(0).innerHTML = "";
newt.insertRow(-1).insertCell(0).innerHTML = "1";
newt.insertRow(-1).insertCell(1).innerHTML = "1";
newt.insertRow(-1).insertCell(2).innerHTML = "2";
newt.insertRow(-1).insertCell(3).innerHTML = "3";
newt.insertRow(-1).insertCell(4).innerHTML = "4";
newt.insertRow(-1).insertCell(5).innerHTML = "5";
newt.insertRow(-1).insertCell(6).innerHTML = "6";
newt.insertRow(-1).insertCell(7).innerHTML = "7";
newt.insertRow(-1).insertCell(8).innerHTML = "8";
テーブルにセル追加、削除のスクリプトはこれでいいと思われる。
function clrow(o){
var inp = o.getElementsByTagName('input');
for(var i=0;inp[i];i++){
if(inp[i].type == 'text') {
inp[i].value = inp[i].defaultValue;
}
}
}
とばして、clrow関数の宣言。inp変数に引数(2行目)のinputを代入。その行のinputは+と-とテキストフィールドの3つある。<
for文にて、inputを1個ずつ探して、typeがtextのものが見つかったら、そのvalueをdefaultvalueにする。最後の1行を削除しようとすると内容(input)のクリアだけ行われるための命令。
if(bt.value == '-'){
if(thF)return;
if(tbod.rows.length<2){
clrow(tbod.rows[0]);
return;
}
tbod.deleteRow(tr.sectionRowIndex);
もし選択されたinputのvalueがマイナスなら、もし親がtheadならundefiend、もしtbodyの行が2よりも小さいなら、clrowが実行されて内容だけがクリアされる。
それ以外なら、tbodyの(押されたinputのtrの行の番号)がdeleterowで行削除される。
} else {
var rcopy = tbod.rows[0].cloneNode(true);
clrow(rcopy);
if(!thF && tr.sectionRowIndex+1==tbod.rows.length) {
tbod.appendChild(rcopy);
} else {
tbod.insertBefore(rcopy,(thF)?tbod.rows[0]:tr.nextSibling);
}
}
押されたボタンがマイナスじゃない(+)なら、変数rcopyにtbodyの1行目のノードを複製するしたものを代入。trueだから値もコピーされるため、clrow関数でテキストフィールドを初期化。
もし、クリックされたinputの親がtheadでなく、そのtrの行番号+1番目がtbodyの総列数と同じなら、tbodyの最後部にrcopyを追加する。(最後の行に追加するパターン)
それ以外なら、tbodyの子ノードとして、rcopyを、押したボタンの親がtheadならtbodyの先頭に、押したボタンの親がtbodyならそのtrの次の行(エレメント)へ。
コメントor補足情報orご指摘あればをお願いします。
記事No2393 題名:よろしくお願いいたします 投稿者:家島ダイアグラム 投稿日:2023-02-05 20:01:30
家島の情報サイトです。船やバスの時刻表や天気など様々な情報を発信中!!時刻表が変わった・間違いがある・ご要望の場合は連絡お願いします。Twitter・LINEをフォローまたはRSSでサイト更新時に通知します。
家島ダイアグラム
https://hyogo.ie-t.net/ #家島 #坊勢 #男鹿 #時刻表 #船 #神姫バス
- << 前のページ
- 次のページ >>
