I modified a pretty common jQuery smooth-scroll method to suit my needs better --- a function to scroll to an anchor:
function scrollToAnchor(id, offset) {
target = $(id);
$('html, body').stop().animate({
'scrollTop': target.offset().top + offset}, 900, 'swing', function () {
window.location = id;
});
}
I have the offset parameter to account for a fixed navigation pane at the top. I have the offset set to -100 on each call of scrollToAnchor so that it scrolls 100 pixels less (this allows the content to be displayed without the fixed navigation pane hiding any content).
My issue occurs with window.location = id;. This sets the URL to include the anchor, but because of this, it scrolls to the top of the div (this hides 100 pixels of content that my offset tries to prevent). I can't really use event.preventDefault() because I don't have any event parameter. Is there any way to prevent the window from scrolling when I set the location?
As you pointed out, it's the browser default behavior to scroll to the element specified by the anchor you add in the URL.
What if you changed the location before scrolling ?
Otherwise, you could use window.history.replaceState method which should modify the URL without scrolling.
However, bear in mind that's it is not supported in all browsers yet.
Related
I have a page with a navbar with links on the same page. When i disable all js plugins and click on a link it "jumps" (without smooth scroll) to the anchored link.
But because i have a sticky header it's neccessary that i use a offset. Because of that i copied this nice piece of code from the web:
My "navbar"
<div id=myAffix>My Affix</div>
Example link
The part of the html page:
<li id="2849" class="list-group-item list-group-item-info">
<h6>Example header</h6>
</li>
// Add smooth scrolling on all links inside the navbar
$("#myAffix a").on('click', function (event) {
var offset = 125;
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top - offset
}, 800, function () {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
When i now click the link it smooth scrolls to that part (with the offset) and after that it "jumps" to the position without the offset. I tried to override default scroll behaviour, disable single js plugins but it keeps this behaviour. Does anyone have an idea?
I have a situation where I need the page to not be scrollable past a certain point (I have the hero set to 100vh and the user should not be able to scroll at all) and then upon click of a button the scroll prevention is disabled and the user is then automatically smooth scrolled down to an anchor link directly below (basically scroll down 100vh or the full window height). I need a smooth scrolling animation instead of just a quick jump.
I've tried playing around with variations of the following code with no luck. So far it is really buggy and jumps around and when you reload the page the body overflow is set to hidden but the window position is not always at the top of the screen so you still see some of the below the fold content but still cant scroll.
function() {
function smoothScroll(){
windowHeight = $('window').height();
$('html, body').stop.animate({scrollTop: windowHeight}, slow);
}
$('.bottom-nav').on('click', '.fold-trigger', function(event) {
$('.home').css('overflow', 'visible');
setTimeout(smoothScroll(), 1000);
});
};
Fiddle is here: https://jsfiddle.net/njpatten/yxkvnymu/1/
Fixed Code
function smoothScroll(){
windowHeight = $(window).height();
$('html, body').stop().animate({scrollTop: windowHeight}, "slow");
}
$('.bottom-nav').on('click', '.fold-trigger', function(event) {
$('.home').css('overflow', 'visible');
setTimeout(smoothScroll(), 1000);
});
Fixed fiddle: https://jsfiddle.net/yxkvnymu/2/
Explanation
You are trying to get the window height by doing $('window').height() which is searching for a 'window' DOM element which doesn't exist. You want to use $(window).height() (note the omission of quotes surrounding window) because window is not a DOM node, it is an object.
In addition, you are using $('html, body').stop.animate({scrollTop: windowHeight}, slow); which has multiple errors. .stop is invalid because the stop property on the NodeList that is returned from $('html, body') is a function that you want to call. You should be using $('html, body').stop().
Also, the animate portion is referencing a variable slow. jQuery's animate function takes "slow" as a string, so that line should be written as such:
.animate({scrollTop: windowHeight}, "slow");
Note the inclusion of quotes on that because we want to pass a string value of "slow" to jQuery's animate function, instead of a variable slow.
Lastly, you are surrounding all of your code in an anonymous function, which seems unnecessary.
The context: I have a one page web app. So there's lots of div's being hidden at any one time (I'm not sure if this matters). What I am finding is that when a user is finished with one page (Page X), then they click back (to Page Y) - if they return back to Page X then the position is the same as when they left the page. The back button is at the bottom, so that's where the user ends up again.
What I want, is when they return to Page X for them to be at the top of the page so they can start again. Whether it scrolls back or just jumps back - either way is fine.
I've tried all of the following with no success:
// Scroll to top
setTimeout(function(){
alert('scroll');
$('html, body').animate({scrollTop : 0}, 2000);
}, 2000);
Adding a div with the id top-anchor at the top and using:
$('html, body').animate({
scrollTop: $("#top-anchor").offset().top
}, 2000);
Having a and using an anchor, with the code below (it only works once though, after that as the hash is already in the URL it no longer works I suppose):
document.hash = '#top-anchor';
Also tried:
window.scrollTo(0, 0);
No luck.
Any alternative ideas are much appreciated.
You can achieve something like that: DEMO : https://jsfiddle.net/yeyene/bpwtLg1w/1/
Not sure how your content divs are shown and hidden, but just get the idea of adding scroll to top of page div part.
Add scroll event on Back button click event, since you already known which page to go, you can scroll to this page's top, by using...
$(element).position().top
JQUERY
$(document).ready(function () {
$('input[type=button]').on('click', function(){
getPageID = $(this).attr('id');
$('.page').hide(0);
$('div#'+getPageID).show(0);
$('html,body').animate({
scrollTop: $('div#'+getPageID).position().top - 10
}, 500);
});
});
I am a jQuery novice but have got really close to achieving my result. Basically what I am trying to do is the following process:
From page load #anchor:
Convert the hash to an ID and a class
Scroll vertical to an element with the anchor ID
Scroll horizontal to a different element with a class
Additionally, the same functionality works when on the page. I am trying to direct link to the url.homl#hash so it is important that the animation effect works on the load as well.
My example is here: http://willminnig.com/stacko/vertical-test-5.html#1908
So far, I can get it to scroll to the vertical ID on page load but not the horizontal class, and also after the pages has loaded perfectly. It will also scroll to the class the very first time after the page loads perfectly, but is erratic behavior after the 1st time.
This is my (messy) jQuery:
$(window).bind("load", function() {
var mainhash = window.location.href.split("#")[1];
$('html, body').animate({
scrollTop: $('#'+mainhash).offset().top
}, 900, 'swing');
$('a[href^="#"]').bind('click',function() {
var target = this.hash; //target is whole #hash
var whatever = '.pics .'+this.hash.split("#")[1];
$whatever = $(whatever);
$target = $(target); //$target is $(#hash)
$('.pics').animate({
scrollLeft: $whatever.offset().left
}, 900, 'swing');
$('html, body').stop().animate({
scrollTop: $target.offset().top
}, 900, 'swing');
window.location.hash = target; //target is whole #hash
});
});
Any expertise explaining what I am doing wrong would be greatly appreciated! Additionally, I could change the way I am scrolling to the elements if it is recommended. The class/ID/hash was just the best I could come up with. Many thanks all!
To trigger the horizontal scroll on load all you need to do is trigger a click on the element with the id equal to 'mainhash'. You could achieve this by adding this line at the end of your 'load' handler:
$('#'+mainhash).trigger('click');
As for the erratic scrolling, well, it's a little complicated. $whatever's offset().left is $whatever's distance from the left side of the window, not its distance from the left side of .pics. When .pics .scrollLeft() is 0 (ie., when '1900' is flush to the left) then your animation will work correctly, otherwise it won't. I think the solution is to add the .pics .scrollLeft() amount to $whatever's offset().left so that you will have the value of $whatever's offset from the left side of .pics:
scrollLeft: ($('.pics').scrollLeft() + $whatever.offset().left)
Also, I think the 200% widths you have on #picswrap and .pics are wreaking havoc, though I am unable to explain precisely why. I think they should be changed to 100%.
Is it possible to add an anchor to this script? Instead of scrolling all the way to the top, I would like to scroll to a particular anchor in the page.
Here is the current script:
if (isError) {
$('html, body').animate({
scrollTop: 700
}, 2500);
$("#error-div").show();
} else {
$("#error-div").hide();
}
There's not really the need to include a huge plugin for this simple task.
With jQuerys position() - function (jQuery Doc) you can get the position of an element in the DOM (as long as it's visible). It returns an object with a top and left - value, relative to the parent. If you want values relative to the document, use the offset() - function, usage stays the same.
I created a little fiddle to show you the basic usage:
http://jsfiddle.net/DtADS/
Use the scrollto plugin, you can scroll the entire page to any element, or even scroll inside of elements. http://demos.flesler.com/jquery/scrollTo/
If I understood your question, you need to place something like that on the place in your page you want to scroll <div id="scrollHere"></div> and in your jquery:
window.location.href = "#scrollHere";
this method goes the page right where the #scrollHere rest, if that the case.