0

I am trying to add class for <li> elements on click event. If I click on the first element it should to get class "current-tab" and others <li> elements should not contain that class and etc. Here is some HTML code:

<nav class="interest-nav">
  <ul id="interest-ul">
     <li><a href="#box1">Fashion</a></li>
     <li><a href="#box2">Movies</a></li>
     <li><a href="#box3">TV</a></li>
  </ul>
</nav>

and Javascript code:

var navUl = document.getElementById('interest-ul').getElementsByTagName('li');
for (var y = 0; y < navUl.length; y++) {
    navUl[y].addEventListener('click', checkLi);
}

function checkLi() {
    if (navUl.className === '') {
        navUl.className = 'current-tab';
    } else {
        navUl.className = '';
    }
}

Thank you for your attention and for your help!

Angel Cuenca
  • 1,637
  • 6
  • 24
  • 46
  • 1
    `navUl` is an array and not a `HTMLElement` – Philipp Mar 07 '19 at 14:43
  • navUl.classList.add('current-tab'); https://www.w3schools.com/jsref/prop_element_classlist.asp also you may want to pass this into the checkLi event callback as navUl is an array – digital-pollution Mar 07 '19 at 14:44
  • With pure Javascript not jQuery... – Daniel Harrison Mar 07 '19 at 14:44
  • classList is pure javascript not jquery – digital-pollution Mar 07 '19 at 14:46
  • no, no, it was addressed to @Pete Nevermind :) – Daniel Harrison Mar 07 '19 at 14:47
  • @DanielHarrison both duplicates are pointing at pure js questions - what about both of those titles makes you think I am talking about jQuery? Any way, it is expected you do research before asking a question here - a simple search for your title brings back a whole host of solutions. Please try using a little more effort in future – Pete Mar 07 '19 at 14:48
  • @Pete ok, thanks by the way. I am a novice at programming. So sometimes I don't know how to syntactically correct write code. – Daniel Harrison Mar 07 '19 at 14:53
  • Ok, that's fine but you should state that in your question - you haven't actually said what's wrong with your code, you have just said you are trying to add a class to li elements - if your code is not working, then you should state what part of it is not working and give any error messages you may be receiving, or at the very least create a working snippet so we can see your code not working – Pete Mar 07 '19 at 14:56
  • @Pete ok, got it. Thanks for advice and for help! – Daniel Harrison Mar 07 '19 at 15:15

4 Answers4

7

You are trying to set the class on an array. You could simplify this script by adding an event listener to the list itself and then work with the event target.

var navUl = document.getElementById( 'interest-ul' );
navUl.addEventListener( 'click', checkLi );

function checkLi( event ) {
  // Just for testing... remove the following line:
  console.log( 'clicked on', event.target.tagName );
  // Only apply our actions if we really clicked on the link.
  if ( event.target.tagName === 'A' ) {
    navUl.querySelectorAll( 'li' ).forEach( el => el.classList.remove( 'current-tab' ) );
    event.target.parentNode.classList.add( 'current-tab' );
  }
}
.current-tab {
  font-weight: bold;
}
<nav class="interest-nav">
  <ul id="interest-ul">
    <li><a href="#box1">Fashion</a></li>
    <li><a href="#box2">Movies</a></li>
    <li><a href="#box3">TV</a></li>
  </ul>
</nav>
lumio
  • 7,428
  • 4
  • 40
  • 56
3

You can pass this to the function. Inside the function you can first remove the class from the all elements and add the class only to the current element.

Please Note: You can also use Document.querySelectorAll() which allows valid CSS selectors as parameters.

var navUl = [].slice.call(document.querySelectorAll('#interest-ul > li'));
for (var y = 0; y < navUl.length; y++) {
    navUl[y].addEventListener('click', function(){checkLi(this)});
}

function checkLi(current) {
  navUl.forEach(el => el.classList.remove('current-tab'));
  current.classList.add('current-tab');
}
.current-tab{
  background-color: lightgray;
}
<nav class="interest-nav">
   <ul id="interest-ul">
      <li><a href="#box1">Fashion</a></li>
      <li><a href="#box2">Movies</a></li>
      <li><a href="#box3">TV</a></li>
   </ul>
</nav>

You can also use Event.currentTarget:

var navUl = [].slice.call(document.querySelectorAll('#interest-ul > li'));
for (var y = 0; y < navUl.length; y++) {
  navUl[y].addEventListener('click', checkLi);
}

function checkLi(event) {
  navUl.forEach(el => el.classList.remove('current-tab'));
  event.currentTarget.classList.add('current-tab');
}
.current-tab{
  background-color: lightgray;
}
<nav class="interest-nav">
   <ul id="interest-ul">
      <li><a href="#box1">Fashion</a></li>
      <li><a href="#box2">Movies</a></li>
      <li><a href="#box3">TV</a></li>
   </ul>
</nav>
Mamun
  • 66,969
  • 9
  • 47
  • 59
3

var navUl = document.getElementById('interest-ul').getElementsByTagName('li');
for (var y = 0; y < navUl.length; y++) {
  navUl[y].addEventListener('click', checkLi);
}

function checkLi(ev) {
  document.querySelector('.current-tab').classList.remove('current-tab');

  ev.target.classList.add('current-tab');
}
.current-tab {
  color: red;
}
<nav class="interest-nav">
  <ul id="interest-ul">
    <li><a href="#box1" class="current-tab">Fashion</a></li>
    <li><a href="#box2">Movies</a></li>
    <li><a href="#box3">TV</a></li>
  </ul>
</nav>
Taki
  • 17,320
  • 4
  • 26
  • 47
1

In your code you are trying to set class to the whole collection (navUl.className = 'current-tab';). But you should iterate elements.

Second thing is about loops. Cache your length in variable before loop, it will be a bit faster.

var navUl = document.getElementById('interest-ul').getElementsByTagName('li');

for (var y = 0, l = navUl.length; y < l; y++) {
    navUl[y].addEventListener('click', checkLi);
}

function checkLi() {
    for (var y = 0, l = navUl.length; y < l; y++) {
        navUl[y].classList.remove('current-tab');
    }
    this.classList.add('current-tab');
}
Roman Meyer
  • 2,634
  • 2
  • 20
  • 27