Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue when using jQuery.Lazy() Plugin with a function AJAX call #253

Open
MicJarek opened this issue Jan 26, 2022 · 5 comments
Open

Issue when using jQuery.Lazy() Plugin with a function AJAX call #253

MicJarek opened this issue Jan 26, 2022 · 5 comments

Comments

@MicJarek
Copy link

MicJarek commented Jan 26, 2022

I have two different pages where I use jQuery.Lazy(). In the first page, AJAX is used to retrieve a record list via AJAX as soon as the page loads. Here .lazy works fine and the images fadein as soon as they show up in the viewport.

On the second page, the user can enter search criteria, and when they click the 'Search' button, a function is called that also uses AJAX to retrieve a record list with images ( see code below). Here though, the images do NOT fadein as soon as they are displayed. The placeholders are displayed, but the images don't fadein. You have to click/scroll the vertical scrollbar on the browser for the fadein to begin.

The ONLY difference that I can tell between the 2 pages is that the second one uses a function() to call the AJAX/retrieve, but the rest of the code is practically identical.

function mySearch() {
   $('#myList').hide();
   let pMyString = $('#myString').val();

   $("#myList").load("mySearch/mySearchListPartial", { __RequestVerificationToken: '@token', "pMyString": pMyString, ... }, function (responseTxt,    statusTxt, xhr) {
       if (statusTxt == "success") {

           let lazyInstance = $(".lazyLoadImage").Lazy({
               chainable: false,
               effect: "fadeIn",
               effectTime: 1000,
               threshold: 0
           });
           lazyInstance.update();

           $('#myList').slideDown();
       }
       else if (statusTxt == "error") {
           $('#myList').show().html('<p class="error-details">Error: ' + xhr.status + ': ' + xhr.statusText + '</p>');
       }
   });
}

How do I call .lazy to start the fadein of images that are initially displayed on the viewport as soon as they are loaded (without having to click/drag the vertical scrollbar first)?

@dkern
Copy link
Owner

dkern commented Jan 26, 2022

First, keep in mind, if you do it like this, you will create a new Lazy instance every time the user searches and you add all images to a new instance over and over again. May this is not the best idea. ;)

The reason why this doesn't work is, that Lazy listens to the page load to start loading images. But in your case, the page load has already happen when you create the instance. Therefore you may use the bind parameter.

let lazyInstance = $(".lazyLoadImage").Lazy({
    chainable: false,
    bind: 'event',
    effect: "fadeIn",
    effectTime: 1000,
    threshold: 0
});

But as said before, this is not the best idea. So, maybe do it like this:

let lazyInstance = $(".lazyLoadImage").Lazy({
    chainable: false,
    effect: "fadeIn",
    effectTime: 1000,
    threshold: 0
});

function mySearch() {
   $('#myList').hide();
   let pMyString = $('#myString').val();

   $("#myList").load("mySearch/mySearchListPartial", { __RequestVerificationToken: '@token', "pMyString": pMyString, ... }, function (responseTxt, statusTxt, xhr) {
       if (statusTxt == "success") {
           lazyInstance.addItems(".lazyLoadImage");
           lazyInstance.update();

           $('#myList').slideDown();
       }
       else if (statusTxt == "error") {
           $('#myList').show().html('<p class="error-details">Error: ' + xhr.status + ': ' + xhr.statusText + '</p>');
       }
   });
}

@MicJarek
Copy link
Author

Very good point. I have created an instance and just call the addItems/update now (as you suggested above). But I am still having an issue with images not fading in (still need to click/scroll the vertical scrollbar to get them to start appearing).

Just and FYI: Initially, when I changed to an instance, the images wound NOT display at all. After some debugging/testing I tracked it down to an AJAX load issue. I think what is happening is that when the page first loads, .lazy does NOT see any reference on the page to the class='lazyLoadImage' because AJAX has not been executed yet (and therefore there is no <img> reference).

Just so we're on the same page, what happens is that there is a simple <div id="myList"></div> on the page that is populated (the contents are replaced) via the AJAX .load() call (with the contents of a Partial Page retrieved from the server). That Partial Page is where the tags are located at, so initially there is no <img class='lazyLoadImage'> for .lazy to find. I ended up putting in a dummy <img class="lazyLoadImage" src="/images/PhotoPlaceholder.png" data-src="/images/PhotoPlaceholder.png"> inside the <div id="myList"></div> and that seems to have fixed that problem.

But the original problem still remains: I still need to click/scroll the vertical scrollbar to get the images to start appearing after the mySearch() call? Is there any way for me to trigger .lazy manually (so that it thinks the scroll bar has been moved)? Just throwing things out there .... :)

As I mentioned originally, on a simple page without an AJAX call, .lazy works awesome. Unfortunately, almost all my pages use AJAX to get the data.

Oh, and BTW: I'm not sure if this is relevant, but the latest version of the library shows it to be 1.7.11 on github, but the actual jquery.lazy.js I have (and redownloaded to make sure) says jQuery & Zepto Lazy - v1.7.10?

@MicJarek
Copy link
Author

OK... so I'm not sure if this is going to help... but... I also noticed that in the first page I mentioned above (where AJAX is used to retrieve a record list via AJAX as soon as the page loads), the images do NOT always appear (now that I started using an instance). What happens now is usually the first time I open the page, images show up. But when I click the refresh button on the browser, most of the time images are blank (probably the place holders are shown). It's sporadic, and if I keep clicking the refresh button, eventually the images come up. Here is what I'm using:

