Интересная задачка.
На оптимальность решения не претендую, безупречность не гарантирую. Но всё же, вот что у меня получилось...
<script type="text/javascript">
// table: элемент DOM Table, THead, TBody или TFoot
// col: позиция колонки
function deleteTableCol (table, col) {
var rows = table.rows, cells, cell, prevCell;
var cx, cy, cw, ch, coff;
var map = [], mx, my, mw = 0, mh = 0;
for (cy=0; cy<rows.length; cy++) {
cells = rows[cy].cells;
for (cx=0, coff=0; cx<cells.length; cx++, coff+=cw) {
cell = cells[cx];
cw = cell.colSpan;
ch = cell.rowSpan;
if (cw == 0 || ch == 0) { return false;
// динамическую растяжку ячеек по <colgroup> (при colspan=0)
// и по <thead> / <tbody> / <tfoot> (при rowspan=0)
// сложно обработать; поэтому, чтобы не напортачить, выходим
}
while (mh < cy+ch) { map[mh++] = []; }
while (map[cy][coff] !== undefined) { coff++; }
for (my=cy; my<cy+ch; my++) {
for (mx=coff; mx<coff+cw; mx++) {
if (map[my][mx] !== undefined) { return false;
// при подсчете размеров и позиций у нас получилось,
// что ячейки якобы "накладываются" друг на друга;
// такую ситуацию тоже сложно обработать, выходим
}
map[my][mx] = cell;
}
}
if (coff+cw > mw) { mw = coff+cw; }
}
}
if (col >= mw) { return true;
// ячеек в указанной позиции нет,
// поэтому ничего делать не надо, выходим
}
for (my=0; my<mh; my++) {
cell = map[my][col];
if (cell !== prevCell && cell !== undefined) {
cw = cell.colSpan;
if (cw > 1) { cell.colSpan = cw-1; }
else { rows[my].removeChild(cell); }
prevCell = cell;
}
}
return true;
}
onload = function () {
var table = document.getElementById("table1");
var tableCols = 5;
var i, button;
for (i=0; i<tableCols; i++) {
button = document.createElement("input");
button.type = "button";
button.value = i;
button.id = "delete" + i;
button.onclick = (function (i) { return function () {
deleteTableCol(table, i);
document.body.removeChild(document.getElementById("delete" + (--tableCols)));
}})(i);
document.body.appendChild(button);
}
}
</script>
<table id="table1" border="1">
<tr>
<td rowspan="3">11111</td>
<td colspan="2">22222</td>
<td colspan="2">33333</td>
</tr>
<tr>
<td>44444</td>
<td colspan="2" rowspan="2">55555</td>
<td>66666</td>
</tr>
<tr>
<td>77777</td>
<td>88888</td>
</tr>
<tr>
<td colspan="5">99999</td>
</tr>
</table><br>
Некоторые соображения:
1. Условно-пустые строки (все
<tr>
, в которых не осталось ни одного
<td>
) - не удаляются, а остаются как есть, чтобы не нарушать структуру таблицы с учетом ячеек, растянутых по вертикали.
2. Полностью пустые строки (те, с которыми не пересекается ни одна вертикально растянутая ячейка) - тоже пока не удаляются. Но это можно допилить.
3. Все colspan'ы в таблице должны быть указаны арифметически корректно, то есть так, чтобы, например, не пытаться втиснуть двойную ячейку туда, где есть место только для одинарной:
<table>
<tr>
<td>1111</td>
<td rowspan="2">2222</td>
</tr>
<tr>
*!*
<td colspan="2">3333</td>
*/!*
</tr>
</table>
С такой таблицей ничего не произойдет и функция просто вернет
false
.
4.
Поведение ячеек с
colspan="0"
и
rowspan="0"
обрабатывать слишком муторно, поэтому, наткнувшись на таковые, функция опять-таки ничего не сделает и вернет
false
.
5. Относительно
<table>
строки извлекаются
сразу изо всех имеющихся секций (
<thead>
,
<tbody>
и
<tfoot>
), то есть будут обработаны ВСЕ
<tr>
насквозь, как будто они имеют одного общего родителя. Поэтому, если секции указаны явно, то, на всякий случай, функцию лучше вызывать для каждой из них по отдельности.
Только прошу сперва тщательно всё потестировать.