OnScrolling new page is automatically loading - javascript

Actually i have seen a website, where while scrolling the new page is automatically loaded and it is appended to the old page.
Not only the page, URL also getting changed while scrolling.
Completely I don't know how to implement this. This is the website which I have seen matt. Here just scroll down, there will be a infinite scrollbar concept, and also URL address bar will change automatically.

if you want to append dynamic contents to the existed page from some database on scroll then make a ajax call on scroll and also rate limit the number of calls by using throttle function which will return you a throttled version of ajax call that is your ajax call will only be served atmost once during the wait millisecond time period.
var myajax = _.throttle(/*your ajax call goes here*/, wait/*time in ms*/);
_.throttle() is part of underscore.js library and if you don't want to include this library, then you can use my version of throttle that is,
function myThrottle(func, wait, leading) {
var lastCall = 0, timeout = null,
execute = function() {
clearTimeout(timeout);
timeout = null;
func();
};
return function() {
var currentTime = new Date().getTime();
if (leading && (lastCall == 0 || (currentTime - lastCall) > wait)) {
lastCall = currentTime;
func();
}
else if (!leading && !timeout)
timeout = setTimeout(execute, wait);
};
}
here the third argument leading if true than call will be made on leading edge of wait duration blocking further calls otherwise on trailing edge(default behaviour).

You can use something like this:
var documentBottom = $(document).height(), // cache document height
page = 0; // current page number
$(document).on('scroll', function () {
// if window scroll position bigger than document bottom minus 300px,
// then make ajax request and append result to container
if($(window).scrollTop() > documentBottom - 300) {
$.ajax({
type: "POST",
url: "some.php",
data: { page: page },
success: function (data) {
$('.my-container').append(data); // appending result
// cache new document height
documentBottom = $(document).height();
page += 1; // change page number
//change url in address bar
window.history.pushState({},"","/page/"+page);
}
});
}
});

Related

How to stop ajax call being triggered several times when using .scroll?