let lazyInstance = $(".lazyLoadImage").Lazy({
    chainable: false,
    effect: "fadeIn",
    effectTime: 1000,
    threshold: 0
    }
});

getlazyLoadImage();

function getlazyLoadImage() {
   $('#myList').hide();
   let pMyString = $('#myString').val();

   $("#myList").load("mySearch/mySearchListPartial", { __RequestVerificationToken: '@token', "pMyString": pMyString, ... }, function (responseTxt, statusTxt, xhr) {
       if (statusTxt == "success") {
           lazyInstance.addItems(".lazyLoadImage");
           lazyInstance.update();

           $('#myList').slideDown();
       }
       else if (statusTxt == "error") {
           $('#myList').show().html('<p class="error-details">Error: ' + xhr.status + ': ' + xhr.statusText + '</p>');
       }
   });

}

Just to test, I removed the instance as the code shows below and that works fine.

getlazyLoadImage();

function getlazyLoadImage() {
   $('#myList').hide();
   let pMyString = $('#myString').val();

   $("#myList").load("mySearch/mySearchListPartial", { __RequestVerificationToken: '@token', "pMyString": pMyString, ... }, function (responseTxt, statusTxt, xhr) {
       if (statusTxt == "success") {
           
            $(".lazyLoadImage").Lazy({
                chainable: false,
                effect: "fadeIn",
                effectTime: 1000,
                threshold: 0
            });

           $('#myList').slideDown();
       }
       else if (statusTxt == "error") {
           $('#myList').show().html('<p class="error-details">Error: ' + xhr.status + ': ' + xhr.statusText + '</p>');
       }
   });

}

Do I need to structure the instance call some other way for .lazy to work correctly?

@MicJarek
Copy link
Author

So I had a bit more time to test/think about this, and this morning I noticed that in my first page (where AJAX retrieves records as soon as the page loads), when I copied your suggestion above, I didn't notice that the bind: 'event' was NOT in it. When I appended it, that seems to have fixed that page issue, and now the images show up each time I refresh the page. So that is all good.

But the second page, where AJAX is called via a 'Search' button, I'm still having problems. It makes sense to use an instance, but I think that instance 'array' list needs to be cleared out each time the 'Search' button is clicked. After all, the AJAX call may return a combination of previously displayed images and some new images. Maybe the instance just needs to be reset and start from scratch? Does that make sense? If that is the case, then how do I do that? Is there a public function to clear the array and leave the instance in place for the next search population?

Sorry for this continued comments, but hopefully some of this will be helpful... :)

@MicJarek
Copy link
Author

MicJarek commented Feb 1, 2022

Well... I kind of spoke too soon (in my previous message above), because the AJAX is still NOT working correctly. First, I did fix an issue by adding bind: 'event' to the instance and also moved the .slideDown() above the lazyInstance addItems/update (and even wrapped it in a CallBack to make sure it was executed synchronously). But there are still issues with AJAX. Here is the modified code:

let lazyInstance = $(".lazyLoadImage").Lazy({
    chainable: false,
    bind: 'event',
    effect: "fadeIn",
    effectTime: 1000,
    threshold: 0
    }
});

getlazyLoadImage();

function getlazyLoadImage() {
   $('#myList').hide();
   let pMyString = $('#myString').val();

   $("#myList").load("mySearch/mySearchListPartial", { __RequestVerificationToken: '@token', "pMyString": pMyString, ... }, function (responseTxt, statusTxt, xhr) {
       if (statusTxt == "success") {

           $("#myList").slideDown("fast", function () {
                lazyInstance.addItems(".lazyLoadImage");
                lazyInstance.update();
            });
       }
       else if (statusTxt == "error") {
           $('#myList').show().html('<p class="error-details">Error: ' + xhr.status + ': ' + xhr.statusText + '</p>');
       }
   });
}

To further test, I also created 2 separate pages:

  1. first one with 15 embedded images (similar to your example: http://jquery.eisbehr.de/lazy/example_show-a-loading-image
  2. and second one that does exactly the same thing (display the same 15 images), but this time the AJAX script above is used to populate/display the contents of the Partial Page in a <div id="#myList"></div>.

Here is what I have noticed:

  1. Both pages display fine when each page is initially at the top (meaning images get loaded by .lazy() as expected).
  2. On page 1), when I scroll down and then click 'Refresh', the page remains in the same vertical position as .lazy() correctly loads the images.
  3. BUT on page 2) AJAX, when I scroll down and then click 'Refresh', the page jumps ('almost' to the top), and once the AJAX displays the place holders, .lazy() does NOT load the images again.

Furthermore, in both pages, I also pulled out the lines:

    lazyInstance.addItems(".lazy");
    lazyInstance.update();

into a separate .js file (in .net core you can't debug javascript when it's embedded in the HTML page), and what I found is that the Page 1) shows a list of 15 img.lazy entries on top of the lazyInstance. BUT, in Page 2) AJAX it does NOT have these.

Is this then an issue with .lazy() not reading the <img> tags correctly in the case of AJAX, and hence all the problems I'm having?

Daniel... I tried to be as helpful as I can with my debugging/observations because I would really like to resolve this issue so that I can use this throughout my application. All my images come from the DB via AJAX, so unfortunately I can't use the AJAX extension you provide.

Please let me know if this is something you can address, or do I need to just go without .lazy() because of AJAX?
Tks for your help... :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants