Welcome to Code Forum!

Join a community that supports you and your coding journey from day one. We strive to be a friendly, supportive community that empowers everyone to be better developers. By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.

    GIF shows where to locate </> in the thread and or post editor toolbar.
    To learn more about how to use our BBCode feature, review our "How to post your code into threads" here.

    Thank you, Code Forum.

JavaScript Vanilla JavaScript Lazy Loading images & passing class to parent

TIBrent

New Coder
I have been tremendously struggling with a custom lazy load/parent class inheritance script I am trying to implement. I am trying to move away from jQuery to Vanilla JavaScript. I wrote a basic lazy load script which worked just fine, Codepen Link For That Here. I then began trying to expand upon that code so that the script searches the whole page for the data attribute “data-lazy-load” which is stored on a parent div which houses the child image I want lazy loaded, inside of it. At several points within the process I believed I had things fully working, but I ultimately realized that if the images weren’t all in the viewport on load, they would never return true for being on screen and would not get the class applied to them or the child doc within them loaded. I have had several iterations of this code, but where I am now doesn’t seem to do anything at all, and I am at a loss. The link to the Current Codepen Can Be Found Here. The full JavaScript is displayed below.
JavaScript:
(() => {
    const initLazyMask = () => {

        const lazyMaskLoader = () => {
            const lazyParents = document.querySelectorAll('[data-lazy-mask]');
            let delay = 0;

            lazyParents.forEach((parent, i) => {
                const img = parent.querySelector('img');
                function add_mask(e, c) {
                    m = document.createElement(e);
                    m.classList.add(c);
                    parent.appendChild(m) ;
                }
                
                if (isImgInViewport(img)) {
                    if (img.getAttribute('data-src') !== null) {
                        img.setAttribute('src', img.getAttribute('data-src'));
                        img.removeAttribute('data-src');
                    }
                    if (img.getAttribute('data-srcset') !== null) {
                        img.setAttribute('srcset', img.getAttribute('data-srcset'));
                        img.removeAttribute('data-srcset');
                    }
                    
                    setTimeout(() => {
                        parent.classList.add('data-lazy-shown');
                        img.classList.add('lazy-img-shown');
                        add_mask('div', 'cs-mask');
                    }, delay);

                    delay += 100; // Increment the delay for staggering
                }
            });

            // Remove event listeners if all images are loaded
Truly, any and all hope appreciated. For further clarification, I am not just using the loading=“lazy” attribute for the image loading because I do not know how to target the parent “data-lazy-mask” on completion of that load. And if it is specifically the “isImgInViewport()” function which is working incorrectly, I am not sure why in my first codepen link, shown at the beginning of the thread works just as expected but this one does not. Thank you in advance.
 
I am not just using the loading=“lazy” attribute for the image loading because I do not know how to target the parent “data-lazy-mask” on completion of that load.
I'm not sure if this will fix your issue, but you can use the JavaScript closest() method to select the closest parent element matching the selector.

Example:
JavaScript:
document.querySelectorAll("img[loading='lazy'").forEach(image => {  // select all lazy loading images
  image.addEventListener("load", () => {
    const parent = image.closest("[data-lazy-mask");  // select closest parent with the data-lazy-mask attribute
  });
});
 

Buy us a coffee!

Buy me a coffee.
Back
Top Bottom