Запуск оператора if внутри списка узлов querySelectorAll

Я создаю макет сообщения в блоге, который требует, чтобы некоторые метаданные располагались с одной стороны и оставались на месте при прокрутке контента, используя position: sticky.

Это работает нормально, но некоторые типы контента растягиваются до ширины 100%, поэтому сталкиваются с метаданными при прокрутке. Я хочу запустить прослушиватель событий в прокрутке, который сравнивает положение обоих и добавляет класс к липкому элементу, давая ему opacity:0, когда другой проходит над ним.

Это прекрасно работает, когда на странице есть только один элемент полной ширины (.fw):

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");
    }
});

Однако контент поста создается динамически, и на странице может быть более одного .fw. Поэтому я пытаюсь собрать все экземпляры, используя querySelectorAll для моей второй переменной, но не могу заставить это работать.

Я так далеко в:

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");
    }
  });
});

Но это просто не работает. Несомненно, я сделал очевидную ошибку или упущение.

Первый экземпляр работает только на месте: https://hba.matmartin.studio/henry-v-donmar-warehouse/

Упрощенный код: https://codepen.io/MMS_/pen/VwQvvpm

С благодарностью всем, кто может помочь.

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>

Не по теме: почему вы отбрасываете кусочки jQuery в то, что в основном представляет собой простой блок кода JavaScript? Это не нужно и путает вещи. См. youmightnotneedjquery.com.

isherwood 05.05.2022 17:42

Это отличный вопрос. Ответ в том, что это предел моих знаний, и я не знаю ничего лучшего. Я очень открыт для любых предложений по улучшению.

mtm 05.05.2022 17:45

Каждый раз в цикле вы добавляете или удаляете класс overlap из одних и тех же элементов. Таким образом, окончательный результат будет только от последней итерации цикла. Может быть, вы имели в виду $(object).find(".postmeta-wrap"), чтобы он менял только класс чего-то в текущем элементе .fw?

Barmar 05.05.2022 17:46

ох – спасибо @Barmar. куда бы я вставил это, точно?

mtm 05.05.2022 17:47

Вместо $(".postmeta-wrap"). Разве вы не понимаете, что это выбирает элементы все с классом, а не что-либо, связанное с итерацией?

Barmar 05.05.2022 17:48

Я думаю, что мы сталкиваемся с тем фактом, что я этого не понимаю, как указал @isherwood. Я только что обновил codepen, как вы предлагаете, но без желаемого эффекта.

mtm 05.05.2022 17:51

Я думаю, что Бармар что-то задумал. Я продолжу свой комментарий, указав на некоторые вещи, которые могут помочь: 1) вам не нужна функция document.ready вокруг вашей функции прокрутки. По сути, они делают то же самое здесь. 2) Вы используете древнюю версию jQuery. Скорее всего, вы сможете без проблем обновиться до версии 3.x.

isherwood 05.05.2022 17:51

спасибо — обе эти вещи теперь настраиваются в codepen, и, как вы подозревали, все осталось по-прежнему. я начинаю понимать точку зрения Бармара, но, если я не ошибаюсь, чтобы это редактирование сработало, целевой элемент должен быть внутри $object, верно? что это не так. на странице есть только один экземпляр цели.

mtm 05.05.2022 17:57
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
8
26
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Код ниже должен обеспечить поведение, которое вы ищете. Проблема заключалась в том, что более поздние элементы .fw в списке обновляли видимость метаэлемента.

Я изменил цикл на формат for...of и добавил разрыв, чтобы остановить цикл, когда он скрыт, и сделал небольшой рефакторинг.

Надеюсь, это сработает!

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");
      }
    }
  });

Другие вопросы по теме