9

I use lazyload() on my ecommerce website. lazyload() works great. I use this code to do that:

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

Also there are some filter like color, price etc. which is run an ajax and show new result. When new result come, lazyload() doesn't work. I know that I have to use lazyload() with live(), delegate() or on(). But I am a newbie on jquery and I couldn't do that. Can anyone help me please? My jquery version is 1.7.2 and we can use on().

tebdilikiyafet
  • 395
  • 2
  • 6
  • 13
  • 1
    Would you please try the other answer and unaccept my answer for this question? My answer no longer works and people keep downvoting it. – Cymen Oct 20 '13 at 00:09

8 Answers8

5

Shortly, the best optimized way to do this is to call the lazyload in your ajax's success function:

$.ajax({
    url: "your url here",
    type: "Post",
    success: function(response){
        // handle your success callback here
        $("img.lazy").lazyload({ 
              effect : "fadeIn"
        });
    }
});

But if you want to centralize your call to the lazyload plugin, you have 2 options:

First: (not recommended due to performance hit)

$(document).on('DOMNodeInserted', '#container', function() {
    $("img.lazy").lazyload({
        effect: 'fadeIn'
    });
});

but note here the "#container", it is the container's selector where you will show your new loaded stuff, so the code above will listen inside this container for any newly added stuff to run the lazyload again on new images,

Second: (recommended)

Calling your custom lazyload by adding it to your JQuery:

$.fn.myLazyLoad = function() {
    this.lazyload({ 
          effect : "fadeIn"
    });
};

then, call it in all your AJAX requests:

$.ajax({
    url: "your url here",
    type: "Post",
    success: function(response){
        // handle your success callback here
        $("img.lazy").myLazyLoad();
    }
});
AbdelHady
  • 7,590
  • 8
  • 48
  • 80
  • @tebdilikiyafet this is a working effecient answer, you can accept it if it fits your need – AbdelHady Sep 29 '13 at 15:02
  • Nope, are you going to repeat this every ajax call? What if you have 20 jquery plugins instead of 1? Single place for this and listening for DOM changes (eg. MutationObserver) if the only bulletproof way. – emix Jul 01 '19 at 12:42
  • @emix, if you want to listen for DOM node changes then you can use the first way mentioned in the answer here which depends on `DOMNodeInserted` .. but performance wise, it won't be the best, because this listener will run with any DOM insertion even if the change didn't insert new images, which will make a performance hit for sure. – AbdelHady Jul 01 '19 at 15:32
  • As easy as using a debounce function. I was talking to @Alex anyway. – emix Jul 01 '19 at 17:57
  • Well, just for the sake of sharing knowledge, a lot of libraries like the lazy loading ones, will produce reflows because of the way they manipulate Dom objects, and reflows block browser's UI thread which reduces rendering fps, which hurts performance badly when used frequently. So using 3rd party libraries should be done with cautious, not only by code convenience. – AbdelHady Jul 01 '19 at 21:03
2

NOTE: At the time this answer was accepted, this worked. The lazy loading plugin changed and now it is broken. I cannot unaccept the answer nor can I delete it.

There is another Q&A that suggests handling it as part of the AJAX request responsible for inserting the additional DOM:

Binding image lazy loading to new images inserted after ajax request

However, this is how I would do it:

$(document).on('DOMNodeInserted', 'img.lazy', function() {
    $(this).lazyload({
        effect: 'fadeIn'
    });
});

Demo: jsfiddle

Community
  • 1
  • 1
Cymen
  • 12,733
  • 4
  • 47
  • 68
  • Sorry it didn't work my friend. I think we should describe an event in on() because I see that on() shoul use like: $(document).on(EVENT, SELECTION, EVENT-HANDLER); – tebdilikiyafet Dec 09 '12 at 21:18
  • I saw that but it is not with on(). What do you think about ajaxstop? which one is better ajaxstop or on? – tebdilikiyafet Dec 09 '12 at 21:28
  • I would use `on`. I've updated my answer with an example of using it with the `DOMNodeInserted` inserted event. I think this is cleaner as it separates it from the concern of loading data via AJAX. – Cymen Dec 09 '12 at 21:36
  • @tebdilikiyafet Did it work? If so, please accept the answer. Thanks! – Cymen Dec 09 '12 at 21:52
  • First of all thank you for your interest. I tried the code directly but it didn't worked. But I understand your point. I will change a little bit the code and I think it will work. I accepted your answer now. I will try the code with some changes and notify you. – tebdilikiyafet Dec 09 '12 at 22:44
  • I added my solution as a new answer. What do you think about it? is it effective? – tebdilikiyafet Dec 10 '12 at 21:03
  • @tebdilikiyafet That looks fine. It is very similar. It might be slightly more efficient as `$(document).on('ajaxStop', 'img.lazy', function() { $(this).lazyload({effect: 'fadeIn' }); });` but I doubt it matters very much performance-wise. – Cymen Dec 11 '12 at 15:41
  • DOMNodeInserted event is deprecated. – kuboon Mar 17 '17 at 05:55
1

