javascriptclickloadingintersection-observer

Intersection Observer not acknowledging new items added on click


I have a group of items that I'm running an animation on. After clicking on a button, more items are added with the same class. These items are being added in groups of 4.

At first intersection observer ignores the new items, but if I click the button again, they work.

The funny thing is, my code works as intended in my example here, BUT not on the page I'm working on which uses the same basic structure, and that exact JS for that part (link removed).

Any ideas on what the issue on that page could be?

const options = {
    threshold: 0.6
};

const sectionObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            entry.target.classList.add('enter');
            observer.unobserve(entry.target);
        }
    });
}, options);

// Convert NodeList to an array
let reveal = Array.from(document.querySelectorAll('.post-list-card'));

// Initial observation for existing items
reveal.forEach(section => {
    sectionObserver.observe(section);
});

// Update reveal with all .post-list-card items
function updateReveal() {
    const updatedSections = document.querySelectorAll('.post-list-card');
    reveal = Array.from(updatedSections); // Update the reveal array
    reveal.forEach(newSection => {
            sectionObserver.observe(newSection); // Observe new items
    });
}

const loadMore = document.querySelector('.post-list .fusion-load-more-button');
loadMore.addEventListener('click', updateReveal);

/* this is not part of the code. added just for demonstration purposes */
function addNewCards() {
            const contentDiv = document.querySelector('.content');
            for (let i = 0; i < 4; i++) {
                const newCard = document.createElement('div');
                newCard.classList.add('post-list-card');
                newCard.textContent = 'New Card'; // You can customize the content here
                contentDiv.appendChild(newCard);
            }
        }
.post-list-card{
  width: 100%;
  height: 50px;
  margin: 50px 0;
  padding: 50px;
  background: blue;
  color: yellow;
}

.post-list-card.enter{
  background: red;
  color: #fff;
}
<div class="post-list">
  <div class="content">
    <div class="post-list-card">Card</div>
    <div class="post-list-card">Card</div>
    <div class="post-list-card">Card</div>
    <div class="post-list-card">Card</div>
   </div>
   <button class="fusion-load-more-button" onclick="addNewCards()">Load More</button>
</div>

EDIT: Found a solution. Added it as an answer.


Solution

  • I figured it out. The issue was the script was running before the loading js was. I couldn't change the order of the code in the theme, so I added a delay when the code is run on click.

    // Update reveal with all .post-list-card items
    function updateReveal() {
        setTimeout(function() {
          const updatedSections = document.querySelectorAll(".post-list-card");
          reveal = Array.from(updatedSections); // Update the reveal array
          reveal.forEach((newSection) => {
              sectionObserver.observe(newSection); // Observe new items
          });
      },800);
    }
    

    UPDATE:

    This solution still was showing problems for some reason, so I looked up solutions to check for DOM changes instead, and found Mutation Observer. This also ended up working.

    //mutation observer
    const observer = new MutationObserver(updateReveal);
    observer.observe(document.body, { childList: true, subtree: true });
    
    function updateReveal(mutations) {
        for (const { addedNodes } of mutations) {
            for (const node of addedNodes) {
                if (node.tagName && node.classList.contains("post-list-card")) {
                    const updatedSections = document.querySelectorAll(".post-list-card");
                    reveal = Array.from(updatedSections); // Update the reveal array
                    reveal.forEach((newSection) => {
                        sectionObserver.observe(newSection); // Observe new items
                    });
                  console.log('more cards loaded');
                }
            }
        }
    }
    
    const loadMore = document.querySelector(".post-list .fusion-load-more-button");
    loadMore.addEventListener("click", () => {
        updateReveal([{ addedNodes: [document.body] }]);
    });