JQuery custom scrollbar and lazy load

I have a container with a custom jQuery content scroller custom content scroller : This code:

(function($){ $(window).load(function(){ $(".content").mCustomScrollbar({ scrollButtons: { enable: true }, mouseWheelPixels: 250 }); }); })(jQuery); 

And I would like to use it with Lazy Load:

 $(function() { $("img.lazy").lazyload({ effect : "fadeIn", container: $(".content") }); }); 

I think it should work with the callbacks function from the Scroller page, but I am not very good at jquery, so my results were unsuccessful.

When I use my code as shown below, it loads all the images when the page loads:

 $(function() { $("img.lazy").lazyload({ effect : "fadeIn", container: $(".mCSB_container") }); }); 

Authorization says that this can be done by writing a simple js function and name it whileScrolling .

Thanks for any help.

+6
source share
4 answers

Your attempt to use container does not work, because mCustomScrollbar does not use scrollable containers, but relative positioning in the overflow: hidden container to achieve scrolling. The cleanest approach I can come up with is to use a custom [event to trigger lazyload] [1]. Here is how I would do it for the example file given by Hassan Gursoi:

 <script> $(document).ready(function () { var filledHeight = 250; $(window).load(function () { $(".scroll").height($(window).height() - filledHeight); $(".scroll").mCustomScrollbar({ scrollButtons: { enable: true }, mouseWheelPixels: 250, callbacks: { whileScrolling: function() { var scroller = $(".mCSB_container"); var scrollerBox = scroller.closest(".mCustomScrollBox"); $(".scroll img.lazy").filter(function() { var $this = $(this); if($this.attr("src") == $this.data("src")) return false; var scrollerTop = scroller.position().top; var scrollerHeight = scrollerBox.height(); var offset = $this.closest("div").position(); return (offset.top < scrollerHeight - scrollerTop); }).trigger("lazyScroll"); }}}); $("img.lazy").lazyload({ event: "lazyScroll" }); }); }); </script> 

I also use the whileScrolling , but only to check which of the img.lazy images are visible. They refer to the fact that their relative position in the container does not exceed the height of the container minus the CSS top property. (Assuming you always scroll the top β†’ down, this setting will not recognize images that are invisible because you scroll too far down.) For these images, the function then fires the custom lazyScroll event, which is the event that lazyload uses to fire Download images.

Note that this solution is not yet very portable: you will need to replace the queries for .mCSB_container and .mCustomScrollBox those that have selected the items associated with the current scroll box for the script to work in situations with more than one mCustomScrollbar . In a real scenario, I would also cache jQuery objects, rather than recreate them every time the callback is called.

+5
source

I think that the author meant to additionally connect to the whileScrolling event as follows:

 (function($){ $(window).load(function(){ $("#content_1").mCustomScrollbar({ scrollButtons:{ enable:true }, callbacks:{ whileScrolling:function(){ WhileScrolling(); } } }); function WhileScrolling(){ $("img.lazy").lazyload(); } }); })(jQuery); 

