yasser Eltibili
yasser Eltibili

Reputation: 134

Select all elements with same class by the selector getElementByClassName not working as expected

I want to select all elements with same class by the selector getElementByClassName but not working

I tried first without loop but it does not work

The selector className is not working and I tried query selector all and also is not working

getElementById the only selector that works with me but it only selects the first div

var front = document.getElementsByClassName('face');
var back = document.getElementsByClassName('tail');

for (var i = 0; i < front.length; i++) {
  front.onmouseenter = function() {
    front.style.display = 'none';
    back.style.display = 'block';
  };
}

for (var i = 0; i < front.length; i++) {
  front.onmouseleave = function() {
    front.style.display = 'block';
    back.style.display = 'none';
  };

}
<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

Upvotes: 0

Views: 75

Answers (3)

mplungjan
mplungjan

Reputation: 178094

Your code needed a front[i].onmouseenter = function() { since you need to address them using an index

That was however not the full story. You can can use the elementSibling to get the back when hovering the front

I use querySelectorAll here, which is why I for older browsers need to wrap in a [... ] to make it iterable. For newer browsers, you can use forEach on the collection

You may want to reconsider your code since it gives a very ugly twitching when the leave is triggered when you hide

Actually the code here is not doing exactly what you want. You need to explain what the display looks like. I would think we need to CSS the coins to take the same space using some kind of position...

I would then delegate (but then need to use over and out, since enter and leave cannot be used in delegation):

const hoverIt = e => {
  const tgt = e.target;
  const face = tgt.matches(".face")
  const tail = tgt.matches(".tail")
  if (!face && !tail) return; // not a coin
  tgt.classList.toggle("hide", e.type === "mouseover");
  tgt[face ? "nextElementSibling" : "previousElementSibling"].classList.toggle("hide", e.type !== "mouseover");
};

document.getElementById("coinDiv").addEventListener("mouseover", hoverIt);
document.getElementById("coinDiv").addEventListener("mouseout", hoverIt)

or similar.

Older snippet.

[...document.querySelectorAll('.face')].forEach(function(front) {
  front.onmouseenter = function() {
    this.style.display = 'none';
    this.nextElementSibling.style.display = 'block';
  }
  front.onmouseleave = function() {
    this.style.display = 'block';
    this.nextElementSibling.style.display = 'block';
  }
})
<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

Upvotes: 2

symlink
symlink

Reputation: 12209

document.getElementsByClassName returns an HTMLCollection: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName

In your for loop, you need to select each item in that collection before you update the styles. In this case, the let vars inside the loop are assigning the _front and _back vars to each item:

const front = document.getElementsByClassName('face');
const back = document.getElementsByClassName('tail');

for (var i = 0; i < front.length; i++) {
  let _front = front[i];
  let _back = back[i];
  
  _front.onmouseenter = function() {
    _front.style.display = 'none';
    _back.style.display = 'block';
  };
  
  _front.onmouseleave = function() {
    _front.style.display = 'block';
    _back.style.display = 'none';
  };

}
<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

Upvotes: 0

Ahmed Gaafer
Ahmed Gaafer

Reputation: 1661

What you want to use is querySelectorAll

var front = document.querySelectorAll('.face');
var back = document.querySelectorAll('.tail');

front.forEach(f => {
  f.addEventListener("mouseenter", () => {
      console.log("I am a head")
    /*your code here*/
  })
})

back.forEach(b => {
  b.addEventListener("mouseenter", () => {
        console.log("I am a tail")

    /*your code here*/
  })
})
<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

<div id="face" class="face">I am the head</div>
<div id="tail" class="tail">I am the tail</div>

Upvotes: 0

Related Questions