JS how to simplify

Basicly if I hover over a list item, I want to add a class to the corresponding span.
Now I’ve found how to do this with the following code.

My question: Is there a way to simplify this (without repeating)? If so, how exactly?

  var listItems = document.querySelectorAll(".hover");
  var spanClass = document.querySelectorAll(".navbar-top-border");


  listItems[0].addEventListener("mouseover", event => {
    spanClass[0].classList.add("navbar-top-border-visible");
  });
  listItems[0].addEventListener("mouseout", event => {
    spanClass[0].classList.remove("navbar-top-border-visible");
  });

  listItems[1].addEventListener("mouseover", event => {
    spanClass[1].classList.add("navbar-top-border-visible");
  });
  listItems[1].addEventListener("mouseout", event => {
    spanClass[1].classList.remove("navbar-top-border-visible");
  });

3 thoughts on “JS how to simplify”

  1. var listItems = document.querySelectorAll(".hover");
    var spanClass = document.querySelectorAll(".navbar-top-border");
    
    listItems.map(function(element) {
        element.addEventListener("mouseover", event => {
            spanClass.map(function(spanElement) {
                spanElement.classList.add("navbar-top-border-visible");
            });
        });
    
        element.addEventListener("mouseout", event => {
            spanClass.map(function(spanElement) {
                spanElement.classList.remove("navbar-top-border-visible");
            });
    
        });
    });
    

    You can loop through the items instead of using item indexes.

    Reply
  2. Yes. Instead of biding each element to essentially the same event listeners, use "event delegation" where you bind the handler(s) to a common ancestor of the elements that need to use the callbacks. The event will originate at some element and then bubble up to the ancestor where it is handled. When it’s handled, you can determine where it originated with event.target and then act accordingly.

    Then, in your handler, if you need to access another element, use a DOM property to find that element in relation to the event.target (there are many possibilities to do this: closest, nextElementSibling, previousElementSibling, parent, etc.).

    This way, you only set up handlers one time, which is less coding and less memory used by the various elements and no loops or indexes are needed. It’s also highly scalable as adding/removing DOM elements (either manually or dynamically) won’t require any changes to the handler configurations.

    Also, don’t use .getElementsByClassName(), especially in connection with loops.

    Here’s an example:

    // set up the event handler on a common ancestor
    document.addEventListener("mouseover", foo1);
    document.addEventListener("mouseout", foo2);
    
    function foo1(event){
      // Test whether the event originated at
      // an element you care about
      if(event.target.classList.contains("foo")){
         console.log("You moused over me!");
         
         // You can access other elements without indexes
         // Just use a relational way of locating them
         event.target.nextElementSibling.classList.add("bar");
      }
    }
    
    function foo2(event){
      // Test whether the event originated at
      // an element you care about
      if(event.target.classList.contains("foo")){
         console.log("You moused out!");
         // You can access other elements without indexes
         // Just use a relational way of locating them
         event.target.nextElementSibling.classList.remove("bar");
      }
    }
    .foo { color:blue; text-decoration:underline; cursor:pointer; }
    .bar { background-color:yellow; }
    <span class="foo">Some element</span>
    <span>Some element</span>
    <span class="foo">Some element</span>
    <span>Some element</span>
    Reply
  3. And how but this in case you really need only 0 and 1 as indexes, witch rest of the answers don’t cover.

    var listItems = document.querySelectorAll(".hover");
    var spanClass = document.querySelectorAll(".navbar-top-border");
    
    let indxeses = [0, 1]
    
    indxeses.forEach(el => {
      listItems[el].addEventListener("mouseover", event => {
        spanClass[el].classList.add("navbar-top-border-visible");
      });
      listItems[el].addEventListener("mouseout", event => {
        spanClass[el].classList.remove("navbar-top-border-visible");
      });
    })
    
    Reply

Leave a Comment