Is there a way to prevent $(window).scroll() from firing on page load?
Testing the following code in Firefox 4, it fires even when I unplug the mouse.
jQuery(document).ready(function($){
$(window).scroll(function(){
console.log("Scroll Fired");
});
});
The scroll event is unrelated to the mouse, it is called whenever a new document scrolling position is set. And arguably that position is set when the document loads (you might load it with an anchor after all), also if the user presses a cursor key on his keyboard. I don't know why you need to ignore the initial scroll event but I guess that you only want to do it if pageYOffset is zero. That's easy:
var oldPageYOffset = 0;
$(window).scroll(function(){
if (window.pageYOffset != oldPageYOffset)
{
oldPageYOffset = window.pageYOffset;
console.log("Window scrolling changed");
}
});
Note: MSIE doesn't have window.pageYOffset property so the above will need to be adjusted. Maybe jQuery offers a cross-browser alternative.
This was the solution I went for. Any improvements gratefully received.
var scroll = 0;
$(window).scroll(function(){
if (scroll>0){
console.log("Scroll Fired");
}
scroll++;
});
The scroll event does not fire on every load, only when refreshing a page that was scrolled, or when navigating to an anchor directly.
Many of the answers suggest ignore the first time it's called, which would ignore a valid scroll if the page doesn't get scrolled initially.
//Scroll the page and then reload just the iframe (right click, reload frame)
//Timeout of 1 was not reliable, 10 seemed to be where I tested it, but again, this is not very elegant.
//This will not fire initially
setTimeout(function(){
$(window).scroll(function(){
console.log('delayed scroll handler');
});
}, 10);
//This will fire initially when reloading the page and re-establishing the scroll position
$(window).scroll(function(){
console.log('regular scroll handler');
});
div {
height: 2000px;
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
</div>
This seems to have worked for me.
$(window).bind("load", function() {
$(window).on("scroll", function () {
console.log('scroll');
});
});
sure, don't load it until after the load. make it a call back for sleep for 500 millis.
Related
I have created a function which scrolls down a div content with overflow-y.
This function works when I just refresh and scrolls correctly down to the bottom. When I come from a other page (same website) it does scroll, but not to the bottom, almost though.
I have used console.log to see how much it scrolls down and even there it shows that scrollHeight is bigger than the div itself, so that should be correct.
I've tried putting a setTimeOut around it with 3000ms, but that didn't work.
setTimeout (function () {
$content.animate({ scrollTop: $content.prop("scrollHeight")}, "medium");
console.log($content.prop("scrollHeight"));
}, 3000)
I don't think it's the code that is wrong, but something else. Anyone have an idea?
animate only works every time you open a tab
You should use popstate event:
function animate(){
$content.animate({ scrollTop: $content.prop("scrollHeight")}, "medium");
console.log($content.prop("scrollHeight"));
}
animate();
window.onpopstate = function() {
animate();
};
I've got this jQuery to add a back to top button. It's simple and works very well. I have it running as a plugin in WordPress MultiSite on probably 120 websites. Today I noticed it isn't working on every site. There are no console errors, but my guess is that some other plugin or script is causing a conflict. This is inconsistent from one site to the other and I can't find a reason.
How can I write this jQuery so it doesn't experience compatibility issues?
jQuery(document).ready(function($){
//Check to see if the window is top if not then display button
$(window).scroll(function(){
if ($(this).scrollTop() > 100) {
$(".scrollToTop").fadeIn();
} else {
$(".scrollToTop").fadeOut();
}
});
//Click event to scroll to top
$(".scrollToTop").click(function(){
$("html, body").animate({scrollTop : 0},800);
return false;
});
});
Example site 1: http://anntowergallery.com/exhibits/ Doesn't work.
Example site 2: http://iemajen.com/asphaltanimals/ Works
I've tried this out on a dozen sites or so and cannot pin point what could cause the problem. No errors in console on the gallery website.
I appreciate any feedback.
Strange bug you got there.
Seems that in site 1 you have the following CSS:
body {
overflow-x: hidden;
}
When that CSS is in place, the $(window).scroll event listener won't fire. If you remove that CSS line, the JS works just fine.
You can also bind the scroll event to the body instead of the window:
$("body").scroll(function(){
...
});
But I recall that had some issues with IE. Probably you'd be safest to bind both $("body").scroll and $(window).scroll:
jQuery(document).ready(function($){
//Check to see if the window is top if not then display button
$(window).add("body").scroll(function(){
if ($(this).scrollTop() > 100) {
$(".scrollToTop").fadeIn();
} else {
$(".scrollToTop").fadeOut();
}
});
//Click event to scroll to top
$(".scrollToTop").click(function(){
$("html, body").animate({scrollTop : 0},800);
return false;
});
});
You've got a style element inside the body tag right before your scroll script, which isn't valid and may be preventing the script from executing. Try moving that into the head.
This is the part I'm talking about:
<style type="text/css">
.scrollToTop {
/* ... */
}
</style>
I wouldn't use that code on mobile devices... every tick of the window scroll is firing either a fadeIn or fadeOut. It would be better to add a flag to check if the scroll to top button is visible, or not (demo)
jQuery(document).ready(function($) {
var visible = false;
//Check to see if the window is top if not then display button
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
if (!visible && scrollTop > 100) {
$(".scrollToTop").fadeIn();
visible = true;
} else if (visible && scrollTop <= 100) {
$(".scrollToTop").fadeOut();
visible = false;
}
});
//Click event to scroll to top
$(".scrollToTop").click(function() {
$("html, body").animate({
scrollTop: 0
}, 800);
return false;
});
});
Why does another scroll event get called after a scrollTop animation fires its complete callback?
Click Handler:
var lock = false;
$('#id').click(function(event) {
var pos;
if (lock) {
return;
}
lock = true;
pos = 150;
console.log("jump start");
$(jQuery.browser.webkit ? "body": "html").animate({ scrollTop: pos }, 150, function () {
lock = false;
console.log("jump end");
});
});
Scroll Handler:
$(window).scroll(function (e) {
console.log("scrolling");
if (!lock){
alert('1');
}
});
Log:
jump start
scrolling
jump end
scrolling
demo on jsfiddle
Background
jQuery scrollTop() uses scrollTo() which is a fire and forget event. There is no stopped event for scrolling. The scroll events occur out of band from scrollTo. scrollTo means 'start scroll', a scroll event means 'scrolled (some position)'. scrollTo just initiates the starting of the scroll, it doesn't guarantee that scrolling finished when it returns. So, jQuery animation completes before final scroll (there could even be multiple scrolls backed up). The alternative would be for jQuery to wait for the position of the scroll to be what it requested (per my soln), but it does not do this
It would be nice if there was a specification that we could point to describing this, but it is just one of the Level 0 dom elements without a spec, see here. I think it makes sense the way that it works, which is why all browsers seem to implement it this way.
Why is this happening
The following occurs on the last scroll of the animation:
jquery: 'Window please scroll this last bit'
Window: 'I got this message from jquery to scroll I will start that now'
jquery: 'woohoo I am finished the animation, I will complete'
Your code: lock = false;console.log("jump end");
Window: 'I have scrolled' call scroll event handlers.'
Your code: $(window).scroll(function (e) { 'Why is this happening?'
As you can see jquery does not wait for the final scroll step of the animation to complete before completing the animation (going on to step 4). Partly this is because there is no stopped event for scrolling and partly this is because jquery does not wait for the scroll position to reach the position that was requested. We can detect when we have reached the destination position as described below.
Solutions
There is no stopped event for when scrolling completes. See here. It makes sense that there is no stopped event because the user could start scrolling again at any point, so there is no point where scrolling has really stopped - the user might just have paused for a fraction of a second.
User scrolling: For user scrolling, the normal approach is to wait some amount of time to see if scrolling is complete as described in the answer of the referenced question (bearing in mind that the user could start scrolling again).
scrollTop: However, since we know the position that we are scrolling to we can do better.
See this fiddle.
The crux of it is that since we know where we are scrolling to, we can store that position. When we reach that position we know that we are done.
The output is now:
jump start
scroll animation
jump end
The code is (note that this is based off your fiddle rather than the code in the edited question):
var scrollingTo = 0;
$('#id').click(function(event) {
if (scrollingTo) {
return;
}
console.log("jump start");
scrollingTo = 150;
$(jQuery.browser.webkit ? "body": "html").animate({ scrollTop: scrollingTo }, 150, function () {
});
});
function handleScroll()
{
if( scrollingTo !== 0 && $(window).scrollTop() == scrollingTo)
{
scrollingTo = 0;
console.log("jump end");
}
}
$(window).scroll(function (e) {
if (!scrollingTo){
console.log('user scroll');
} else {
console.log("scroll animation");
}
handleScroll();
});
I believe that at the time the animation ends and the callback function is called, the event has not reached the window yet, so it is not re-called, it just hasn't been fired yet.
I'm running into a problem that's actually a "feature" on Chrome.
As most of you might know, Chrome remembers a scroll position that it returns to, whenever you come back to a page. And I kind of have a problem with that.
Is there any way to override this without the user noticing?
Mees
Failed try-outs:
ScrollTop on document.ready
In Chrome 46+, the auto scroll behavior can be turned off using history.scrollRestoration:
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
source: https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration
I've checked on chrome, it worked well. Sometimes setTimeout does trick :)
<script type="text/javascript">
window.onload=function(){
setTimeout(function(){
scrollTo(0,-1);
},0);
}
</script>
x = 0; //horizontal coord
y = document.height; //vertical coord
window.scroll(x,y);
Some Javascript like that may very well be able to be manipulated to stop the auto scrolling.
It depends though, are you happy for the scroll to be simply set to automatically go to the top, or are you actually looking for the Chrome standard option to take the page to last scroll position, to be turned off completely?
What are you currently attempting to use for scrollTop()?
I solved this by attaching to scroll event, and then resetting scroll position the first time a user scrolls. Works for on-spot reloads for me.
Looks like this:
var scrollResetOnce = false;
$(window).on("scroll", function() {
if (scrollResetOnce) return;
scrollResetOnce = true;
scrollTo(0, -1);
});
Here is a clean way of getting this done.
window.addEventListener('unload', function(e){
document.body.style.display = 'none';
});
By simply setting the body display to 'none' you don't have to worry about a flash of the browser scrolling to the top of the page before it is unloaded and the scroll position will automatically be reset to 0.
I've re-created a simple version of what I'm trying to do here (jsFiddle)
The header should stay where it is, and as you scroll down, when you click the header div it should scroll back up to the top, which it does. But if you focus on the input, or click the "logo", the scroll should stay where it is.
With the first method I've tried is by using jQuery's .css and setting the input/logo's z-index as higher than the header, then getting the current scroll and keeping it at that position.
This sort of works, but once you click the input or logo, the header scroll no longer works.
I've also tried changing the logo/input jQuery to .animate with a slow speed, and it stays static for a couple seconds and then scrolls to the top even though I've not set it to do so. Here is the second example - jsFiddle
Doing it with the second example however doesn't stop the other function from working.
Is there any reason for this behaviour that I'm missing?
You can prevent the click event from propagating to the header.
$("#logo, #input").click(function(e) {
e.stopPropagation();
});
Check out this interesting article about event order, all you have to do is stop propagation. Here your modified Fiddle
$("#logo, #input").click(function(e) {
e.stopPropagation();
var y = window.scrollY;
$('html').animate({
scrollTop: y
}, 'slow');
$('body').animate({
scrollTop: y
}, 'slow');
});
All you need to do is stop the propegation of the event. To do this you return false from your click function.
$("#logo, #input").click(function() {
return false; // Add this line
});
Here is your fiddle updated: http://jsfiddle.net/BRnvT/