'Running an if statement inside a querySelectorAll Node List

I am building a blog post layout which requires some metadata to sit on one side and stay in place as the content scrolls, using position: sticky.

This works fine but some types of content stretch to 100% width, so collide with the metadata as they scroll by. I am looking to run an event listener on scroll which compares the position of both and adds a class to the sticky element, giving it opacity:0 as the other passes over it.

This works fine when there is only one full width (.fw) element on the page:

window.addEventListener('scroll', function() {
var a = document.querySelector('.postmeta-sticky').getBoundingClientRect(),
    b = document.querySelector('.fw').getBoundingClientRect();
    if((b.top <= (a.top + a.height)) && ((b.top + b.height) > a.top)) {
        $(".postmeta-wrap").addClass("overlap");
    } else {
        $(".postmeta-wrap").removeClass("overlap");
    }
});

However, the post content is created dynamically and there may be more than one .fw per page. I am therefore trying to gather all instances using querySelectorAll for my second variable, but I cannot get this to work.

I am this far in:

window.addEventListener('scroll', function(){
  var a = document.querySelector(".postmeta-sticky").getBoundingClientRect(),
      objects = document.querySelectorAll(".fw");
  objects.forEach(function(object) {
    b = object.getBoundingClientRect();
    if ((b.top <= (a.top + a.height)) && ((b.top + b.height) > a.top)) {
      $(".postmeta-wrap").addClass("overlap");
    } else {
      $(".postmeta-wrap").removeClass("overlap");
    }
  });
});

But it just isn't working. Doubtless I have made some obvious error or omission.

First instance only working in situ: https://hba.matmartin.studio/henry-v-donmar-warehouse/

Simplified codepen: https://codepen.io/MMS_/pen/VwQvvpm

With thanks to anyone who can help.

jQuery(document).ready(function($) {
  window.addEventListener('scroll', function() {
    var a = document.querySelector(".sticky-content").getBoundingClientRect(),
      objects = document.querySelectorAll(".fw");
    objects.forEach(function(object) {
      b = object.getBoundingClientRect();
      if ((b.top <= (a.top + a.height)) && ((b.top + b.height) > a.top)) {
        $(".sticky-wrap").addClass("overlap");
      } else {
        $(".sticky-wrap").removeClass("overlap");
      }
    });
  });
});
.content {
  box-sizing: border-box;
  position: relative;
}

.sticky-wrap {
  position: absolute;
  height: 100%;
  width: 33%;
  z-index: 0;
}

.sticky-wrap.overlap {
  opacity: 0;
}

.sticky-content {
  position: sticky;
  top: 0;
  left: 0;
  width: 100%;
  height: 112px;
  padding: 24px 0;
  background: #e9e9e9;
}

.scrolling-content {
  width: 100%;
  position: relative;
  z-index: 1;
}

.scrolling-element {
  width: 66%;
  height: 160px;
  background: #d56d56;
  margin: 0 0 48px auto;
}

.scrolling-element.fw {
  width: 100%;
  background: #9dc9dc;
  opacity: 0.5;
}

.page-head {
  width: 100%;
  height: 72px;
  background: #F6F6F6;
}

.page-end {
  width: 100%;
  height: 480px;
  background: #383838;
}
<div class="page-head"></div>
<div class="content">
  <div class="sticky-wrap">
    <div class="sticky-content">
      <ul>
        <li>This info</li>
        <li>sticks around</li>
        <li>for a bit</li>
      </ul>
    </div>
  </div>
  <div class="scrolling-content">
    <div class="scrolling-element"></div>
    <div class="scrolling-element fw"></div>
    <div class="scrolling-element"></div>
    <div class="scrolling-element fw"></div>
    <div class="scrolling-element"></div>
    <div class="scrolling-element"></div>
  </div>
</div>
<div class="page-end"></div>

<script src="https://code.jquery.com/jquery-1.12.3.js" integrity="sha256-1XMpEtA4eKXNNpXcJ1pmMPs8JV+nwLdEqwiJeCQEkyc=" crossorigin="anonymous"></script>


Solution 1:[1]

The code below should achieve the behavior you're looking for. The problem was that the later .fw elements in the list were updating the visibility of the meta element.

I changed the loop to a for...of format and added a break to stop the loop when it is hidden, and did a bit of refactoring.

Hope this works!

window.addEventListener('scroll', function(){
    var sticky = document.querySelector(".sticky-content");
    var a = sticky.getBoundingClientRect();
    var objects = document.querySelectorAll(".fw");
    for (object of objects) {
      b = object.getBoundingClientRect();
      if ((b.top <= (a.top + a.height)) && ((b.top + b.height) > a.top)) {
        sticky.parentNode.classList.add("overlap");
        break;
      } else {
        sticky.parentNode.classList.remove("overlap");
      }
    }
  });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 misterjingles