My infinite scroll append two times with Safari and make duplicate - javascript

I have problem with my infinite scroll with Safari.
He run two times and make duplicate.
This is my code :
$window.scroll(function(){
if (($document.height() - $window.height()) == $window.scrollTop()) {
$('#loading-more svg').show();
jQuery.post(
ajaxurl,
{
'action': 'load_more',
'offset': offset
},
function(response){
$('#loading-more svg').hide();
$('.load-more').append(response);
if (response) {
offset = offset + 4;
}
}
);
}
});
Do you have solution ?
Thank you so much !

Unbind that specific scroll event till your delayed operation is completed to prevent accumulating more of the event triggers which create the duplication behaviour as in your case.
$window.scroll(myEventFn);
function myEventFn() {
if (($document.height() - $window.height()) == $window.scrollTop()) {
$window.unbind("unbind", myEventFn); //unbind specific event
$('#loading-more svg').show();
jQuery.post(
ajaxurl, {
'action': 'load_more',
'offset': offset
},
function(response) {
$('#loading-more svg').hide();
$window.scroll(myEventFn); //bind back the event
$('.load-more').append(response);
if (response) {
offset = offset + 4;
}
}
);
}
}

Try this
var scrolled = true;
$window.scroll(function(){
if ( scroll == true; ) {
scrolled = false;
if (($document.height() - $window.height()) == $window.scrollTop()) {
$('#loading-more svg').show();
jQuery.post(
ajaxurl,
{
'action': 'load_more',
'offset': offset
},
function(response){
$('#loading-more svg').hide();
$('.load-more').append(response);
if (response) {
offset = offset + 4;
scrolled = true;
}
}
);
}
}
});

Related

Infinite Scroll Implementation Not Working On Mobile Browsers

I'm trying to implement infinite scroll. Full code
jQuery(document).ready(function($) {
$(window).scroll(function() {
var that = $('#loadMore');
var page = $('#loadMore').data('page');
var newPage = page + 1;
var ajaxurl = $('#loadMore').data('url');
if ($(window).scrollTop() + $(window).height() == $(document).height()) {
$.ajax({
url: ajaxurl,
type: 'post',
data: {
page: page,
action: 'ajax_script_load_more'
},
error: function(response) {
console.log(response);
},
success: function(response) {
//check
if (response == 0) {
//check
if ($("#no-more").length == 0) {
$('#ajax-content').append('<div id="no-more" class="text-center"><h3>You reached the end of the line!</h3><p>No more posts to load.</p></div>');
}
$('#loadMore').hide();
} else {
$('#loadMore').data('page', newPage);
$('#ajax-content').append(response);
}
}
});
}
});
});
This works fine on my computer, but does not work on any browsers on mobile (Android/iOS).
Any help would be appreciated!

Ajax to fire on page load

I'm hoping someone can find what my issue is. my script only fires when scrolled down... I need that functionality. What it doesn't do is fire on page load too which I need it to do initially. So it loads the content first, then I can scroll down the page for more new content.
I tried putting the ajax inside a function with the function name outside and it still didn't fire.
$(document).ready(function() {
$(window).scroll(function() {
if ($(window).scrollTop() >= $(document).height() - $(window).height() - 100) {
flag = true;
first = $('#first').val();
limit = $('#limit').val();
no_data = true;
if (flag && no_data) {
flag = false;
$('#loadmoreajaxloader').show();
$.ajax({
url: "commentedoncontent.php",
dataType: "json",
method: "POST",
cache: false,
data: {
start: first,
limit: limit
},
success: function(data) {
flag = true;
$('#loadmoreajaxloader').hide();
if (data.count > 0) {
first = parseInt($('#first').val());
limit = parseInt($('#limit').val());
$('#first').val(first + limit);
$.each(data.posts, function(i, response) {
//post content here
});
} else {
alert('No more data to show');
no_data = false;
}
},
error: function(xhr, ajaxOptions, thrownError) {
alert(xhr.status);
flag = true;
no_data = false;
}
});
}
}
});
});
You need to separate it as a function, so you can call it on scroll AND on page load:
$(document).ready(function() {
myFunction();
$(window).scroll(function() {
if ($(window).scrollTop() >= $(document).height() - $(window).height() - 100) {
myFunction();
}
});
});
function myFunction(){
/* all the logic goes here */
}
You can place your code in a function and then execute it on page load and on on scrolling.
$(document).ready(function() {
doStuff(); //choose the name that you want
$(window).scroll(function() {
doStuff();
});
});
function doStuff(){
if ($(window).scrollTop() >= $(document).height() - $(window).height() - 100) {
flag = true;
first = $('#first').val();
limit = $('#limit').val();
no_data = true;
if (flag && no_data) {
flag = false;
$('#loadmoreajaxloader').show();
$.ajax({
url: "commentedoncontent.php",
dataType: "json",
method: "POST",
cache: false,
data: {
start: first,
limit: limit
},
success: function(data) {
flag = true;
$('#loadmoreajaxloader').hide();
if (data.count > 0) {
first = parseInt($('#first').val());
limit = parseInt($('#limit').val());
$('#first').val(first + limit);
$.each(data.posts, function(i, response) {
//post content here
});
} else {
alert('No more data to show');
no_data = false;
}
},
error: function(xhr, ajaxOptions, thrownError) {
alert(xhr.status);
flag = true;
no_data = false;
}
});
}
}
}