I wrote a piece of jQuery that allows to me to amend some html on the fly.
$(document).ready(function() {
$(window).scroll(function () {
if ($(window).scrollTop() > $('#target').height() / 2) {
request = $.ajax({
// ajax call
});
request.done(function(html){
$(html).appendTo('#target');
});
}
}
});
So basically when the user scrolls past half way on the element with id='target' it triggers with ajax call which gets some new html and gets appended to target.
Also when scrolling up and down around the boundary (the half the height of target) can lead to multiple triggers of the call.
Is there a way to only allow one ajax call when it passes half way then it cannot make another call until it passes the new halfway point of #target with the appended html?
You can maintain a state for that.
$(document).ready(function() {
let isRequestInProcess = false; // state of request
$(window).scroll(function () {
if (
($(window).scrollTop() > $('#target').height() / 2) &&
!isRequestInProcess
) {
isRequestInProcess = true; // change state as in process
request = $.ajax({
// ajax call
});
request.done(function(html){
isRequestInProcess = false; // change state again to false
$(html).appendTo('#target');
});
}
}
});

How to handle page numbers for an infinite scroll with Jquery / Ajax?

This is my first time trying to implement an infinite scroll with JQuery / Ajax. This is where I am currently:
<script>
$(document).ready(function() {
// see if we're at the bottom of the page to potentially load more content
$(window).on('scroll', scrollProducts);
function scrollProducts() {
var end = $("#footer").offset().top;
var viewEnd = $(window).scrollTop() + $(window).height();
var distance = end - viewEnd;
// when we're almost at the bottom
if (distance < 300) {
// unbind to prevent excessive firing
$(window).off('scroll', scrollProducts);
console.log('we reached the bottom');
$.ajax({
type: 'GET',
url: "foo/bar/2",
success: function(data) {
console.log("success!");
$('#container').append(data).fadeIn();
// rebind after successful update
$(window).on('scroll', scrollProducts);
}
});
}
}
});
</script>
I'd like to understand the correct way to update the page number in the url: foo/bar/2.
I've read that due to the difference between synchronous and asynchronous calls you can't use a global variable but instead need a callback (although I'm failing to understand it). I've also seen a solution where someone updated the values of hidden fields and then referenced those, although that seems like an ugly workaround.
What is the correct or recommended way to handle page numbers in this situation, so that the number increases with each request until there are no more pages?
keep a counter and use it in you request
var page = 1;
$(document).ready(function() {
// see if we're at the bottom of the page to potentially load more content
$(window).on('scroll', scrollProducts);
function scrollProducts() {
var end = $("#footer").offset().top;
var viewEnd = $(window).scrollTop() + $(window).height();
var distance = end - viewEnd;
// when we're almost at the bottom
if (distance < 300) {
// unbind to prevent excessive firing
$(window).off('scroll', scrollProducts);
console.log('we reached the bottom');
$.ajax({
type: 'GET',
url: "foo/bar/" + page,
success: function(data) {
console.log("success!");
$('#container').append(data).fadeIn();
// rebind after successful update
$(window).on('scroll', scrollProducts);
page++;
}
});
}
}
});

infinite scroll on squarespace get category filter

I am using this code to infinite load a page on squarespace. My problem is the reloading doesn't capture the filtering that I have set up in my url. It cannot seem to 'see' the variables or even the url or categoryFilter in my collection. I've tried to use a .var directive but the lazy loaded items cannot see the scope of things defined before it. I'm running out of ideas here please help!
edit: I've since found the answer but gained another question.
I was able to use window.location.href instead of window.location.pathname to eventually get the parameters that way. Except this doesn't work in IE11 so now I have to search for this.
<script>
function infiniteScroll(parent, post) {
// Set some variables. We'll use all these later.
var postIndex = 1,
execute = true,
stuffBottom = Y.one(parent).get('clientHeight') + Y.one(parent).getY(),
urlQuery = window.location.pathname,
postNumber = Static.SQUARESPACE_CONTEXT.collection.itemCount,
presentNumber = Y.all(post).size();
Y.on('scroll', function() {
if (presentNumber >= postNumber && execute === true) {
Y.one(parent).append('<h1>There are no more posts.</h1>')
execute = false;
} else {
// A few more variables.
var spaceHeight = document.documentElement.clientHeight + window.scrollY,
next = false;
/*
This if statement measures if the distance from
the top of the page to the bottom of the content
is less than the scrollY position. If it is,
it's sets next to true.
*/
if (stuffBottom < spaceHeight && execute === true) {
next = true;
}
if (next === true) {
/*
Immediately set execute back to false.
This prevents the scroll listener from
firing too often.
*/
execute = false;
// Increment the post index.
postIndex++;
// Make the Ajax request.
Y.io(urlQuery + '?page=' + postIndex, {
on: {
success: function (x, o) {
try {
d = Y.DOM.create(o.responseText);
} catch (e) {
console.log("JSON Parse failed!");
return;
}
// Append the contents of the next page to this page.
Y.one(parent).append(Y.Selector.query(parent, d, true).innerHTML);
// Reset some variables.
stuffBottom = Y.one(parent).get('clientHeight') + Y.one(parent).getY();
presentNumber = Y.all(post).size();
execute = true;
}
}
});
}
}
});
}
// Call the function on domready.
Y.use('node', function() {
Y.on('domready', function() {
infiniteScroll('#content','.lazy-post');
});
});
</script>
I was able to get this script working the way I wanted.
I thought I could use:
Static.SQUARESPACE_CONTEXT.collection.itemCount
to get {collection.categoryFilter} like with jsont, like this:
Static.SQUARESPACE_CONTEXT.collection.categoryFilter
or this:
Static.SQUARESPACE_CONTEXT.categoryFilter
It didn't work so I instead changed
urlQuery = window.location.pathname
to
urlQuery = window.location.href
which gave me the parameters I needed.
The IE11 problem I encountered was this script uses
window.scrollY
I changed it to the ie11 compatible
Window.pageYOffset
and we were good to go!

Reliably clear intervals when switching page on a dynamic app

I load all content inside a div in the index. Some of these pages require starting intervals, and when switching page those intervals keep going, so I created a destroyjs() function which gets overridden by pages that need it, and is also called every time you switch pages.
The goServiceXXX functions are called onclick in the website's navbar.
var destroyjs = function(){};
function loading(elem)
{
if (typeof destroyjs == 'function')
destroyjs();
document.getElementById("mbody").innerHTML = '<div class="container4"><img src="dist/img/loading.gif" alt="Loading..."></div>';
}
function goServiceManager()
{
var element = "#mbody";
var link = "loadservicemanager.php";
loading(element);
$(element).load(link, function(){
reloadServerStatus();
statusInterval = setInterval(function()
{
reloadServerStatus();
}, 2000);
destroyjs = function(){
clearInterval(statusInterval);
clearInterval(modalInterval);
alert("destroyed manager, interval #"+statusInterval);
}
});
}
function goServiceMonitor()
{
var element = "#mbody";
var link = "loadservicemonitor.php";
loading(element);
$(element).load(link, function(){
reloadServerStatus();
statusInterval = setInterval(function()
{
reloadServerStatus();
}, 2000);
destroyjs = function(){
clearInterval(statusInterval);
alert("destroyed monitor, interval #"+statusInterval);
}
});
}
This works fine when used normally however if I spam click between the two pages, intervals start adding up and the 2 second query is now being called 10 times every two seconds. I added the alerts to debug but they slow the interface down enough for everything to work properly.
Is there a hole in my logic somewhere? I already thought of disabling all navbar buttons when one is clicked and enabling them at the end of .load; but I'd like to know why my current implementation is not working and if it can be fixed more easily.
Edit:: So I tried to make a fiddle with the problem and in the process realized that the problem happens when destroyjs() is called before .load() finishes. Moving the interval right before .load() fixes the problem but can create a scenario where if the content never loads (or doesn't load in two seconds) there are missing elements which the function inside the interval tries to fill. Disabling the navbar temporarily and wait for .load to finish is the easy way out after all but I'd still like more opinions on this or maybe ideas for a better implementation.
destroyjs isn't defined until the load() completes. If you switch tabs before the previous tab has loaded, you won't be able to call the correct destroyjs.
Therefore, you will want to cancel any outstanding load requests when switching tabs. To do this, you can use jQuery's ajax method. Just store a reference to the resulting XHR object and call abort() when loading a new tab. Aborting an outstanding ajax request will prevent it's success callback from firing.
Here's an example (DEMO FIDDLE). Notice that I've also changed the way that intervals are cleared:
//ajax request used when loading tabs
var tabRequest = null;
//Any intervals that will need to be cleared when switching tabs
var runningIntervals = [];
function loading(elem)
{
if (tabRequest) {
//Aborts the outstanding request so the success callback won't be fired.
tabRequest.abort();
}
runningIntervals.forEach(clearInterval);
document.getElementById("mbody").innerHTML = '<div>Loading...</div>';
}
function goServiceManager()
{
var element = "#mbody";
var link = "loadservicemanager.php";
loading(element);
tabRequest = $.ajax({
url: link,
success: function(data) {
$(element).html(data);
reloadServerStatus();
statusInterval = setInterval(reloadServerStatus, 2000);
modalInterval = setInterval(modalFunction, 2000);
runningIntervals = [statusInterval, modalInterval];
}
});
}
function goServiceMonitor()
{
var element = "#mbody";
var link = "loadservicemonitor.php";
loading(element);
tabRequest = $.ajax({
url: link,
success: function(data) {
$(element).html(data);
reloadServerStatus();
statusInterval = setInterval(reloadServerStatus, 2000);
runningIntervals = [statusInterval];
}
});
}

AJAX call to messages database if new message fire javascript

What I am trying to do is detect whether there has been any new messages added to a conversation in a mysql database. If there is the I want to use JavaScript to scroll to the bottom of the page to the last message.
$(document).ready(function() {
var prevdata;
var interval = setInterval(function() {
$.ajax({
url: 'inc/aj_chat.php',
success: function(data) {
$('#messages').html(data);
afterdata = data;
}
});
setTimeout(function() {
alert(prevdata);
if (prevdata != afterdata) {
// Scroll Down function
}
prevdata = afterdata;
},1);
}, 3000);
});
as you can see I have a setInterval loop refreshing every 3000ms and im trying to pass the variables from the previous loop into the next loop to compare them. Firstly is this the best way to achieve this and secondly if it is how can I do this?
I would do something like this instead:
$.ajax({
url: 'inc/aj_chat.php',
success: function(data) {
$('#messages').html(data);
if($(window).scrollTop() + $(window).height() > $(document).height() - 50) {
window.scrollTo(0,document.body.scrollHeight);
}
}
});
So everytime the scrollbar is 50 pixels or less from the bottom, it'll send the scrollbar to the bottom. If it's not, it'll leave the scrollbar alone. You can adjust the number 50 to any number of pixels you want.
So this will make sure your chatsystem auto-scrolls only if the user isn't searching in previous messages.

Categories

Resources