Доброе время суток!
Товарище, подскажите куда копать. Только начинаю изучать javascript и столкнулся с задачей:
Есть таблица в html, есть массив элементов td (100 штук в массиве).
Нужно при нажатии на td узнать номер этого элемента в массиве.
Пробовал так:
for (var i = 0; i < fieldArray.length; i++) {
fieldArray[i].onclick = check;
}
Тут я с помощью цикла всем элементам вешаю событие клика, далее пробовал написать эту функцию, которая узнает номер элемента в массиве (примеры неправильного кода сейчас привести не могу, но много чего пробовал). Не хватает знаний реализовать данное чудо, подскажите как это сделать или куда копать/что читать. Спасибо!
var cellsArray = [ ...document.querySelectorAll('td') ];
var listener = e => document.getElementById('output').innerHTML = cellsArray.indexOf(e.target); // Создать элемент вывода надо заранее
cellsArray.forEach( cell => cell.addEventListener( 'click', listener ) );
Прокомментирую код. В общем, создаем переменные, в которых будут объекты дом. Один для вывода результата, второй для перебора. Смысл такой, что при клике мы с помощью метода indexOf можем узнать номер элемента массива, НО! querySelectorAll возвращает нам объект не типа array, а nodeList, и у него нет метода indexOf, поэтому я переписал массив элементов. Далее повесил обработчик события, который по умолчанию принимает объект события. Обработчик смотрит индекс элемента по которому кликнули и записывает все это в див с классом рес.
Жоско Вы переписываете массив в цикле…
А ведь уже есть оператор spread, а до него много лет был Array.prototype.slice, а потом и from для таких дел.
А уж обработчик новый создавать при каждом проходе цикла это вообще за гранью. Представляете, сколько памяти в никуда?
pygame, Bhudh, Прям перед вами написал: "Сразу скажу, по-хорошему код можно еще улучшить."!!! Я вечером уставший пил чай и решил подсказать человеку, хоть в общих чертах. Человек только учиться, вряд-ли он сейчас умеет ес6,с бэйблом работать, в прототипы лезть. Вариант с дата очень даже, можно было бы предложить. Возьмите и напишите свой ответ. Раскритиковали, будто я на продакшен код написал) Я понимаю, сколько памяти в никуда и прочее, но я не на заказ это делаю, а просто написал рабочий вариант, и описал нюансы, почему indexOx не функция и так далее. Пусть посмотрит, что такое разные типы объектов, что обработчик принимает ивент, что вешать события надо с помощью цикла и не на onclicj, а с помощью addEventList... Сразу грузить его делегированием, прототипами, спред операторами, тоже на мой взгляд жестко.
Дмитрий Дербенев, если будет возможность расскажу больше, более идеальный вариант, pygame говорил про data атрибуты, как раз хороший вариант, без лишней мороки, плюс можно сделать прослушку события на родителе, и через объект события вытаскивать данные, вечером постараюсь написать вариант этот с комментариями.
Дмитрий Дербенев, bhudh написал вариант тоже классный и лаконичный и современный, и после освоения js советую этот современный синтаксис изучить: вот видео, и не только видео.
Дело в том, что es6 сейчас можно юзать, но с полифилами и обрабатывать через babel.
var cellsArray = [ ...document.querySelectorAll('td') ];
- это по сути перезапись массива в массив, в моем варианте я тоже самое делал в цикле for, разница в том, что так лаконичнее и переменных меньше, так как querySelectorAll сразу распаковывается и записывается в новый массив. "...Obj" это называется spread оператор, три точки перед объектом внутри другого объекта как команда распаковки одного объекта в другой.
Переписать массивы пришлось, так как у обычного массива есть метод indexOf, а querySelectorAll возвращает объект типа NodeList, у которого нет этого метода. indexOf принимает параметр и возвращает порядковый номер этого элемента в массиве, у которого этот метод вызван, если переданный элемент в нем есть, если нет, то indexOf вернет, внезапно, -1.
Также в примере указаны стрелочные функции, это тоже из es6, их особенность в том, что они сохраняют контекст, this, который, скажем, во внешней среде, до объявления функции. В случаях, когда вешаете eventListener стрелочная функция может сыграть злую шутку, если вместо e.target Вы захотите просто обратится к this, так как this теперь станет таким, каким был в области видимости перед объявлением функции, в данном примере this станет window. Сейчас модно писать стрелочные функции, потому что как бы экономим на слове function, скобках и так далее, а еще такая форма записи помогает не писать return.
У этого способа есть плюсы, что теперь не важно, будут новые элементы, или нет, индекс получаем с помощью indexOf, а не из дата атрибутов.
В конце примера с помощью forEach проходимся по массиву и на каждый элемент вешаем обработку события, вот тут можно как раз как в моем варианте, просто на родителя повесить, например на тег table, и искать с помощью e.target, задействуя всплытие событий.