0

I'm trying to add a class 'is-visible' to all elements of a class 'module' using IntersectionObserver when they come into view on scrolling. I get the error:

IntersectionObserver.observe: Argument 1 does not implement interface Element.

Javascript:

let modules = document.getElementsByClassName("module");

const observer = new IntersectionObserver(
  ([e]) => {
    let modules = document.getElementsByClassName("module");
    modules.forEach((entry) => {
      entry.classList.toggle("is-visible", e.intersectionRatio < 1);
    });
  },
  { threshold: [0, 0.25, 0.5, 0.75, 1] }
);

window.addEventListener(
  "load",
  (event) => {
    observer.observe(modules);
  },
  false
);

HTML

<div id="wrapper">
  <div id="hero">
    <h1>This is my hero</h1>
  </div>
  <div id='strip'>
    <div id='s1'>Option 1</div>
    <div id='s2'>Option 2</div>
    <div id='s3'>Option 3</div>
    <div id='s4'>Option 4</div>
  </div>
  <div id="box" class="module fade-in-section">
    <h2>Contact us</h2>
    <img src="https://picsum.photos/300/100" />
  </div>

  <div class="module fade-in-section">
    <h2>What we do</h2>
    <img src="https://picsum.photos/300/100" />
  </div>

  <div class="module fade-in-section">
    <h2>Who we are</h2>
    <img src="https://picsum.photos/300/100" />
  </div>

  <div class="module fade-in-section">
    <h2>Mission</h2>
    <img src="https://picsum.photos/300/100" />
  </div>

  <div class="module fade-in-section">
    <h2>About us</h2>
    <img src="https://picsum.photos/300/100" />
  </div>

  <div class="module fade-in-section">
    <h2>Services</h2>
    <img src="https://picsum.photos/300/100" />
  </div>

  <div class="module fade-in-section">
    <h2>Processes</h2>
    <img src="https://picsum.photos/300/100" />
  </div>

</div>

Here's a codepen:

https://codepen.io/m-herda/pen/BazpzZM

UPDATE: Apart from the explanation to my problem that was mentioned in the comments/answers, it looks like a lot of the code above was not necessary. The code below works fine and is much simpler.

const modules = document.querySelectorAll(".module");

function handleIntersection(entries) {
  entries.map((entry) => {
    if (entry.isIntersecting) {
      entry.target.classList.add("is-visible");
    } else {
      entry.target.classList.remove("is-visible");
    }
  });
}

window.addEventListener("load", (event) => {
  const observer = new IntersectionObserver(handleIntersection);
  modules.forEach((m) => observer.observe(m));
});
Wasteland
  • 4,889
  • 14
  • 45
  • 91
  • 1
    The `observe` method takes in a single element, not an array of elements. You'd have to loop over the `modules` and observe every single one. – Emiel Zuurbier Oct 23 '20 at 18:43

2 Answers2

4

The error you get is:

IntersectionObserver.observe: Argument 1 does not implement interface Element.

This clearly states that the first argument of the function IntersectionObserver.observe needs to be an element. Read the documentation of it.

In your code, you are calling .observe with a collection of elements.

The solution is to call it on each element you want to observe separately.

assembly_wizard
  • 2,034
  • 1
  • 17
  • 10
0

Instead of using getElementsByClassName("module"); to select your class use querySelector(".module"); or querySelectorAll(".module"); when selecting the observed element.

JStw
  • 1,155
  • 11
  • 20
Ebenezer
  • 11
  • 2