where the HTML container is as follows:

 <div id="content_1" class="content"> <p>Lorem ipsum dolor sit amet. Aliquam erat volutpat. Maecenas non tortor nulla, non malesuada velit.</p> <p> <img class="lazy img-responsive" data-original="/img/bmw_m1_hood.jpg" width="765" height="574" alt="BMW M1 Hood"><br/> <img class="lazy img-responsive" data-original="/img/bmw_m1_side.jpg" width="765" height="574" alt="BMW M1 Side"><br/> <img class="lazy img-responsive" data-original="/img/viper_1.jpg" width="765" height="574" alt="Viper 1"><br/> <img class="lazy img-responsive" data-original="/img/viper_corner.jpg" width="765" height="574" alt="Viper Corner"><br/> <img class="lazy img-responsive" data-original="/img/bmw_m3_gt.jpg" width="765" height="574" alt="BMW M3 GT"><br/> <img class="lazy img-responsive" data-original="/img/corvette_pitstop.jpg" width="765" height="574" alt="Corvette Pitstop"><br/> </p> <p>Aliquam erat volutpat. Maecenas non tortor nulla, non malesuada velit. Nullam felis tellus, tristique nec egestas in, luctus sed diam. Suspendisse potenti. </p> <p>Consectetur adipiscing elit. Nulla consectetur libero consectetur quam consequat nec tincidunt massa feugiat. Donec egestas mi turpis. Fusce adipiscing dui eu metus gravida vel facilisis ligula iaculis. Cras a rhoncus massa. Donec sed purus eget nunc placerat consequat.</p> <p>Cras venenatis condimentum nibh a mollis. Duis id sapien nibh. Vivamus porttitor, felis quis blandit tincidunt, erat magna scelerisque urna, a faucibus erat nisl eget nisl. Aliquam consequat turpis id velit egestas a posuere orci semper. Mauris suscipit erat quis urna adipiscing ultricies. In hac habitasse platea dictumst. Nulla scelerisque lorem quis dui sagittis egestas.</p> <p>Etiam sed massa felis, aliquam pellentesque est.</p> <p>the end.</p> </div> 

To reduce the number of lazyload() during scrolling, we could use, for example, the mcs.top property for the top position of the scroll content (pixels):

 function WhileScrolling() { // Debug: // console.log( 'top: ' + mcs.top ); // Run lazyload in 10 pixel steps (adjust to your needs) if( 0 == mcs.top % 10 ) { // Run lazyload on the "div#conent_1" box: $("#content_1 img.lazy").lazyload(); // Debug: //console.log( 'lazyload - mcs.top: ' + mcs.top ); } } 

where we restrict the layzload selector, so we don’t need to find all the images in the entire DOM tree.

I noticed that in Internet Explorer 11 mcs.top can be floating numbers, but it also contains integers in Chrome.

So, we can install it using Math.floor() .

To further reduce lazyload calls, we could further compare mcs.top with its previous value:

 var mcsTopPrev = 0; var mcsTop = 0; function WhileScrolling() { // Fix the Chrome vs Internet Explorer difference mcsTop = Math.floor( mcs.top ); // Current vs previous if( mcsTop != mcsTopPrev ) { // Run lazyload in 10px scrolling steps (adjust to your needs) if( 0 == mcsTop % 10 ) { $("#cphContent_lReferences img.lazy").lazyload(); } } mcsTopPrev = mcsTop; } 
+2
source

Finally, I wrote this, which can be called from the mCustomScrollbar callback:

  function lazyLoad(selector,container) { var $container=$(container); var container_offset=$container.offset(); container_offset.bottom=container_offset.top+$container.height(); $(selector,$container).filter(function(index,img){ if (!img.loaded) { var img_offset=$(img).offset(); img_offset.bottom=img_offset.top+img.height; return (img_offset.top<container_offset.bottom && (img_offset.top>0 || img_offset.bottom>0)); } }).trigger('appear'); } 

If the image size is constant and the list of images is huge, it might be worth looking for the first image using a dichotomy, and then calculate the range of indices for which the event β€œappears” using the known image and container, the dimensions and offset () of the matching image should be fired. ..

0
source

I use Lazy Load plugins with a custom content scroller and had the same problem.

What worked for me was to add a callback to the whileScrolling mCustomScrollbar event, in which I fire the container scroll event, which I am lazyloading:

 /* Lazy load images */ $(".blog-items img.lazyload").lazyload({ effect: "fadeIn", effect_speed: 1000, skip_invisible: true, container: $(".blog-items") }); /* Custom scrollbar */ $(".blog-items").mCustomScrollbar({ theme: "rounded-dark", callbacks: { whileScrolling: function() { $(".blog-items").trigger("scroll"); } } }); 

I set the lazyload skip_invisible property to true in the hope of increasing performance. Set to false if you encounter any problems.

0
source

All Articles