0

I have an intersectionObserver on a box that changes color when it comes into the viewport which all works fine.

I'm trying to apply this to multiple boxes though, and when I change the the getElementsById to querySelectorAll (line 13 of the JS) it doesn't play ball.

Does anyone know what I'm doing wrong here? I don't think the problem is with the intersectionObserver, I think it's with the selector. It's driving me mad.

Codepen: https://codepen.io/emilychews/pen/RMWRPZ

window.addEventListener("load", function(){

var iO = "IntersectionObserver" in window; /* true if supported */

if (iO) {
  const config = {
    root: null, // sets the framing element to the viewport
    rootMargin: '400px 0px 0px 0px',  // should remove the animation 400px after leaving the viewport
    threshold: .5
  };

  const box = document.getElementById('box1');
  // const box = document.querySelectorAll('.box');

  let observer = new IntersectionObserver(function(entries) {
    entries.forEach(function(item) {
      if (item.intersectionRatio > .5) {
        item.target.classList.add("active");
      } else {
        item.target.classList.remove("active");
      }
    });
  }, config);

  observer.observe(box);

} // end of if(iO)


}); // end of load event
body {
  font-family: arial;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 250vh;
}

.box {
  margin: 1rem;
  width: 100px;
  height: 100px;
  background: blue;
  opacity: 1;
  transition: .5s all;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
}

.active {
  background: red;
  opacity: 1;
}
<div id="box1" class="box">Box 1</div>
<div id="box2" class="box">Box 2</div>
Sphinx
  • 10,519
  • 2
  • 27
  • 45
pjk_ok
  • 618
  • 7
  • 35
  • 90
  • `".box"` is a selector for all elements with *class* "box", not id. You'll get back a node list, not a single element. You have to pass each element in the list separately to `.observe()`. – Pointy Mar 12 '18 at 17:14
  • Also you're setting the threshold to 0.5, so the callback will never be called when the visibility is smaller than that. – Pointy Mar 12 '18 at 17:18
  • That doesn't bother me and that isn't the issue @pointy – pjk_ok Mar 13 '18 at 01:45
  • Re: your 1st comment @Pointy i understand that, i just don't know how to do it. – pjk_ok Mar 13 '18 at 01:50

1 Answers1

3

querySelectorAll returns an array of nodes, getElementById returns a single dom object. observer.observe needs a dom object as a parameter, so a solution to that could be

const box = document.getElementsByClassName('box');
box.forEach(function(item){
    observer.observe(item);
});
Yuval Perelman
  • 4,499
  • 1
  • 22
  • 32
  • that won't work with the way intersection observer works? I need a way of storing all .box items in a variable i think? – pjk_ok Mar 13 '18 at 01:52
  • they are all stored in the const "box". The problem is that box is an array of dom objects, and the function expects a single dom object, that's why you have to iterate that array and register each one of the objects to the observer separately. If you want to store each object separately you can do something like var box0=box[0], box1=box[1], etc. but I don't see much sense in that. – Yuval Perelman Mar 13 '18 at 14:34
  • Thanks. There was a type in the above code `foreach` instead of `forEach` . Thanks for your help Yuval. Much appreciated – pjk_ok Mar 13 '18 at 16:40