I have a scroll function
$('#lisr').scroll( function() {
if($(this).scrollTop() + $(this).innerHeight()>= $(this)[0].scrollHeight)
{
//DO some code
}
}
The problem is when I scroll down and it hits the bottom it executes the code twice instead of once, so If I make any ajax call in it, it is made twice, what I am missing in it?
The scroll() function binds to the scroll event - which is fired many times when the user scrolls the page.
Write your code with the assumption that it can be called more than once:
var completed = false;
function doSomeCode() {}
function isAtBottomOfPage() {}
$('#lisr').scroll(function () {
if (!completed && isAtBottomOfPage()) {
doSomeCode();
completed = true;
}
});
jsfiddle: http://jsfiddle.net/kZJ9k/1/
As a more advanced note, you probably shouldn't bind your logic directly to the scroll event; you run the risk of causing lag for your users when scrolling. Read more about this from John Resig:
http://ejohn.org/blog/learning-from-twitter/
Here are my codes for endless scrolling. What I do is unbinding the scroll event until the ajax request finishes. You can also use a variable as a flag and check/change its value before calling ajax request. Hope it helps:
$(document).ready(function(){
$(window).bind('scroll', loadPage);
});
var loadPage = function(){
if($(window).scrollTop() + $(window).height() == $(document).height()) {
$(window).unbind('scroll');
$.ajax({
//Your things here
success: function(result){
// Do success here
$(window).bind('scroll', loadPage);
},
error : function(xhr){ //Do error here }
});
}
}
$('#lisr').scroll( function() {
if($(this).scrollTop() + $(this).innerHeight() > $(this)[0].scrollHeight)
{
//DO some code
}
}
Related
posting for the first time on here, just wondering what im doing wrong within this little jquery script I wrote for a external html file containing my menu element. It works on resize just not load. I've tried a standalone $(window).load(); event as well and nothing seems to work. I'm new to jQuery and just know the do's and donts yet!
jQuery(document).ready(function($) {
var vwidth = $(window).width();
var vheight = $(window).height();
var menu = $('#menu_container');
$( window ).on('load resize', function() {
if (vwidth >= 1000) {
menu.css('zoom', '1');
} else {
menu.css('zoom', '0.8');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
There are two problems here. One already explained by #Mr. Polywhirl.
The other one is the fact that the DOM ready event will excute AFTER the window.load event. That means that by the time jQuery(document).ready executes $(window).load has already happened, so the event registration for window.load it's a bit late. Try this instead...
//this is essentially the same as jQuery(document).ready
$(function(){
toggleZoom();
$(window).on("resize", function(){
toggleZoom();
});
});
function toggleZoom(){
var vwidth = $(window).width();
//this isn't needed in this snippet
//var vheight = $(window).height();
var menu = $('#menu_container');
if (vwidth >= 1000) {
menu.css('zoom', '1');
} else {
menu.css('zoom', '0.8');
}
}
jQuery(document).ready(function($) {
Remove the dollar sign ($) from the function above. You are redefining the global as a function argument for the scope of the jQuery.ready function.
jQuery(document).ready(function() {
Edit
If that does not work, try some of these basic calls and see what the console prints out.
When I click the Run code snippet button, I get the following output:
Document ready()
Window resize()
Window load()
Window load() x2
Window resize()
$(document).ready(function() {
console.log("Document ready()");
});
$(window).on('load', function() {
console.log("Window load()");
});
// or
$(window).on({
load : function() {
console.log("Window load() x2");
},
resize : function() {
console.log("Window resize()");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
The correct usage for jQuery ready() function is:
jQuery(document).ready(function(){
//The code you want to execute.
});
For more info look at:
https://api.jquery.com/ready/
I can't figure this problem out.
I use this JS call to load ajax content when I arrive at the bottom of the page:
$(window).scroll(function() {
if($(window).scrollTop() + window.innerHeight == $(document).height() ) {
and it works well, but now I want to change for loading the content when I reach the bottom of my container... I am trying this:
$(window).bind('scroll', function() {
if($(window).scrollTop() >= $('#postswrapper').offset().top + $('#postswrapper').outerHeight() - window.innerHeight) {
It loads the content when I reach the bottom of the container, but it loads it like 5 times... It's like as if it does a loop 5 times each time.
I want it to load ONCE, then when I go back DOWN the page and I reach the "NEW BOTTOM" of the container, load data 1 more time...etc
I tried many variables, but I can't figure it out. Any suggestions?
FULL AJAX CODE
$(window).bind('scroll', function() {
if($(window).scrollTop() >= $('#postswrapper').offset().top + $('#postswrapper').outerHeight() - window.innerHeight) {
$('div#loadmoreajaxloader').show();
$.ajax
({
url: "loadmore.php",
method: "get",
data: { page: pageNumber, perpage: perPage, search: "<?=$search?>", blogtag: "<?=$blogtag?>"},
success: function(html)
{
if(html)
{
$("#postswrapper").append(html);
$('div#loadmoreajaxloader').hide();
pageNumber++;
}
else
{
$('div#loadmoreajaxloader').html('<center>No more posts to show.</center>');
}
}
}); // close AJAX
} // close if()
}); // close $(window)
Scroll top is executed few times after you have the set true for the condition:
if($(window).scrollTop() >= $('#postswrapper').offset().top + $('#postswrapper').outerHeight() - window.innerHeight)
Here is a test fiddle for the window scroll, it always fires when you move the scroll and your condition does not limit the inner scope to execute only once.
test scrool event
Edit: simplest way is to use a lock while the ajax request is executing and while you are updating the UI with new content.
Why build something like this yourself when there are plenty of libraries out there? Just use an infinite scroll library that meets your needs. As you already use jQuery:
http://www.sitepoint.com/jquery-infinite-scrolling-demos/
But that's not the answer to your question. You should add a boolean to check if you're already loading new content. Let's say: loading. Initially set this boolean to false. If you request new data, set the boolean to true and in the check scroll statement add a check for this boolean. After adding the newly loaded content set the boolean to false again.
Fully working code:
var loading = false;
$(window).bind('scroll', function() {
if(!loading && $(window).scrollTop() >= ($('#postswrapper').offset().top + $('#postswrapper').outerHeight() - window.innerHeight)) {
loading = true;
$('div#loadmoreajaxloader').show();
$.ajax({
url: "loadmore.php",
method: "get",
data: {
page: pageNumber,
perpage: perPage,
search: "<?=$search?>",
blogtag: "<?=$blogtag?>"
},
success: function(html) {
if(html) {
$("#postswrapper").append(html);
$('div#loadmoreajaxloader').hide();
pageNumber++;
loading = false;
} else {
$('div#loadmoreajaxloader').html('<center>No more posts to show.</center>');
}
}
}); // close AJAX
} // close if()
}); // close $(window)
I have written a code to look for page scrolling. It works when I put it inside script tag.
How to put this code inside a function and let it look for page scrolls?
Here is my code
$(window).scroll(function(){
if ($(window).scrollTop() == $(document).height() - $(window).height()){
alert('scrolling');
}
});
I did not understand exactly what you ask,something like this ? (put this in a script tag or an external js file)
$(document).ready(function() {
$(window).scroll(function(e){
detect_scrollPage(e);
});
});
function detect_scrollPage(event){
...
}
What about this:
function scrollBinder(selector, callback){
$(selector).scroll(function(e){
callback.call(this, e);
});
}
$(document).ready(function() {
scrollBinder('#some_div', function(div, event) {
//do calcl here
})
//or on window
scrollBinder(window, function(div, event) {
//do calcl here
})
});
Any way it is a shorthand, most people will do that the same as you did.
I'm having a bit of a problem with Javascript. I have a list of article titles which, when you click a title, the corresponding article appears on the right hand side (fixed at the top of the page). I have got these articles to fade in/out using Javascript. I also have a function which, when you are scrolled down and click on an article title, scrolls the page slowly back up to the top.
The problem I have is that when the page scrolls up and the article changes at the same time, the animations on both become quite choppy, especially in Safari. Is there any way to make the page scroll to the top first, then make the article change?
I'm basically asking if there is away to make my Javascript functions happen one after the other, rather than at the same time?
Heres my Javascript:
$(document).ready(function () {
$('.scrollup').click(function () {
$("body").animate({
scrollTop: 0
}, 'slow');
return false;
});
$('.articlelist ul li').click(function() {
var i = $(this).index();
$('.fullarticle').fadeTo(500,0);
$('#article' + (i+1)).fadeTo(500,1);
});
});
Any help would be hugely appreciated!
Thank you
I'm guessing you want to keep the click functionality on your article list and only the elements with class scrollup have 2 animations.
$(document).ready(function () {
$('.articlelist ul li').click(function () {
var i = $(this).index();
if ($(this).is(".scrollup")) {
$("body").animate({
scrollTop: 0
}, 'slow', function () {//when animation completes
fadeArticle(i);
});
} else {
fadeArticle(i);
}
});
function fadeArticle(i) {
$('.fullarticle').fadeTo(500, 0);
$('#article' + (i + 1)).fadeTo(500, 1);
}
});
In your call to animate() you'd want to add a function to be called upon completion. The animate function provided by JQuery takes a function as an optional parameter. When the animation completes that function is called.
You could use something like this:
$('.scrollup').click(function () {
$("body").animate({
scrollTop: 0
}, 'slow', showArticle);
return false;
});
showArticle would be a call to a function that fades the article in like the anonymous one in your click listener. You would probably need some way to pass an argument about which article should be shown.
I'm relatively new to this, but I think this may work. What I'm trying to do is enclose each of these as a callable function and then pass one function as the callback to the other.
$(document).ready(function () {
scrollTop(showArticle());
});
function scrollTop(callback) {
$('.scrollup').click(function () {
$("body").animate({
scrollTop: 0
}, 'slow');
callback;
});
}
function showArticle() {
$('.articlelist ul li').click(function () {
var i = $(this).index();
$('.fullarticle').fadeTo(500, 0);
$('#article' + (i + 1)).fadeTo(500, 1);
});
}
My Problem is this:
I have a MouseWheel Event (from plugin: https://github.com/brandonaaron/jquery-mousewheel) that triggers a function:
$(document).on('mousewheel', onMouseWheel);
function onMouseWheel(event,delta)
{ Code... }
I Also have a Scroll Event that triggers another function:
$(document).on('scroll', onScroll);
function onScroll()
{ Code... }
However when using the mouswheel, both events are triggered and so both functions run, which I don't want them to. They have to be separate since using the mousewheel and dragging the scrollbar should give separate results. The problem only occurs that way around ie. the mousewheel function is not triggered by dragging the scrollbar.
EDIT:
I've realized with a little help, that the problem occurs because I use ScrollLeft() inside my mousewheel function, which of course causes the scroll event.
I've tried to think of a solution but with no luck. Can anyone help? Thanks!
EDIT: More code:
$(document).on('scroll', onScroll );
function onScroll()
{
code...
}
$(document).on('mousewheel', onMouseWheel ) );
function onMouseWheel(event,delta)
{
event.preventDefault();
if(delta<0)
{
detectDown();
}
else if(delta>0)
{
detectUp();
}
return false;
}
$(document).on("keydown", onKeyDown);
function onKeyDown(e)
{
event.preventDefault();
if (e.keyCode == 37)
{
detectUp();
}
else if (e.keyCode == 39)
{
detectDown();
}
}
function detectUp()
{
$("html, body").animate({scrollLeft:(currentElement.prev().position().left - 100)}, 800, 'easeOutQuad');
currentElement = currentElement.prev();
}
function detectDown()
{
$("html, body").animate({scrollLeft:(currentElement.next().position().left - 100)}, 800, 'easeOutQuad');
}
Maybe this helps?
Add return false at the end of the onMouseWheel function.
function onMouseWheel(event, delta) {
// code
return false;
}
This will disable the default scroll action for the 'mousewheel' event, hence the 'scroll' event will not be triggered.
fiddle
I've come to the realization, that the best solution is to make a custom scrollbar. This way we can avoid calling the scrolling function and having the different types of scrolling interfering with one another.