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.). Or, in your case, you can dynamically get the index of the moused over list item and act upon the span with that same index.
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 hard-coded 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:
// These collections will be used later to match up indexes
// but no looping or hard coding of indexes will be required.
var listItems = Array.from(document.querySelectorAll(".hover"));
var spanClass = document.querySelectorAll(".navbar-top-border");
// 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("hover")){
// Find the span with the same index as the list item
// and add the desired class
spanClass[listItems.indexOf(event.target)].classList.add("navbar-top-border-visible");
}
}
function foo2(event){
// Test whether the event originated at
// an element you care about
if(event.target.classList.contains("hover")){
// Find the span with the same index as the list item
// and remove the desired class
spanClass[listItems.indexOf(event.target)].classList.remove("navbar-top-border-visible");
}
}
.hover { color:blue; text-decoration:underline; cursor:pointer; }
.navbar-top-border { display:none; }
.navbar-top-border-visible { display:inline; }
<ul>
<li class="hover">Item</li>
<li class="hover">Item</li>
<li class="hover">Item</li>
<li class="hover">Item</li>
</ul>
<span class="navbar-top-border">Item 1</span>
<span class="navbar-top-border">Item 2</span>
<span class="navbar-top-border">Item 3</span>
<span class="navbar-top-border">Item 4</span>