Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Как получить предыдущую ячейку при rowspan? (https://javascript.ru/forum/events/29709-kak-poluchit-predydushhuyu-yachejjku-pri-rowspan.html)

Cepin 08.07.2012 10:14

Как получить предыдущую ячейку при rowspan?
 
Есть огромная таблица с данными, в которой частенько встречаются ячейки со атрибутами rowspan и colspan.
Дана определенная ячейка из таблицы и нужно найти содержимое ее соседей (слева и справа).


Вот набросал мини-пример:
http://jsfiddle.net/zj7RU/

Вот таблица. Задача получить содержимое соседа слева(ячейка с номером 0) от ячейки с номером 5.


Как костыльный вариант использую следующую схему:
1) Создаю копию таблицы, где разворачиваю все colspan и rowspan (бью на ячейки с копированием содержимым)
2) Осуществляю переходы используя rowIndex и cellIndex

Вариант рабочий, но жутко тормозит на больших таблицах. Хотелось бы без глобального перебора.

Aetae 08.07.2012 10:46

Хитро.
Пока на ум приходит только построение виртуальной модели таблицы при загрузке и навигация уже по оной.

lord2kim 08.07.2012 11:00

а если nextSibling и previousSibling заюзать если известна требуемая (а она известна?)

Deff 08.07.2012 12:44

Cepin,
1.Проставить в каждой ячейке свой индивидуальный класс
2. сделать первичный обход таблицы по строкам - добавить класс предыдущей ячейки к следущей(для добавления фиксируем ток первый класс в списке
3. Аналогичный обход сделать по столбцам и тоже добавлять только первый текущий класс в списке к последующей ячейке

4. При выборе данной ячейки -ищем все ячейки с классами прописанными в ней

bes 08.07.2012 15:00

Как насчёт того, чтобы сохранять общее количество ячеек в строках, а неиспользуемым ячейкам ставить display: none

<table border=1 id="table" style="cursor: pointer;">
    <tr>
        <td rowspan="3">0</td>
        <td>1</td>
        <td rowspan="3">2</td>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td style="display: none"></td>
        <td id="td">5</td>
        <td style="display: none"></td>
        <td>6</td> 
        <td>7</td>
    </tr>
    <tr>
        <td style="display: none"></td>
        <td id="td">8</td>
        <td style="display: none"></td>
        <td>9</td> 
        <td>0</td>
    </tr>
</table>​
<script>
window.onload = function (e) {
  var table = document.getElementById('table');
  var len;
  var index;

  table.onclick = function(e) {
    e = e || event;
    var target = e.target || e.srcElement; 
    if (target.parentNode.tagName == 'TR') {
      if (target.previousElementSibling == null) {
        alert('нет предыдущей ячейки')
      } else {
         index = target.parentNode.rowIndex; 
        for (var i = index; i >= 0; i--) {
          if (target.previousElementSibling.style.display != 'none') {
            alert(target.previousElementSibling.innerHTML);
            break;
          } else {
            index--;
            target = table.rows[index].cells[target.cellIndex];
          }
        }
      }
    }
  }

}
</script>

Cepin 08.07.2012 15:55

К сожалению, но нет возможности как-то повлиять на вывод этой таблицы.
Вообщем, по совету Aetae решил делать не копию таблицу, а модель (в каждой ячейке хранит лишь запись о соотвествующих координатах первой таблицы)

Что сделано для оптимизации:
1) Заранее определен максимальный rowspan (в моем случае это 3)
2) Сканировать теперь всю таблицу не обязательно.

Стартовую строку для обработки можно начинать не с 0, а строка заданной ячейки - 5 (из-за максимального rowspan для избежания глюков).
Правую и нижнюю сторону ограничиваем координатами известной ячейки + 1

Все это делает довольно сильно сокращает объем таблицы и дает высокую скорость обработки.

Вроде даже работает, но чувствую, что могут быть камни в таком подходе.

bes 08.07.2012 16:49

Цитата:

Сообщение от Cepin
К сожалению, но нет возможности как-то повлиять на вывод этой таблицы.

Тогда проверять входит ли ячейка в строку, на которую распространён rowspan: последовательно проверяется есть ли в строках выше (до первой найденной) предыдущая по номеру ячейка с rowspan (getAttribute('rowspan')), значение которой распространяется до строки данной ячейки, если есть, значит предыдущее значение - это значение именно этой ячейки с rowspan.

Deff 08.07.2012 19:25

Вообще говоря задача типично решаемая в "Игре морской бой" тут где то было решение

bes 09.07.2012 15:50

<style>
  table, td {border: solid 1px; cursor: pointer}
</style>

<table id="table">
    <tr>
        <td rowspan="3">0</td>
        <td>1</td>
        <td rowspan="3">2</td>
        <td colspan="2">3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>5</td>
        <td  rowspan="2">6</td> 
        <td>7</td>
        <td>8</td>
    </tr>
    <tr>
        <td id="td">9</td>
        <td>10</td> 
        <td>11</td> 
    </tr>
</table>​

<script>
window.onload = function () {//onload begin
  var table = document.getElementById('table');
  var coord, left, top, right, previous, next;
  var d = 5;//здесь можно уточнить
  var p, n;

  table.onclick = function(e) {//onclick begin
    e = e || event;
    var target = e.target || e.srcElement;

    if (target.parentNode.tagName == 'TR') {//if begin
      coord = target.getBoundingClientRect();
      left = coord.left + 1; 
      top = coord.top + 1; 
      right = coord.right; 
      previous = document.elementFromPoint(left - d, top);
      next = document.elementFromPoint(right + d, top);
   
      if (previous.parentNode.tagName == 'TR')  {
        p = previous.innerHTML;
      } else {
        p = 'нет';
      }

       if (next.parentNode.tagName == 'TR')  {
         n = next.innerHTML;
       } else {
         n = 'нет';
       }
      
       alert('предыдущий: ' + p + '\nследующий: ' + n)

      }//if end

  }//onclick end
   
}//onload end
</script>

Deff 09.07.2012 16:14

bes,
Плюс! - ток в универсальном варианте нун искать все элементы по каждой из 4-x сторон: в порядке(обхода) прилегания и Учитываешь ли - что эл-т может быть одновременно и rowspan и colspan ?
(*Ксать скрипт весьма востребованный в бугалтерских расчетах - если exel таблы переносят в брауз,
Его бы добить и вылизать


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