document.querySelect arguments

2

I have the following sample code:

ul = document.getElementById("list");
li = document.querySelector("#list li");
cuerpo = document.body;

ul.addEventListener("click", function(event) {
  console.log("Clicked on ul");
});

li.addEventListener("click", function(event) {
  console.log("Clicked on li");
});
<ul id="list">
  <li>one</li>
  <li>two</li>
  <li>three</li>
</ul>

That I'm using it to understand the Event Propagation process. As it is bubbling by default, it should show the console.log message ("Clicked on li"); and then that of ul. But it does not, it only shows that of ul.

If I do the same with other HTML elements, the propagation works correctly. So for me the problem is in the document.querySelector argument. The information from MDN or from W3C itself made me very complex. So I would appreciate it if you could tell me if "#list li" is a valid argument and if not, in what way I could achieve what I set out to do.

EDIT: I've noticed that only the first li responds to the event.

    
asked by Federico Grandon Soporsky 18.05.2017 в 18:30
source

3 answers

2

What happens is that the querySelector will return a single object, to do what you want you should use querySelectorAll that returns an array with all objects li , inside #list , then you should cycle through them with one cycle for and assign a listener to each one, that is, you should change your code to this:

var ul = document.getElementById("list");
var li = document.querySelectorAll("#list li");
var cuerpo = document.body;

ul.addEventListener("click", function(event) {
  console.log("Clicked on ul");
});

for (var i = 0; i < li.length; i++) {
  li[i].addEventListener("click", function(event) {
    console.log("Clicked on li");
  });
}
<ul id="list">
  <li>one</li>
  <li>two</li>
  <li>three</li>
</ul>
    
answered by 18.05.2017 / 19:14
source
1

This occurs because document.querySelector only returns the first element that matches the specified selector. To get all the li within ul you should use document.querySelectorAll that returns a nodeList of elements, then that nodeList is covered with a forEach and each li we assign a listener.

var ul = document.getElementById("list");
var li = document.querySelectorAll("#list li");
var cuerpo = document.body;

ul.addEventListener("click", function(event){
  console.log("Clicked on ul");
});

Array.prototype.forEach.call(li, function(el) {
  el.addEventListener('click', function (event) {
    console.log('Clicked on li');
   });
});
<ul id="list">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>
    
answered by 18.05.2017 в 19:37
1

With querySelector() you get the first element of a given class, as I understand you want all the elements of the class, for that you must use querySelectorAll() .

Example:

ul = document.getElementById("list");
li = document.querySelectorAll("#list li"); // Todos los Elementos
cuerpo = document.body;

ul.addEventListener("click", function(event) {
  console.log("Clicked on ul");
});

for (i = 0; i < li.length; i++) {
  li.item(i).addEventListener("click", function(event) {
    console.log("Clicked on li");
  });
}
<ul id="list">
  <li>one</li>
  <li>two</li>
  <li>three</li>
</ul>

If you want the onClick event not to propagate from child to parent, you can stop it with the event.stopPropagation () method.

Example:

ul = document.getElementById("list");
li = document.querySelectorAll("#list li"); // Todos los Elementos
cuerpo = document.body;

ul.addEventListener("click", function(event) {
  console.log("Clicked on ul");
});

for (i = 0; i < li.length; i++) {
  li.item(i).addEventListener("click", function(event) {
    console.log("Clicked on li");
    event.stopPropagation();
  });
}
<ul id="list">
  <li>one</li>
  <li>two</li>
  <li>three</li>
</ul>
    
answered by 18.05.2017 в 21:14