Vanilla-lazyload: Infinite scroll and update new images

Created on 14 May 2019  路  4Comments  路  Source: verlok/vanilla-lazyload

Hello everyone

Describe the bug
I am using an infinite scroll pagination on my products list.
For example this page https://www.boutique-thalassotherapie.com/categorie-produit/spa/ has 5 parts. 46 products, 12 products per page.
When scrolling, lazyload doesn't load the last part images.

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://www.boutique-thalassotherapie.com/categorie-produit/spa/
  2. Scroll down to the bottom of the page
  3. See the last 10 images not loaded

Expected behavior
Images shoud load.
I have read the previous ticket with https://github.com/verlok/lazyload/issues/160 with @Tabrisrp author of WPRocket (WordPress cache plugin) which I am using on this website.
WPRocket does use window.addEventListener('LazyLoad::Initialized', function (e) { and MutationObserver and lazyLoadInstance.update(); that should load images loaded with ajax, like your suggested on this ticket.

LazyLoad version

  • Version 11.0.6

Desktop (please complete the following information):

  • OS: Windows 7
  • Browser: Chrome
  • Version: 75

Screenshots
56507900-1e697800-6523-11e9-81c3-9d5d3be8487d

Additional context
I tried to fix the issue by manipulating the JS part with update().
Setting a timeout made it work but it looks like an ugly fix. Maybe there is a better way to fix this issue.

setTimeout(function() { 
lazyLoadInstance.update();
}, 500); 

Thank you for your help

Question

Most helpful comment

Thanks for your tips, I managed to adapt the code (from WP Rocket original code).
It was checking if images tags were found in the DOM, but not if the new DOM was just a single img tag.

Another difference is that I update() only after all mutations have been parsed, to execute it just once.

Replaced the old code:

window.addEventListener('LazyLoad::Initialized', function (e) {
            var lazyLoadInstance = e.detail.instance;

            if (window.MutationObserver) {
                var observer = new MutationObserver(function(mutations) {
                    mutations.forEach(function(mutation) {
                        for (i = 0; i < mutation.addedNodes.length; i++) {
                            if (typeof mutation.addedNodes[i].getElementsByTagName !== 'function') {
                                return;
                            }

                           if (typeof mutation.addedNodes[i].getElementsByClassName !== 'function') {
                                return;
                            }

                            imgs = mutation.addedNodes[i].getElementsByTagName('img');
                            iframes = mutation.addedNodes[i].getElementsByTagName('iframe');
                            rocket_lazy = mutation.addedNodes[i].getElementsByClassName('rocket-lazyload');

                            if ( 0 === imgs.length && 0 === iframes.length && 0 === rocket_lazy.length ) {
                                return;
                            }

                            lazyLoadInstance.update();

                        }
                    } );
                } );

                var b      = document.getElementsByTagName("body")[0];
                var config = { childList: true, subtree: true };

                observer.observe(b, config);
            }
        }, false);

By this new code:

        window.addEventListener('LazyLoad::Initialized', function (e) {
            var lazyLoadInstance = e.detail.instance;

            if (window.MutationObserver) {
                var observer = new MutationObserver(function(mutations) {

                    image_count = 0;
                    iframe_count = 0;
                    rocketlazy_count = 0;

                    // Check all mutations
                    mutations.forEach(function(mutation) {

                        // Check all added nodes of the mutations
                        for (i = 0; i < mutation.addedNodes.length; i++) {
                            if (typeof mutation.addedNodes[i].getElementsByTagName !== 'function') {
                                return;
                            }

               if (typeof mutation.addedNodes[i].getElementsByClassName !== 'function') {
                return;
               }

               images = mutation.addedNodes[i].getElementsByTagName('img');
               is_image = mutation.addedNodes[i].tagName == "IMG";

                   iframes = mutation.addedNodes[i].getElementsByTagName('iframe');
               is_iframe = mutation.addedNodes[i].tagName == "IFRAME";

               rocket_lazy = mutation.addedNodes[i].getElementsByClassName('rocket-lazyload');

               image_count += images.length;
               iframe_count += iframes.length;
               rocketlazy_count += rocket_lazy.length;

               if(is_image){
                   image_count += 1;
               }
               if(is_iframe){
                   iframe_count += 1;
               }

                        }
                    } );

                    // After all mutations have been executed, check if any image, iframe was found in the added DOM 
                    if(image_count > 0 || iframe_count > 0 || rocketlazy_count > 0){
                        lazyLoadInstance.update();
                    }

                } );

                var b      = document.getElementsByTagName("body")[0];
                var config = { childList: true, subtree: true };

                observer.observe(b, config);
            }
        }, false);

So in the end the images are now loaded correctly on my page
https://www.boutique-thalassotherapie.com/categorie-produit/spa/

All 4 comments

Hi @nicomollet
Thank you for opening this.

The solution would be to call the update() method on your instance of LazyLoad, but this needs to be called _after_ the new DOM has been added.

If you have control over the JavaScript that appends new DOM, I鈥檇 suggest you to call update() in the JavaScript function that appends the new DOM to your page.

If you don鈥檛 have control over it, you could use MutationObserver to understand when new DOM was appended, but I鈥檇 suggest you to consider NOT to use LazyLoad at all, since you鈥檙e already lazily loading the HTML content and the maximum number of images that are being downloaded if the user doesn鈥檛 scroll down is 12.

You can find a demo in the demos folder called dynamic_content.html if I remember correctly. The demos are also listed in the README file, so check it out.

Let me know if you manage to solve... or if you don鈥檛!

Thanks for your tips, I managed to adapt the code (from WP Rocket original code).
It was checking if images tags were found in the DOM, but not if the new DOM was just a single img tag.

Another difference is that I update() only after all mutations have been parsed, to execute it just once.

Replaced the old code:

window.addEventListener('LazyLoad::Initialized', function (e) {
            var lazyLoadInstance = e.detail.instance;

            if (window.MutationObserver) {
                var observer = new MutationObserver(function(mutations) {
                    mutations.forEach(function(mutation) {
                        for (i = 0; i < mutation.addedNodes.length; i++) {
                            if (typeof mutation.addedNodes[i].getElementsByTagName !== 'function') {
                                return;
                            }

                           if (typeof mutation.addedNodes[i].getElementsByClassName !== 'function') {
                                return;
                            }

                            imgs = mutation.addedNodes[i].getElementsByTagName('img');
                            iframes = mutation.addedNodes[i].getElementsByTagName('iframe');
                            rocket_lazy = mutation.addedNodes[i].getElementsByClassName('rocket-lazyload');

                            if ( 0 === imgs.length && 0 === iframes.length && 0 === rocket_lazy.length ) {
                                return;
                            }

                            lazyLoadInstance.update();

                        }
                    } );
                } );

                var b      = document.getElementsByTagName("body")[0];
                var config = { childList: true, subtree: true };

                observer.observe(b, config);
            }
        }, false);

By this new code:

        window.addEventListener('LazyLoad::Initialized', function (e) {
            var lazyLoadInstance = e.detail.instance;

            if (window.MutationObserver) {
                var observer = new MutationObserver(function(mutations) {

                    image_count = 0;
                    iframe_count = 0;
                    rocketlazy_count = 0;

                    // Check all mutations
                    mutations.forEach(function(mutation) {

                        // Check all added nodes of the mutations
                        for (i = 0; i < mutation.addedNodes.length; i++) {
                            if (typeof mutation.addedNodes[i].getElementsByTagName !== 'function') {
                                return;
                            }

               if (typeof mutation.addedNodes[i].getElementsByClassName !== 'function') {
                return;
               }

               images = mutation.addedNodes[i].getElementsByTagName('img');
               is_image = mutation.addedNodes[i].tagName == "IMG";

                   iframes = mutation.addedNodes[i].getElementsByTagName('iframe');
               is_iframe = mutation.addedNodes[i].tagName == "IFRAME";

               rocket_lazy = mutation.addedNodes[i].getElementsByClassName('rocket-lazyload');

               image_count += images.length;
               iframe_count += iframes.length;
               rocketlazy_count += rocket_lazy.length;

               if(is_image){
                   image_count += 1;
               }
               if(is_iframe){
                   iframe_count += 1;
               }

                        }
                    } );

                    // After all mutations have been executed, check if any image, iframe was found in the added DOM 
                    if(image_count > 0 || iframe_count > 0 || rocketlazy_count > 0){
                        lazyLoadInstance.update();
                    }

                } );

                var b      = document.getElementsByTagName("body")[0];
                var config = { childList: true, subtree: true };

                observer.observe(b, config);
            }
        }, false);

So in the end the images are now loaded correctly on my page
https://www.boutique-thalassotherapie.com/categorie-produit/spa/

Yay! Good to hear that.
I鈥檓 glad you solved

Was this page helpful?
0 / 5 - 0 ratings

Related issues

isuke01 picture isuke01  路  3Comments

wzhscript picture wzhscript  路  8Comments

ghost picture ghost  路  8Comments

brycewray picture brycewray  路  5Comments

starfishpatkhoo picture starfishpatkhoo  路  6Comments