Делегирование событий Javascript, обработка родительских элементов с щелчком?
http://jsfiddle.net/walkerneo/QqkkA/
Я видел много вопросов здесь или спрашивал или отвечал на делегирование событий в javascript, но я еще не видел, как использовать делегирование событий для элементов, которые не станут объектами щелкните событие.
Например:
HTML:
<ul>
<li><div class="d"></div></li>
<li><div class="d"></div></li>
<li><div class="d"></div></li>
<li><div class="d"></div></li>
<li><div class="d"></div></li>
<li><div class="d"></div></li>
</ul>
CSS
ul{
padding:20px;
}
li{
margin-left:30px;
margin-bottom:10px;
border:1px solid black;
}
.d{
padding:10px;
background:gray;
}
Что делать, если я хочу добавить событие click для обработки элементов li
при нажатии? Если я присоединю обработчик события к элементу ul
, div
всегда будет целевыми элементами. Помимо проверки каждого родителя целевого элемента в функции щелчка, как я могу это сделать?
изменить:
Я хочу использовать делегирование событий вместо:
var lis = document.getElementsByTagName('li');
for(var i=0;i<lis.length;i++){
lis[i].onclick = function(){};
}
Но если я это сделаю:
document.getElementsByTagName('ul')[0].addEventListener('click',function(e){
// e.target is going to be the div, not the li
if(e.target.tagName=='LI'){
}
},false);
EDIT: Мне не интересно, как использовать библиотеки JavaScript для этого, мне интересно, как они это делают и как это можно сделать с помощью чистого js.
Ответы
Ответ 1
Вот один из способов его решения:
var list = document.getElementsByTagName('ul')[0]
list.addEventListener('click', function(e){
var el = e.target
// walk up the tree until we find a LI item
while (el && el.tagName !== 'LI') {
el = el.parentNode
}
console.log('item clicked', el)
}, false)
Это слишком упрощено, цикл продолжит движение по дереву даже через элемент UL. Для более полного примера см. Реализацию rye/events.
Element.matches
, Node.contains
и Node.compareDocumentPosition
могут помочь вам реализовать этот тип функций.
Ответ 2
Теперь есть метод для элементов, называемых closest
, что делает именно это. Он выбирает селектор CSS как параметр и находит ближайшего совпадающего предка, который может быть самим элементом. Все текущие версии настольных браузеров поддерживают его, но в целом он не готов к использованию. Следующая страница MDN содержит polyfill.
Ответ 3
Я не javascript geek, но чтобы ответить на ваш вопрос (только для любопытства), я провел некоторое время в Интернете, и через пару минут я понял, что вы можете инициировать событие на родительском элементе также так ( как альтернативная идея, может быть, я не уместен), чтобы обращаться с родителями щелкнувших элементов
var el=document.getElementsByTagName('ul')[0];
el.addEventListener('click',function(e){
var elm=e.target.parentNode;
if(document.createEvent)
{
evt = document.createEvent('MouseEvents');
evt.initMouseEvent("click", false, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
elm.dispatchEvent(evt);
liEventhandler(evt);
}
});
function liEventhandler(e)
{
console.log(e);
console.log(e.target);
console.log(e.which);
alert(e.target.innerHTML);
}
Пример здесь.
Выше пример не будет работать в IE использует createEventObject
и fireEvent
if(document.createEventObject)
{
var evt = document.createEventObject();
el.fireEvent('onclick', evt);
liEventhandler(evt);
}
а также e.target - window.event.srcElement и addEventListener
должно быть
el.attachEvent('onclick', function(){...})
Когда событие срабатывает в ul
, а цель - div
Я только что вызвал событие на li
Некоторые ссылки: 1. comp.lang.javascript 2. MOZILLA DEVELOPER NETWORK и 3. это.