Lazyload for images loaded after window load (e.g. AJAX) will not display any images before a scroll event. This is because it is internally hardcoded to trigger the initial update after the window load event. All the above answers, for now, are wrong.

Mark
  • 836
  • 8
  • 18
  • Was that the original question though? I don't think so. Why not go ask this question as a new question? – Cymen Jun 27 '13 at 16:19
  • Yes Cymen, my answer is relevant. The question is about issues using lazyload with Ajax, and I am pointing out that lazyload is not designed for this..... – Mark Jun 28 '13 at 12:48
  • I think what happened though was that jQuery lazyload changed implementation. I know at the time of my answer the jsfiddle I had worked. It does not now. That is why it make more sense to ask the question again to handle why it broke or to file a bug with the lazyload folks to get it fixed. – Cymen Jun 28 '13 at 21:54
1

In addition to AbdelHady's answer you can lazy load new images on success as a callback or use when() this way:

   $.when(load_new_image()).done(function(i){

            if($('img.lazy').length){

                 $('img.lazy').lazyload({ 

                          effect:'fadeIn'

                 }).removeClass('lazy').addClass('lazyloaded');

            }

        });

        function load_new_image() {

            return $.ajax({
                url: "your url here",
                type: "Post",
                success: function(response){

                     //append new content
                    $('#container').append(response);

                }
            });
        }

NOTA BENE

RafaSashi
  • 14,170
  • 8
  • 71
  • 85
0

I have same problem, when using waypoints infinite scroll with lazy load image. (but not work on ajax content).

and I fixed that issue with this :

$("img.lazy").lazyload({
    effect : "fadeIn",
    event: "scrollstop",
    skip_invisible : true
}).removeClass('lazy');

$(document).bind('DOMNodeInserted', function(e) {
    $("img.lazy").lazyload({
        effect : "fadeIn",
        event: "scrollstop",
        skip_invisible : true
    }).removeClass('lazy');
});

I bind the lazy load configuration on DOMNodeInserted event.

antoniputra
  • 3,681
  • 5
  • 22
  • 31
0

For my scenario when the page is loaded I will get list of template with template Id. Based on that template Id I use jQuery Lazy to load base64 encoded images using ajax and load image lazily on my page.

Hope you will get some idea of my approach

$(document).ready(function() {
  let imageArray = [0, 1, 10, 100, 1000, 1001];

  let parsedImageArray = $.map(imageArray, function(value) {
    return "<div class='lazy' data-loader='ajaxLoader' data-src='/echo/html/' data-method='post' contentId='" + value + "'></div><br>";
  });

  $("#content").html(parsedImageArray);

  console.log("Here" + parsedImageArray)
});


$(document).bind('DOMNodeInserted', function(e) {
  $('.lazy').lazy({
    effect: "fadeIn",
    event: "scrollstop",
    skip_invisible: true,
    removeAttribute: false,
    ajaxLoader: function(element, response) {
      let thumbnailId = element.attr("contentId");
      console.log("Here" + thumbnaiId);
      $.get("https://picsum.photos/id/" + thumbnailId, function(srcValue, status) {
        //for me i have to pull the base64 encode image from my server 
        let defaultImageDom = generateThumbnailImage(tempSrc);
        element.html(defaultImageDom);
        element.removeClass('lazy');
      }).fail(function(jqXHR, textStatus, errorThrown) {
        let defaultImageDom = generateThumbnailImage("");
        element.html(defaultImageDom);
        element.append("<em>Error Getting Thumbnail Preview</em>");
        element.removeClass('lazy');
      });
    },
  });
});

function generateThumbnailImage(srcValue) {
  let defaultImageDom = new Image();
  defaultImageDom.height = 200;
  defaultImageDom.style.borderColor = "#d5d5d5";
  defaultImageDom.style.borderWidth = "1px";
  defaultImageDom.style.borderStyle = "solid";

  if (srcValue && srcValue.length > 0) {
    defaultImageDom.src = srcValue;
  } else {
    //set your fallback image link
    defaultImageDom.src = "data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=";
  }
  return defaultImageDom;
}
.lazy {
  width: 700px;
  height: 467px;
  display: block;
  /* optional way, set loading as background */
  background-image: 'data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=';
  background-repeat: no-repeat;
  background-position: 50% 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.lazy/1.7.9/jquery.lazy.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.lazy/1.7.9/jquery.lazy.plugins.min.js"></script>

<div id="content">
</div>
Dipen
  • 866
  • 1
  • 14
  • 32
-2

I use the code below and it worked:

$(document).on('ajaxStop', function() {
   $("img.lazy").lazyload({
        effect: 'fadeIn'
    });
});
tebdilikiyafet
  • 395
  • 2
  • 6
  • 13
-2
   $(document).ajaxStop(function() {$('.loading').removeClass('in');
    $("img.lazy").lazyload({
                effect: "fadeIn",
               container: $("#scrollable"),
               threshold: 100,
            })

      });

works for ajax images. but however, not showing the first image by default. the update is not triggered.

alexzg
  • 795
  • 7
  • 8