infinite scroll duplicate ajax call

I'm having hard time figuring how to avoid duplicate ajax call for my infinite scroll javascript code.
It mostly works but sometimes i have 2 or 3 times the same ajax page call causing a sort of loop.
How to avoid this?
Thanks
//infiniteScroll
var currentPage = 1;
var intervalID = -1000;
var scroll = false;
$('document').ready(function(){
if ( scroll == true) {
if (window.location.pathname == "/" && window.location.search == "" && $('#items_container').length > 0) {
$('.pagination').hide();
intervalID = setInterval(checkScroll, 300);
}
};
})
function checkScroll() {
if (nearBottomOfPage()) {
currentPage++;
jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get',
beforeSend: function(){
var scroll = false;
$('.spinner').show();
},
success: function(data, textStatus, jqXHR) {
$('.spinner').hide();
$('#items_container').append(jQuery(data).find('#items_container').html());
var scroll = true;
if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
clearInterval(intervalID);
}
},});
}
}
}
function nearBottomOfPage() {
return scrollDistanceFromBottom() < 450;
}
function scrollDistanceFromBottom(argument) {
return pageHeight() - (window.pageYOffset + self.innerHeight);
}
function pageHeight() {
return Math.max(document.body.scrollHeight, document.body.offsetHeight);
}
It looks like the checkScroll function is being called every 300 milliseconds, and it's possible that an AJAX request will take longer than that.
I see you've got the scroll variable, but you are only checking the value of it on the initial document load, which won't affect the timer.
I would suggest having a look at listening to the scroll event instead of creating a timer: jQuery docs. You could then do something like the following to prevent two ajax calls running:
var ajaxRunning = false;
function checkScroll() {
if (!ajaxRunning && nearBottomOfPage()) {
currentPage++;
ajaxRunning = true;
jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get',
beforeSend: function(){
$('.spinner').show();
},
success: function(data, textStatus, jqXHR) {
$('.spinner').hide();
$('#items_container').append(jQuery(data).find('#items_container').html());
if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
clearInterval(intervalID);
},
complete: function() {
ajaxRunning = false;
}
},});
}
}
Set async to false, or create a variable like
var isLoading = false;
In before send set it to true. On success set it false again. And before sending the ajax call, check if isLoading isn't true. If it is, return out of the function or put a loop inside with a spinner, which will be checking for the isLoading value so it fires the ajax first after isLoading was set to false.
Example:
function checkScroll() {
if (nearBottomOfPage() && isLoading === false) {
currentPage++;
jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get',
beforeSend: function(){
var scroll = false;
$('.spinner').show();
isLoading = true;
},
success: function(data, textStatus, jqXHR) {
$('.spinner').hide();
$('#items_container').append(jQuery(data).find('#items_container').html());
var scroll = true;
if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
clearInterval(intervalID);
isLoading = false;
}
},
});
}}}

Stop function being fired multiple times on scroll

The following piece of code loads the next page, when the user scrolls to the bottom. However, sometimes it is repeating itself — when the user scrolls too rapidly, or scrolls whilst the AJAX is still being loaded.
Is there a way to prevent it from firing multiple times? So for example, nothing can be loaded while the AJAX is being called, or the AJAX can only be called once a second?
Any help would be great.
$(window).scroll(function() {
if( $(window).scrollTop() + $(window).height() == $(document).height()) {
if (firstURL !== null) {
$.get(firstURL, function(html) { // this gets called multiple times on erratic scrolling
firstURL = '';
var q = $(html).find('.post');
l = $(html).filter('div.bottom-nav');
if( l[0].childNodes.length > 0 ){
firstURL = l[0].children[0].getAttribute('href');
} else {
firstURL = null;
}
q.imagesLoaded( function() {
jQuery(".content").append(q).masonry( 'appended', q, true );
});
});
}
}
});
Just add a flag :
var ready = true; //Assign the flag here
$(window).scroll(function() {
//Check the flag here. Check it first, it's better performance wise.
if(ready && $(window).scrollTop() + $(window).height() == $(document).height()) {
ready = false; //Set the flag here
if (firstURL !== null) {
$.get(firstURL, function(html) { // this gets called multiple times on erratic scrolling
firstURL = '';
var q = $(html).find('.post');
l = $(html).filter('div.bottom-nav');
if( l[0].childNodes.length > 0 ){
firstURL = l[0].children[0].getAttribute('href');
} else {
firstURL = null;
}
q.imagesLoaded( function() {
jQuery(".content").append(q).masonry( 'appended', q, true );
});
}).always(function(){
ready = true; //Reset the flag here
});
}
}
});
I had a similar issue, that scrolling the window fired my function multiple times (manupulating my img slider's properties). To effectively deal with that matter you can defer the execution of scroll handler and use an additional 'page is being scrolled' flag to prevent multiple handler calls.
Check out the example below, you can surely addopt the approach to your case.
$(function()
{
var pageFold = 175; //scrolling threshold
var doScroll = false; //init
var timeoutScroll = 100; //delay
var windowScrolled = false; //initial scrolling indicatior
var windowScrolling = false; //current scrolling status indicator
//load next page handler
function loadNextPage()
{
if(windowScrolling != true)
{
//and do ajax stuff - your code
}
}
//check if page scrolled below threshold handler
function foldedBelow()
{
//nice scrolled px amount detection
return (Math.max($('body').scrollTop(), $('html').scrollTop()) > pageFold);
}
//actual scrolled handler
function doWindowScroll()
{
windowScrolled = true;
if(foldedBelow())
{
loadNextPage();
}
windowScrolling = false;
}
//deffered scroll hook
$(window).scroll(function(e){
windowScrolling = true;
clearTimeout(doScroll);
doScroll = setTimeout(doWindowScroll, timeoutScroll);
});
});
When I did something like this I implemented a timed scroll handler that calls a custom scrolled_to_bottom-event.
(function($, window, document){
"use strict";
var $document = $(document);
var $window = $(window);
var _throttleTimer = null;
var _throttleDelay = 100;
function ScrollHandler(event) {
//throttle event:
clearTimeout(_throttleTimer);
_throttleTimer = setTimeout(function () {
if ($window.scrollTop() + $window.height() > $document.height() - 400) {
console.log('fire_scrolled_to_bottom');
$document.trigger('scrolled_to_bottom');
}
}, _throttleDelay);
}
$document.ready(function () {
$window
.off('scroll', ScrollHandler)
.on('scroll', ScrollHandler);
});
}(jQuery, window, document));
And then in my object handling the reload I bound that event with a flag-check if it was already loading.
handler = {
...,
isLoading: false,
bind: {
var self = this;
$document.on('scrolled_to_bottom', function () {
if (self.isLoading) {
return;
}
self.nextPage();
});
}
nextPage(): function () {
var self = this;
this.isLoading = true;
$.ajax({
url: url,
data: self.searchData,
dataType: "json",
type: "POST",
success: function (json) {
// do what you want with respone
},
error: function (xhr, statusText, errorThrown) {
bootbox.alert('An error occured.');
},
complete: function () {
self.isLoading = false;
}
});
},
init: function () {
this.doInitStuff();
this.bind();
}
}
This way I seperated the concerns and can reuse the triggering nicely, and easily add functionality if other things should happen on reload.
Try storing some kind of data that stores whether the page is currently loading new items. Maybe like this:
$(window).data('ajaxready', true).scroll(function(e) {
if ($(window).data('ajaxready') == false) return;
if ($(window).scrollTop() >= ($(document).height() - $(window).height())) {
$('div#loadmoreajaxloader').show();
$(window).data('ajaxready', false);
$.ajax({
cache: false,
url: 'loadmore.php?lastid=' + $('.postitem:last').attr('id'),
success: function(html) {
if (html) {
$('#postswrapper').append(html);
$('div#loadmoreajaxloader').hide();
} else {
$('div#loadmoreajaxloader').html();
}
$(window).data('ajaxready', true);
}
});
}
});
Right before the Ajax request is sent, a flag is cleared signifying that the document is not ready for more Ajax requests. Once the Ajax completes successfully, it sets the flag back to true, and more requests can be triggered.
copied : jQuery Infinite Scroll - event fires multiple times when scrolling is fast
Here is my solution. You can get an idea and apply it to yours. Also to help others.
You can execute your method first with condition: if(loadInterval ===
null). That means if we already waited for 5 secs.
Assign loadInterval = setTimeout(), then nullify the variable after 5 secs.
Here is sample code.
//declare outside
var loadInterval = null;
// .....
// .....
$(window).scroll(function() {
if ($('.loadmore').isOnScreen() === true) {
//No waiting registered, we can run loadMore
if(loadInterval === null) {
// This console.log executes in 5 seconds interval
console.log('Just called ' + new Date());
// your code in here is prevented from running many times on scroll
// Register setTimeout() to wait for some seconds.
// The code above will not run until this is nullified
loadInterval = setTimeout(function(){
//Nullified interval after 5 seconds
loadInterval = null;}
, 5000);
}
}
});
I post here the IsOnScreen() plugin for jQuery (i found it on stackoverflow :)
$.fn.isOnScreen = function() {
var win = $(window);
var viewport = {
top: win.scrollTop(),
left: win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};

ajax request triggering multiple times when scrolling is fast

here i am trying to achieve infinite scrolling but what happens when i am scrolling too fast it fire multiple ajax request with same parameter , which cause same data again n again.how overcome from this problem pls help.
(function( $ ){
$.fn.scrollPagination = function(options) {
var opts = $.extend($.fn.scrollPagination.defaults, options);
var target = opts.scrollTarget;
if (target == null){
target = obj;
}
opts.scrollTarget = target;
return this.each(function() {
$.fn.scrollPagination.init($(this), opts);
});
};
$.fn.stopScrollPagination = function(){
return this.each(function() {
$(this).attr('scrollPagination', 'disabled');
});
};
var itr = 2;
$.fn.scrollPagination.loadContent = function(obj, opts){
var target = opts.scrollTarget;
var mayLoadContent = $(target).scrollTop()+opts.heightOffset >= $(document).height() - $(target).height();
if (mayLoadContent){
if (opts.beforeLoad != null){
opts.beforeLoad();
}
$(obj).children().attr('rel', 'loaded');
$.ajax({
type: 'POST',
url: opts.contentPage+"?iteration="+itr,
data: opts.contentData,
success: function(data){
itr++;
$(obj).append(data);
var objectsRendered = $(obj).children('[rel!=loaded]');
if (opts.afterLoad != null){
opts.afterLoad(objectsRendered);
}
}
});
}
};
$.fn.scrollPagination.init = function(obj, opts){
var target = opts.scrollTarget;
$(obj).attr('scrollPagination', 'enabled');
$(target).scroll(function(event){
if ($(obj).attr('scrollPagination') == 'enabled'){
$.fn.scrollPagination.loadContent(obj, opts);
//alert(event.isPropagationStopped());
}
//event.stopPropagation();
//console.log(event.isPropagationStopped());
event.preventDefault();
});
//$.fn.scrollPagination.loadContent(obj, opts);
};
$.fn.scrollPagination.defaults = {
'contentPage' : null,
'contentData' : {},
'beforeLoad': null,
'afterLoad': null ,
'scrollTarget': null,
'heightOffset': 0
};
})( jQuery );
How about firing off the ajax every 10 times the scroll event is triggered?
$.fn.scrollPagination.init = function(obj, opts) {
var target = opts.scrollTarget;
$(obj).attr('scrollPagination', 'enabled');
target.scrollCount = 0;
$(target).scroll(function(event) {
this.scrollCount++;
if (this.scrollCount % 10 == 0) {
if ($(obj).attr('scrollPagination') == 'enabled') {
$.fn.scrollPagination.loadContent(obj, opts);
//alert(event.isPropagationStopped());
}
//event.stopPropagation();
//console.log(event.isPropagationStopped());
event.preventDefault();
}
});
}
I used to call my ajax function when the scroll reaches the bottom of the page.
function nearBottomOfPage() {
return $(window).scrollTop() > $(document).height() - $(window).height() - 200;
}
$(window).scroll(function(){
if (loading) {
return;
}
if(nearBottomOfPage()) {
loading=true;
page++;
$("#place_of_loading_image").show();
$.ajax({
url:'your source',
type: 'get',
dataType: 'script',
success: function() {
$("#place_of_loading_image").remove();
loading=false;
}
});
}
});

Categories