1

I have simply an unordered list am trying to create with html5 and javascript, I want to add events to this list element eg first element.

Here is my HTML list:

<ul class="aside__list">
    <li class="one">Kutomba kuma</li>
    <li class="two">Kutomba tako</li>
    <li class="three">Kutomba mkundu</li>
    <li class="four">Kutomba malaya</li>
</ul>

JS:

var parentElements = document.getElementsByClassName('aside__list');
for (var i=0; i<parentElements.length; i++) {        
    parentElements[i].addEventListener('click', doStuff, false);
    console.log(parentElements[i]);
}

function doStuff() {
    alert('Delete me');
}
   

I want to add an event to the first element of my list using for loop without using a class or id, now this event applies to every list element in my list,

what do I need to change to get what I want?

1
  • Your code makes a classic performance mistake, not only by using .getElementsByClassName(), but by referencing the live node list returned by it inside of a loop. See this for an explanation. Commented Mar 2, 2019 at 23:43

3 Answers 3

4

You can use:

document.querySelector('ul.aside__list li').addEventListener('click', doStuff);

This matches the first li so you don't need to include :first-child.

Sign up to request clarification or add additional context in comments.

Comments

2

Add a listener to the li which is the first child of the list, instead of to every whole .aside__list:

document.querySelector('.aside__list li:first-child').addEventListener('click', doStuff);

function doStuff() {
  console.log('Delete me');
}
<ul class="aside__list">
  <li class="one">Kutomba kuma</li>
  <li class="two">Kutomba tako</li>
  <li class="three">Kutomba mkundu</li>
  <li class="four">Kutomba malaya</li>
</ul>

As comment notes, the :first-child psuedo-selector isn't necessary since querySelector will only return the first matching element, though it may make the code's intent a bit clearer.

1 Comment

Semi-related, :first-child shouldn't be necessary, as querySelector only matches a single element anyways.
2

This would work for any number of ul.aside__list:

[...document.querySelectorAll('.aside__list')].forEach(
  ul => ul.firstElementChild.addEventListener('click', doStuff)
);

function doStuff() {
  console.log('Delete me');
}
<ul class="aside__list">
  <li class="one">Kutomba kuma</li>
  <li class="two">Kutomba tako</li>
  <li class="three">Kutomba mkundu</li>
  <li class="four">Kutomba malaya</li>
</ul>
<ul class="aside__list">
  <li class="one">Kutomba kuma</li>
  <li class="two">Kutomba tako</li>
  <li class="three">Kutomba mkundu</li>
  <li class="four">Kutomba malaya</li>
</ul>
<ul class="aside__list">
  <li class="one">Kutomba kuma</li>
  <li class="two">Kutomba tako</li>
  <li class="three">Kutomba mkundu</li>
  <li class="four">Kutomba malaya</li>
</ul>

6 Comments

Why not just querySelectorAll('.aside__list li')? The end result is the same, and it avoids fetching the entire list.
@jhpratt Because that would select all list items inside each list.
Whoops, tack a :first-child on the end of that then.
Can you explain why did you choose to use foreach and not for loop as question suggest?
Because it's more readable, does not require an index variable and lets you access the iterated elements without using the clunky element[i] syntax.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.