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.
Related
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');
});
}
}
});
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++;
}
});
}
}
});
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);
}
});
}
});
I want an event to load more content when a user is scrolling and reaches nearly the bottom of the page, say about 100px from the bottom, the problem is that the events get fired every single time you scroll in that lower 100px of the page, so that's an obvious issue that cannot happen, for obvious reasons, so I am wondering how I can do this best, I have checked out other answers/questions on here, however the one solution that partially works doesn't fit what I need it to do, and when i try to change it so it will, it completely freezes my browser every time.
this is the question:
Check if a user has scrolled to the bottom
The answer I'm looking at is near the bottom, but here is the code he suggests:
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
$(window).unbind('scroll');
alert("near bottom!");
}
});
now like I said, this does work and prevents more than one event being fired, the problem is I need to have a endless amount of events fired, say i load 100 rows of information when you reach the bottom, but there are still 1500 more, i need it to repeat each time to load every amount of information (once you reach the bottom 100px part of the page each time)
so what I have tried to do is:
function loadMore()
{
alert("More loaded");
$(window).bind('scroll');
}
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
$(window).unbind('scroll');
loadMore();
}
});
like I said, this freezes up my browser immediately every time, the binding part.
I was having this same problem too. I came across this link and it really helped (and worked)!
Update: I looked at the code and I think that when you rebind, you are missing the function to rebind to.
jsFiddle
function loadMore()
{
console.log("More loaded");
$("body").append("<div>");
$(window).bind('scroll', bindScroll);
}
function bindScroll(){
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
$(window).unbind('scroll');
loadMore();
}
}
$(window).scroll(bindScroll);
This will help you.
<script type="text/javascript">
var sIndex = 11, offSet = 10, isPreviousEventComplete = true, isDataAvailable = true;
$(window).scroll(function () {
if ($(document).height() - 50 <= $(window).scrollTop() + $(window).height()) {
if (isPreviousEventComplete && isDataAvailable) {
isPreviousEventComplete = false;
$(".LoaderImage").css("display", "block");
$.ajax({
type: "GET",
url: 'getMorePosts.ashx?startIndex=' + sIndex + '&offset=' + offSet + '',
success: function (result) {
$(".divContent").append(result);
sIndex = sIndex + offSet;
isPreviousEventComplete = true;
if (result == '') //When data is not available
isDataAvailable = false;
$(".LoaderImage").css("display", "none");
},
error: function (error) {
alert(error);
}
});
}
}
});
</script>
Go through this link for whole article and details how to fire multiple event.
load more content when browser scroll to end of page in jquery
I had a same problem. To solve it, Im using underscore.js library to prevent multiple events from firing. Here is the link. http://underscorejs.org/#throttle
I have the code below to find the next sequential page number and load it at the bottom of the page once the user hits the bottom of the screen.
the loading div slides down and as it is loading and up once it is done... it is set to "display:none" by default
What i need is a line of code in there which basically hides the #loading div if no more pages can be found to load... " var url = "page"+nextpage+".html";" finds the new page... titled 'page 2.html, page3.html' and so on.
Any help would be appreciated. I'm assuming it is easy but I can't find a solution anywhere...
alreadyloading = false;
nextpage = 2;
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
if (alreadyloading == false) {
$("#loading").slideDown();
var url = "page"+nextpage+".html";
alreadyloading = true;
$.post(url, function(data) {
$('#newcontent').children().last().after(data);
alreadyloading = false;
nextpage++;
$("#loading").slideUp();
});
}
}
});
If there is no such file then the AJAX request will fail, so you can do what you need from inside a "failure" handler. To be able to specify that, you one solution is to move from using $.post to using the more configurable $.ajax, which gives you all the necessary options:
$.ajax({
type: 'POST',
url: url,
success: function(data) {
$('#newcontent').children().last().after(data);
nextpage++;
},
complete: function() {
alreadyloading = false;
$("#loading").slideUp();
}
});
The complete callback contains code which will be executed no matter what happens with the request; the success callback will be executed before complete, but only if the request was successful.