Delegação de eventos Javascript, lidar com os pais de elementos clicados?

Http://jsfiddle.net/walkerneo/QqkkA/

já vi muitas perguntas aqui a fazer ou a ser respondidas com a delegação de eventos em javascript, mas ainda não vi como usar a delegação de eventos para elementos que não vão ser os alvos do evento click.

por exemplo:

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;
}
​
E se eu quiser adicionar um evento click para lidar com os elementos li quando forem clicados? Se eu anexar um manipulador de eventos para o elemento ul, Os div S serão sempre os elementos alvo. Além de verificar todos os pais do elemento alvo em uma função de clique, Como posso realizar isso?

editar:

quero usar a delegação de eventos em vez de:

var lis = document.getElementsByTagName('li');
for(var i=0;i<lis.length;i++){
    lis[i].onclick = function(){};
}

mas se o fizer:

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: não estou interessado em como usar bibliotecas Javascript para este {[[30]}, Estou interessado em como eles fazem isso e como isso pode ser feito com js puro.

Author: mowwwalker, 2012-03-28

3 answers

Eis uma maneira de resolver isto:
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)

Isto é demasiado simplificado, o laço vai continuar até a árvore, mesmo depois do elemento UL. Ver a aplicação em rye / events para um exemplo mais completo.

A Element.matches, Node.contains e Node.compareDocumentPosition Os métodos podem ajudá-lo a implementar este tipo de recursos.

 15
Author: Ricardo Tomasi, 2016-12-01 19:50:17

Eu não sou um javascript geek, mas para responder a sua pergunta (só por curiosidade) eu passei algum tempo on-line e depois de alguns minutos eu descobri que você pode disparar um evento no elemento pai também como esta (como uma alternativa ideia, pode ser que eu não estou apropriado) para lidar com os pais de clicaram em elementos

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

Um exemplo é aqui.

O exemplo acima não funciona em IE usa createEventObject e fireEvent

if(document.createEventObject)
{
    var evt = document.createEventObject();
    el.fireEvent('onclick', evt);
    liEventhandler(evt);
}

E também E. O alvo é janela.evento.srcElement e addEventListener devem ser

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

Quando o evento dispara em ul e o alvo é div acabo de despoletar um evento em li

Algumas referências: 1.comp.idioma.javascript 2.MOZILLA DEVELOPER NETWORK e 3.isto.

 0
Author: The Alpha, 2012-03-28 22:42:41
Há agora um método para os elementos chamados closest, o que faz exactamente isto. Ele toma um seletor CSS como parâmetro e encontra o ancestral mais próximo, que pode ser o próprio elemento. Todas as versões atuais dos navegadores de desktop suportam it, mas em geral não está pronto para uso de produção. A página MDN acima ligada contém um polifill.
 0
Author: Ignavia, 2017-05-16 16:51:43