Как получить соседние ячейки таблицы?

240
22 апреля 2018, 19:38

Ситуация такая:

Я навожу курсор на любую ячейку таблицы и хочу получать массив(список/объект, вообще не важно) с соседними ячейками. Таблица при этом может быть отформатирована как угодно.

На самом деле есть решение(точнее идея) с координатами ячеек, но хотелось бы узнать ещё способы.

Answer 1

  const $table = document.querySelector('table'); 
  const $input = document.querySelector('input'); 
  const $span = document.querySelector('span'); 
 
  $table.addEventListener('mousemove', onMove); 
  $input.addEventListener('change', onChange); 
 
  function clean() { 
    const $actives = $table.querySelectorAll('.active'); 
    const $neighbours = $table.querySelectorAll('.neighbour'); 
 
    $actives.forEach($active => $active.classList.remove('active')); 
    $neighbours.forEach($neighbour => $neighbour.classList.remove('neighbour')); 
  } 
 
  function indexOf($element) { 
    return Array.prototype.slice.call($element.parentElement.children).indexOf($element); 
  } 
 
  function onChange() { 
    $span.innerHTML = $input.value; 
  } 
 
  onChange(); 
 
  function onMove(event) { 
    const $target = event.target; 
 
    if ($target.tagName !== 'TD' || $target.classList.contains('active')) { 
      return; 
    } 
 
    const far = parseInt($input.value); 
    const neighbours = getNeighbors($target, far); 
 
    clean(); 
 
    $target.classList.add('active'); 
    neighbours.forEach(neighbour => neighbour.classList.add('neighbour')); 
  } 
 
  /** 
   * Получить соседей ячейки 
   * @param {HTMLTableCellElement} $cell Исходня ячейка 
   * @param {Number} far На сколько далёких соседей нужно получить 
   * @return {HTMLTableCellElement[]} 
   */ 
  function getNeighbors($cell, far = 1) { 
    // выбираем строку ячейки 
    const $row = $cell.parentElement; 
    // выбираем элемент, который держит все строки (обычно это <table> или <tbody>) 
    const $wrapper = $row.parentElement; 
 
    // находим индекс исходной ячеки 
    const index = [ 
      indexOf($row), // индекс строки 
      indexOf($cell) // индекс ячейки 
    ]; 
 
    // вычисляем ограничивающий "ящик" 
    const bbox = [ 
      Math.max(index[0] - far, 0), // индекс минимальной строки 
      Math.max(index[1] - far, 0), // индекс минимальной ячейки 
      Math.min(index[0] + far, $wrapper.children.length - 1), // индекс максимальной строки 
      Math.min(index[1] + far, $row.children.length - 1) // индекс максимальной ячейки 
    ]; 
 
    // массив с результатом 
    const list = []; 
 
    // перебираем все строки из bbox 
    for (let i = bbox[0]; i < bbox[2] + 1; i++) { 
      const $sRow = $wrapper.children.item(i); 
 
      // в рамках каждой строки, перебираем все ячейки из bbox 
      for (let j = bbox[1]; j < bbox[3] + 1; j++) { 
 
        // если сейчас ячейка является исходной, пропускаем её 
        if (i === index[0] && j === index[1]) { 
          continue; 
        } 
 
        const $sCell = $sRow.children.item(j); 
 
        list.push($sCell); 
      } 
    } 
 
    return list; 
  }
table { 
  border: 1px; 
} 
 
td { 
  width: 30px; 
  height: 30px; 
  content: ''; 
  border: 1px solid green; 
} 
 
td.active { 
  background: #ff0000; 
} 
 
td.neighbour { 
  background: #ff9999; 
}
<input type="range" min="0" max="5" step="1" value="1"> 
<span></span> 
<table> 
  <tr> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
  </tr> 
  <tr> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
  </tr> 
  <tr> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
  </tr> 
  <tr> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
  </tr> 
  <tr> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
  </tr> 
  <tr> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
    <td></td> 
  </tr> 
</table>

Answer 2

У элемента td, свойство parentElement указывает на родительский элемент tr.
А у элемента tr, свойство children содержит коллекцию дочерних элементов td.

var table = document.getElementById('my-table');  
for (let td of table.querySelectorAll('td'))  
  td.addEventListener('mouseenter', showSiblings); 
 
function showSiblings() { 
  let str = '',  
      siblings = this.parentElement.children;  
  for (let td of siblings) { 
    if (td === this) 
      str += ` [${td.textContent}]`;  
    else 
      str += `  ${td.textContent} `;   
  } 
  console.clear();  
  console.log(str);  
}
table { border-collapse: collapse; text-align: center; } 
   td { width: 50px; height: 30px; border: 1px solid #ccc; }
<table id="my-table"> 
  <thead></thead> 
  <tbody> 
    <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr> 
    <tr><td>5</td><td>6</td><td>7</td><td>8</td></tr> 
    <tr><td>9</td><td>10</td><td>11</td><td>12</td></tr> 
    <tr><td>13</td><td>14</td><td>15</td><td>16</td></tr> 
  </tbody> 
</table>

Если необходимо получать также и ячейки строкой выше/ниже, то можно использовать такие свойства элемента tr как previousElementSibling и nextElementSibling - они ссылаются на предыдущий и следующий tr, соответственно.

READ ALSO
Глючит анимация html js

Глючит анимация html js

Я делаю всплывающее окно, над кнопкой, при успешном добавлении в корзинувсе вроде работает, но проблема если товар находится в слайдере, slick

208
innerHTML. В чем проблема?

innerHTML. В чем проблема?

Имеется некоторое количество строк кода:

192
OptimisticLock при управлении транзакциями сервером

OptimisticLock при управлении транзакциями сервером

Имеем: Сервер Wildfly, управление транзакциями - контейнерИспользуется XA транзакция

166
Как отрисовать объекты Box2D

Как отрисовать объекты Box2D

Как можно корректно отобразить объекты JBox2D с помощью обычных функций Graphics2D, которые находятся в стандартной Java библиотеке?

137