Reputation: 12437
I am creating a 'scroll to bottom' news feed that populates news when the user scrolls to the bottom of the page.
I have the following code (via Check if a user has scrolled to the bottom):
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
//Ajax Request
}
});
How can I make sure that a user does not scroll up and then scroll down again before the ajax request is done to populate the news. In other words whats a clean way to pause it until the ajax request is done and has filled in its results
Upvotes: 2
Views: 2338
Reputation: 176
You can use .off()
to remove event handlers.
var attachEvent = function(){
$(window).scroll(function() {
$(window).off("scroll");
$.ajax("example.php").done(function() {
//If you want to reattach event
attachEvent();
});
});
};
attachEvent();
Upvotes: 0
Reputation:
Just use a variable to mark whether an outstanding ajax request is present. If so do not make another request. Else fetch the data. My thinking is that let the user scroll, why to block the UI. In that case it is like making a synchronous call.
var isLoading = false;
//event handler
$(window).scroll(function () {
// check height..
// make an ajax request if isLoading is false
if (!isLoading) {
$.ajax(/* .. */, success: function () {
isLoading = false;
},
error: function () {
isLoading = false;
});
isLoading = true;
}
}
If you still want to stop listening to event until the ajax response, simply remove the binding in and reattach it in the ajax response handler.
var isLoading = false;
addScrollEvent();
function scrollHandler(e) {
// check height..
// make an ajax request if isLoading is false
if (!isLoading) {
$.ajax(/* .. */, success: function () {
isLoading = false;
addScrollEvent();
},
error: function () {
isLoading = false;
addScrollEvent();
});
$(window).off('scroll', scrollHandler);
}
}
function addScrollEvent() {
$(window).on('scroll', scrollHandler);
}
Upvotes: 0
Reputation: 1066
Not an answer as such, but a note that doesn't fit well in a comment.
For IE6/IE7/IE8 the .scroll
doesn't really perform well and will call your callback dozens (if not hundreds) of times in each scroll. In our projects we use a wrapper function called .detachedScroll
to prevent this behavior:
/**
* Detached scroll prevents freezing in IE<=8
*/
if($.browser.msie && parseInt($.browser.version, 10) <= 8) {
$.fn.scrollDetached = function(callback) {
return $(this).each(function() {
var oThis = this;
clearInterval(this.detachedScrollInterval);
this.detachedScrollInterval = setInterval(function() {
if (oThis.hasScrolled) {
oThis.hasScrolled = false;
// Calling detached scrolling callback
callback();
}
}, 500);
$(this).scroll(function() {
// There was a scrolling event
oThis.hasScrolled = true;
});
});
};
} else {
$.fn.scrollDetached = $.fn.scroll;
}
Upvotes: 0
Reputation: 91467
Before making the AJAX request, unbind the scroll
handler. After you've processed the AJAX response, rebind the scroll
handler. You'll want to give the scroll
handler a name to enable unbinding and rebinding:
$(window).scroll(function scrollHandler() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
$(window).off("scroll", scrollHandler);
$.ajax({
...
complete: function() {
$(window).scroll(scrollHandler);
}
});
}
});
Upvotes: 1
Reputation: 57709
Something like this:
var request_pending = false;
function at_bottom_of_page() {
return $(window).scrollTop() + $(window).height() > $(document).height() - 100;
}
$(window).scroll(function() {
if (request_pending) {
return;
}
if (at_bottom_of_page()) {
request_pending = true;
doAjax(function (moar_news) {
render_news(moar_news);
request_pending = false;
});
}
});
Upvotes: 3