1

I want to iterate through a class and display the corresponding text when I hover over each element.

HTML

<div class="box red"></div>

<div class="box green"></div>

<div class="box red"></div>

<div class="info">
Hi
</div>

<div class="info">
Hello
</div>

<div class="info">
Hey
</div>

CSS

.box {
  width:100px; 
  height:100px;
  border-radius: 10px;
}

.red{
  background-color: red;
}

.green{
  background-color: green;
}

.info {
  display: none;
}

Javascript

var box = document.getElementsByClassName("box");

for (var i = 0; i < box.length; i++) {
  box[i].onmouseover = function(){
    var info = document.getElementsByClassName("info");
    info[i].style.display= "block";
  }
}

for (var i = 0; i < box.length; i++) {
box[i].onmouseout = function(){
  var info = document.getElementsByClassName("info");
  info[i].style.display= "block";
  }
}

I get an error

Uncaught TypeError: Cannot read property 'style' of undefined"

It works if I set each <div> with an <id> then repeat my code over and over again. Why is it not working if I iterate?

https://jsfiddle.net/4q8jrt2m/2/

catzen
  • 51
  • 4
  • Each loop, `i` gain `1`. At the end of the third loop, `i` gain `1` so `i = 3`. Because of it, the code inside the loop are not executed avec the third. But it's to late, because when onmouseover is executed, i don't change or reset, so `i = 3` and that's why `info[i]` is undefined. – CrunchyArtie May 02 '21 at 15:17

2 Answers2

1

this worked for me:

var box = document.getElementsByClassName("box");
var info = document.getElementsByClassName("info")
for (var i = 0; i < box.length; i++) {
box[i].onmouseover = show(i);
box[i].onmouseout = hide(i);
}



function show(index){
return ()=>{info[index].style.display='block'
}}

function hide(index){
return ()=>{info[index].style.display='none'
}}
I3B
  • 108
  • 2
  • 6
  • 1
    How does this line work? ```return ()=>{info[index].style.display='none' }}``` Why can't I just write ```function hide(index){ info[index].style.display='none'; }``` – catzen May 02 '21 at 16:37
  • because we passed parameters with it, which would fire the function immediately without onmouseover event for example getting triggered. Look at this answer https://stackoverflow.com/a/29965761/14283533 to solve this we warp it into another function – I3B May 02 '21 at 16:54
0

A perfect candidate for event delagation I'd say. Something like:

document.addEventListener("mouseover", handle); 

function handle(evt) {
  if (evt.target.classList.contains("box")) {
    const hoveredColor = [...evt.target.classList][1];
    const info = document.querySelector(".info");
    info.dataset.hovered = hoveredColor;
    info.style.color = hoveredColor;
    return;
  }
}
.box {
  width:100px; 
  height:100px;
  border-radius: 10px;
}

.red{
  background-color: red;
}

.green{
  background-color: green;
}

.info {
  font-weight: bold;
  font-size: 2rem;
  margin-top: 2rem;
  position: fixed;
  left: 150px;
  top: 1rem;
}

.info:after {
  content: attr(data-hovered);
}
<div class="box red"></div>

<div class="box green"></div>

<div class="info"></div>
KooiInc
  • 119,216
  • 31
  • 141
  • 177