Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Ох эти таблицы (https://javascript.ru/forum/events/30452-okh-ehti-tablicy.html)

Apollo_440 05.08.2012 01:45

Ох эти таблицы
 
Доброго времени суток, форумчане. Встал вопрос о том, как удалить колонку в таблице, притом с colspan ами и rowspan ами. Подате хотя бы идею как это сделать.

Надеюсь на вашу помощь. Прошу проверять вот на этой табличке:

<table border="1">
 <tr>
  <td rowspan="3">1111</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>

Дзен-трансгуманист 05.08.2012 07:10

Интересная задачка. :)
На оптимальность решения не претендую, безупречность не гарантирую. Но всё же, вот что у меня получилось...

<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> насквозь, как будто они имеют одного общего родителя. Поэтому, если секции указаны явно, то, на всякий случай, функцию лучше вызывать для каждой из них по отдельности.

Только прошу сперва тщательно всё потестировать. :)

Deff 05.08.2012 09:58

Цитата:

Сообщение от Apollo_440
Встал вопрос о том, как удалить колонку в таблице,

Apollo_440,
Произвольную ? (Или только первую) С произвольной - вряд ли универсально - посколь для каждого случая нужен алгоритм - что делать с ячейками с соlspan более этой колонки

bes 05.08.2012 11:07

Я бы предложил добить таблицу недостающими ячейками c display: none, а потом решать какие ячейки будете удалять, где-то тут есть тема про нахождение соседних ячеек в таблице

http://javascript.ru/forum/events/29...i-rowspan.html

Apollo_440 05.08.2012 12:50

Дзен-трансгуманист,
благодарю. Это везде пашет, то есть на любых таблицах?
Deff,
как раз то универсал нужен. Эту таблицу дал якобы со всеми случаями жизни.
bes,
не вариант.

Пока буду разбирать код первого поста. Очень хорош...

Deff 05.08.2012 13:19

Цитата:

Сообщение от Apollo_440
как раз то универсал нужен. Эту таблицу дал якобы со всеми случаями жизни.

Универсал вряд ли возможен - (*если нет железного алгоритма, либо не прописаны все удаляемые ячейки колонки )
- я сталкивался с данной задачей: - седни бухгалтера говорят - алгоритм удаления такой - завтра иначе - Итоговый Вариант: - все ячейки в строках,( вплоть для идентичных повторяющих друг друга строк) - Бух задаёт явно явно кликая по ним в исходнике, и составляя граф удаления - в строках с идентичной структурой - алгоритм задается единожды

Apollo_440 05.08.2012 14:14

А что если просканировать всю таблицу и записать в массив colspan ы, если rowspan>1?? и записать еще в следующие ячейки до rowspan значения? Тогда вероятно получится получить реальные значения ячеек, где длина их в строке меньше максимальной в данной таблице...

Deff 05.08.2012 14:31

Apollo_440,
Да структуировать и восстановить пол-дела - но при удалении колонки - не ячейки - встают вопросы что делать с нижестоящей ячейкой у которой colspan более чем 1 она она по центру (к примеру) под удаляемой колонкой и забита текстом без переноса(цифры) - Переносить цифры ?

bes 05.08.2012 14:45

Поэтому кажый раз придумывать реализацию под новые требования легче, когда все ячейки на руках. ;)

Apollo_440 05.08.2012 14:52

Deff,
colspan-1. Вроде как бы еще действует. Получили индекста удаляемых ячеек - а затем при удалении обновляем colspan на единицу меньше.

Думаю работать будет. Конечно массив шаблона не самое лучшее решение, так как придется сканировать всю таблицу (размеры таблицы играют большую роль).

Самое важное сейчас для меня - получить реальный индекс в строке.


Часовой пояс GMT +3, время: 03:32.