Делегирование событий 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;
}
​

Что, если я хочу добавить событие щелчка для обработки элементов li при нажатии на них? Если я прикреплю обработчик событий к элементу ul, divs всегда будут целевыми элементами. Помимо проверки каждого родителя целевого элемента в функции щелчка, как я могу это сделать?

редактировать:

Я хочу использовать делегирование событий вместо:

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);

РЕДАКТИРОВАТЬ: Меня не интересует, как использовать библиотеки Javascript для этого, меня интересует, как они это делают и как это можно сделать с помощью чистого js.


person mowwwalker    schedule 28.03.2012    source источник
comment
На самом деле запутался в вашем вопросе, не понял, чего вы хотите достичь.   -  person The Alpha    schedule 28.03.2012
comment
Я всегда ошибаюсь в этом... эта ссылка может помочь: quirksmode.org/js/events_order .html   -  person Jeffrey Sweeney    schedule 29.03.2012
comment
@Michal, это казалось неэффективным, мне было интересно, единственный ли это способ.   -  person mowwwalker    schedule 29.03.2012


Ответы (2)


Вот один из способов решения:

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 могут помочь вам реализовать этот тип функций.

person Ricardo Tomasi    schedule 28.03.2012
comment
Я немного покопался в jQuery и вот что нашел. - person mowwwalker; 29.03.2012
comment
Спасибо :) Это то, что мне нужно. - person Frank Fang; 24.03.2017

Теперь для элементов существует метод closest, который делает именно это. Он принимает селектор CSS в качестве параметра и находит ближайшего подходящего предка, которым может быть сам элемент. Все текущие версии настольных браузеров поддерживают его, но в целом он не готов к использованию в рабочей среде. Страница MDN, указанная выше, содержит полифилл.

person Ignavia    schedule 16.05.2017
comment
Идеальный! Это именно то, что мне нужно. Спасибо - person rom5jp; 12.08.2020