Делегирование событий Javascript, обработка родителей щелкнутых элементов?

http://jsfiddle.net/walkerneo/QqkkA/

Я видел много вопросов здесь, спрашивая или отвечая на делегирование событий в javascript, но я еще не видел, однако, как использовать делегирование событий для элементов, которые не будут целями события click.

например:

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 элемента divs всегда будут целевыми элементами. Помимо проверки каждого родителя целевого элемента в функции click, как я могу это сделать?

edit:

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

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 для этого меня интересует как они это делают и как это можно сделать с помощью pure js.

3 ответов


вот один из способов решить это:

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. См. реализацию в рожь/события для более полного примера.

на Element.matches, Node.contains и Node.compareDocumentPosition методы могут помочь вам реализовать такие функции.


Я не 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.цель-окно.событие.srcElement и addEventListener должно быть

el.attachEvent('onclick', function(){...})

когда событие срабатывает на ul и цель div Я только что запустил событие на li

ссылки: 1. comp.ленг.в JavaScript 2.СЕТЬ РАЗРАБОТЧИКОВ MOZILLA и 3.этой.


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