skip to Main Content

I was practicing a lesson about modal windows from one video course and noticed one feature: I had an "onscroll" event running when I scrolled to the end of the page and after closing the modal window, this event refused to fire further, so at first I did not understand why the author was writing logic for a single trigger of this event.

That’s why it became interesting for me to figure this out. As I noticed, the page height is exactly 4264px. When the event is triggered for the first time, the condition "window.Scrollly + document.documentElement.clientHeight" gives us 4264px, but when triggered again, this value already equals 4263.8, which is not enough to fulfill the condition. As I understand it, this is due to the overflow change in the body element.

I decided to fix this and started rounding this value up, but I ran into another problem: now, when I reopen the modal window when scrolling to the bottom, it becomes impossible to close it at all.
When you click on the cross to close it, an inscription is displayed twice in the console that the scroll event was triggered and the condition was also satisfied, although overflow=hidden at this moment and I would not be able to trigger this event in any way anymore.
But if I write any character inside the tag located in the popup modal window, then I can safely close the modal window and it no longer pops up from this event until I scroll down the page again.
I also noticed that "set timer" type solutions don’t work and this event is triggered twice again.
Why is this happening?
code section: https://phpout.com/wp-content/uploads/2024/03/3q2mK.png

full project (the problem starts at 97th line in script.js): https://github.com/sevabek/tt/tree/main/%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F%20%D1%82%D0%B0%D0%B1%D0%BE%D0%B2

2

Answers


  1. Chosen as BEST ANSWER

    I found info that the problem occurs because when the end of the page is reached, scrollY may exceed the height of the document and the condition will be met not only once, but several times. To fix this, i added an additional variable that will track the execution status of the scroll event:

    let is Scrolled = false;
    
    window.addEventListener("scroll", (e) => {
      if (!isScrolled && Math.ceil(window.scrollY + document.documentElement.clientHeight) >= document.documentElement.scrollHeight) {
        console.log("scrolled down");
        openModal();
        is Scrolled = true;
      } else if (Math.ceil(window.scrollY + document.documentElement.clientHeight) < document.documentElement.scrollHeight) {
        is Scrolled = false;
      }
    });
    

  2. **try use this code **

        const modalTrigger = document.querySelectorAll("[data-modal]"),
        modal = document.querySelector(".modal"),
        modalCloseBtn = document.querySelector("[data-close]");
      
      let modalIsOpen = false;
      let modalTimerId;
      let scrollDebounceTimer;
      
      function openModal() {
        if (!modalIsOpen) {
          modal.classList.add("show");
          modal.classList.remove("hide");
          document.body.style.overflow = "hidden";
          clearInterval(modalTimerId);
          modalIsOpen = true;
        }
      }
      
      modalTrigger.forEach((item) => {
        item.addEventListener("click", () => {
          openModal();
        });
      });
      
      function closeModal() {
        if (modalIsOpen) {
          modal.classList.add("hide");
          modal.classList.remove("show");
          document.body.style.overflow = "scroll";
          modalIsOpen = false;
      
          // Introduce a small delay before checking the scroll position again
          clearTimeout(scrollDebounceTimer);
          scrollDebounceTimer = setTimeout(() => {
            if (
              Math.ceil(window.scrollY + document.documentElement.clientHeight) >=
              document.documentElement.scrollHeight
            ) {
              console.log("scrolled down");
              openModal();
            }
          }, 100);
        }
      }
      
      modalCloseBtn.addEventListener("click", () => {
        closeModal();
      });
      
      modal.addEventListener("click", (e) => {
        if (e.target === modal) {
          closeModal();
        }
      });
      
      document.addEventListener("keydown", (e) => {
        if (e.code === "Escape" && modal.classList.contains("show")) {
          closeModal();
        }
      });
      
      modalTimerId = setTimeout(openModal, 15_000);
      
      window.addEventListener("scroll", () => {
        // Debounce the scroll event
        clearTimeout(scrollDebounceTimer);
        scrollDebounceTimer = setTimeout(() => {
          if (
            Math.ceil(window.scrollY + document.documentElement.clientHeight) >=
            document.documentElement.scrollHeight
          ) {
            console.log("scrolled down");
            openModal();
          }
        }, 100);
      });
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search