@Alibenc

Как делегировать событие mouseenter?

Задача: необходимо подсвечивать колонки таблицы при наведении.

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

Сделал с событием mouseover, работает, но оно не подходит. Взял событие "mouseenter", оно подходит, но с ним делегирование не работает, и в консоли выдает "e.target.closest is not a function"

Прошу помочь, почему так получается, и как все-таки делегировать событие mouseenter
p.s большинство стилей убрал, но в основном, суть сохранил

document.addEventListener('mouseenter', function (e) {
  if (e.relatedTarget) {
    if (e.relatedTarget.closest('._hight-light__cell')) {
      const cells = document.querySelectorAll('._hight-light__cell');
      for (cell of cells) {
        cell.classList.remove('_hover');
      }
    }
  }
  if (e.target.closest('._hight-light__cell')) {
    const hoverCell = e.target.closest('._hight-light__cell');
    const hoverCellNum = hoverCell.getAttribute('data-tdnum');
    if (hoverCell.classList.contains('_hover')) {
      return;
    } else {
      const cells = document.querySelectorAll('._hight-light__cell');
      for (cell of cells) {
        const cellsWithNum = document.querySelectorAll(`[data-tdnum="${hoverCellNum}"]`);
        for (cellWithNum of cellsWithNum) {
          cellWithNum.classList.add('_hover');
        }
      }
    }
  }
})

<table class="pilmat-tables__table-big table-big">
              <tr class="pilmat-tables__main-row pilmat-tables__visible">
                <th class="pilmat-tables__head">ПИЛОМАТЕРИАЛЫ ОБРЕЗНЫЕ ЕСТЕСТВЕННОЙ ВЛАЖНОСТИ</th>
              </tr>
              <tr class="table-big__row pilmat-tables__row light-blue pilmat-tables__visible">
                <td class="_hight-light__cell table-big__number">&#8470;</td>
                <td class="_hight-light__cell table-big__name">наименование</td>
                <td class="_hight-light__cell table-big__size">размер сечения, <br>мм</td>
                <td class="_hight-light__cell table-big__grade">сорт</td>
                <td class="_hight-light__cell table-big__long">длина, м</td>
                <td class="_hight-light__cell table-big__amount"> 
                  кол-во шт в м<span class="goods__squared">3</span>
                </td>
                <td class="_hight-light__cell table-big__price">цена, руб</td>
                <td class="_hight-light__cell table-big__write-amounth">укажите количество</td>
                <td class="_hight-light__cell table-big__total-cost">стоимость, <br> руб</td> 
                <td class="_hight-light__cell table-big__add-del">добавить/ удалить</td>
              </tr>
              <tr class="table-big__row pilmat-tables__row pilmat-tables__visible">
                <td class="_hight-light__cell table-big__number table-big__defult">1</td>
                <td class="_hight-light__cell table-big__name table-big__defult">доска обрезная <br> 25 х 100 х 6000</td>
                <td class="_hight-light__cell table-big__size table-big__size-img table-big__defult">
                  <div class="table-big__img-wrapper">
                    <div class="table-big__img-wrapper-inner">
                      <img src="http://127.0.0.1:5500/img/pages_img/pilmat/pilmat-tables/section_size1.webp" 
                      alt="сечение" class="table-big__img _pb_img_max">
                    </div>
                  </div>
                </td>
                <td class="_hight-light__cell table-big__grade table-big__defult">AB</td>
                <td class="_hight-light__cell table-big__long table-big__defult">6</td>
                <td class="_hight-light__cell table-big__amount table-big__defult">66</td>
                <td class="_hight-light__cell table-big__price table-big__defult">15 000</td>
                <td class="_hight-light__cell table-big__write-amounth write-amounth table-big__defult">
                  <div class="write-amounth__item-wrapper">
                    <div class="write-amounth__item">шт</div>
                    <div class="write-amounth__item">м<span class="goods__squared">3</span></div>
                  </div>
                  <div class="write-amounth__item-wrapper">
                    <div class="write-amounth__item">33</div>
                    <div class="write-amounth__item">0,5</div>
                  </div>
                  
                </td>
                <td class="_hight-light__cell table-big__total-cost table-big__defult">7 000</td> 
                <td class="_hight-light__cell table-big__add-del table-toggle table-big__defult">
                  <div class="table-toggle__item">V</div>
                  <div class="table-toggle__item">X</div>
                </td>
              </tr>
            </table>

._hight-light__cell._hover {
  background-color: #09AB3D;
  color: #fff;  
}
._hight-light__cell:hover {
  font-weight: 700;
}
  • Вопрос задан
  • 139 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
делегирование не работает

Ну ещё бы оно работало - mouseenter не всплывает. Надо его ловить на стадии захвата.

в консоли выдает "e.target.closest is not a function"

Всё правильно - обработчик висит на документе, документ не является элементом, соответственно, никаких методов элемента у него нет.

const hoverCellNum = hoverCell.getAttribute('data-tdnum');

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

Исправляем:

document.addEventListener('mouseenter', ({ target: t }) => {
  if (t.matches?.('td._hight-light__cell')) {
    t.closest('tbody').querySelectorAll('.table-big__row').forEach(n => {
      n.cells[t.cellIndex].classList.add('_hover');
    });
  }
}, true);

document.addEventListener('mouseleave', e => {
  if (e.target.matches?.('td._hight-light__cell')) {
    document.querySelectorAll('._hover').forEach(n => n.classList.remove('_hover'));
  }
}, true);
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
NikFaraday
@NikFaraday
Student full-stack Developer
Это да
Навешивать слушатель событий на каждую ячейку таблицы не вариант


Но я бы сделал автоматизировано. Думаю, с помощью селектором не проблема обратиться к каждой ячейке и уже на ню повешать событие
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы