I am using jQuery.Lazy()
Plugin with ASP.NET Core Razor Pages and Bootstrap 4 app to retrieve 2 lists from the DB via AJAX (see photo). Everything is working great except for one thing: on a mobile device, I can’t figure out how to delay the retrieval/display of Content Data 2 List
until the user scrolls down far enough in the browser so that Title 2/content
is in their view port. The problem is non-existent on desktops (since the lists are displayed side-by-side and both need to be retrieved), but on a mobile device I don’t want to retrieve the Content Data 2 List
if the user never scrolls down far enough to see it.
When the page first loads, both of the titles are displayed along with a small data area with a spinner. Using AJAX, I retrieve the data, hide the spinner, and then display the retrieved data in it’s place. My over-simplified HTML is:
<div class="col-sm-12 col-lg-6 lazy" data-loader="lazyAJAX1">
<div class="col">
<label class="">Title 1</label>
</div>
<div class="col">
<div class="">
<div class="lp-spinner mt-4 mb-4">
</div>
</div>
<div id="Content1List" class="col-12">
</div>
</div>
</div>
<div class="col-sm-12 col-lg-6 lazy" data-loader="lazyAJAX2">
<div class="col">
<label class="">Title 2</label>
</div>
<div class="col">
<div class="">
<div class="lp-spinner mt-4 mb-4">
</div>
</div>
<div id="Content2List" class="col-12">
</div>
</div>
</div>
And the related JQuery is:
$(".lazy").Lazy({
scrollDirection: 'vertical',
effect: 'fadeIn',
visibleOnly: true,
bind: 'event',
threshold: 0,
lazyAJAX1: function () {
loadAJAX1Partial();
},
lazyAJAX2: function () {
loadAJAX2Partial();
}
});
After playing with it for a while, I believe the problem is with the data-loaders. Specifically, data-loader="lazyAJAX2"
because it is initially displayed in the user’s view port on page load, and therefore automatically retrieves the Content Data 2 List
. What I want is for Lazy() to retrieve Content Data 1 List
first (which will push the Title 2
content down and out of user’s view port), and then enable/activate Lazy() for Content Data 2 List
so that when the user scrolls down far enough to reach Title 2
, the Content Data 2 List
will be retrieved. I hope that makes sense.
I was contemplating using addClass() to try and get around this, but maybe someone with more .Lazy() experience has a better idea on how to do this.
Thanks for any suggestions/help in advance… 🙂
2
Answers
After some trial and error, I found a solution to my dilemma. Building on what @eisbehr suggested, the secret lies within the DOM refresh.
The problem is: when the first
Content Data 1 List
is retrieved via loadAJAX1Partial(),Content Data 2 List
is also called/retrieved asynchronously via loadAJAX2Partial(). Depending on the data (size and time taken to return from the server), either of these 2 lists could return in any order. Using what @eisbehr suggested doesn't guarantee the sequence, nor does wrapping the calls in async/await (at least I was not able to constantly get it to work).So what is the answer? Using setTimeout() or requestAnimationFrame() and sequencing the retrieval as @eisbehr suggested.
There is a really good article about DOM and how it refreshes the contents in the browser (see When DOM Updates Appear to Be Asynchronous), but essentially you need to give the browser time to update/refresh
Content Data 1 List
on screen so thatLazy
can do it's magic.So in my first AJAX call (loadAJAX1Partial()), on success: (after the list is retrieved), I simply call: setTimeout(loadAssetLists, 500) to loadAssetLists() BUT give it 500ms (1/2 second) to allow for the browser screen to refresh before initializing
'Lazy'
:Allowing the screen to refresh BEFORE
Lazy
is initialized displays theContent Data 1 List
, thereby pushing theContent Data 2 List
viewport down. And that seems to work consistently.Notice also that once the viewport is moved down, you can easily chain multiple loads (i.e. loadAJAX2Partial(), loadAJAX3Partial(), etc.) and everything works as expected.
And the great thing is: when the user fully displays the page (by scrolling partially down to retrieve all the AJAX data), clicks to a new page, and then clicks the 'Back button, all the
'Lazy'
functionality works as expected.I hope this solution and explanation is helpful to others, because I cannot be the only one who has faced this issue... :)
I would think, the problem is, that on your approach, both tables will be requested at the same time, because they initially have no content and therefore are very small. When the user scrolls down he will trigger both loads with a high probability, because there are only headlines.
If you want to only load the second table after first has been loaded, a easy way would be to use two instances of
Lazy
. Like shown below. It’s untested but I think you get the idea.