This one may be simple for the jQuery/JavaScript gurus here, but I just can't find a solution for it around the web.
Case
I have a link at the bottom of a page that says Back to Top, the link is simply a target link like this:
Back to Top
So when you click it, it jumps to the top of page. Simple.
Problem
When the target link is clicked, the id #top is added to the URL of the page, ie:
http://website.com/about-us/#top
Question
Is there a way to remove or avoid getting that id #top added to the URL of the page but retain the functionality of the page jumping to the top?
Any help with this is greatly appreciated.
In either case (jQuery or vanilla JavaScript), you'll want to do the following:
Select all anchor tags where href is set to #top
Create a "jump" function which sets the page position to the top and returns false to prevent the default link behavior
Bind the "jump" function to the click event of all of the nodes found
To jump you have several options. I've provided them (jQuery and JS specific) in the first example below.
Using jQuery
jQuery makes selecting and binding to a click event easy. Then you can jump to the top of the page using jQuery or straight JavaScript.
$('a[href="#top"]').click(function() {
//
// To jump, pick one...
//
// Vanilla JS Jump
window.scroll(0,0)
// Another Vanilla JS Jump
window.scrollTo(0,0)
// jQuery Jump
$('html,body').scrollTop(0);
// Fancy jQuery Animated Scrolling
$('html,body').animate({ scrollTop: 0 }, 'slow');
//
// ...then prevent the default behavior by returning false.
//
return false;
});
jQuery's animate provides options for animation duration and easing along with the ability to set a callback.
Vanilla JavaScript
You can also use Vanilla JS the whole way through... Querying and binding, however, become a bit more painful.
Modern browsers support document.querySelectorAll() which will allow you to grab all of the link elements just as you would with jQuery:
var links = document.querySelectorAll('a[href="#top"]');
Then loop over the elements and bind the "jump":
for (var i = links.length - 1; i >= 0; i--) {
links[i].onclick = function() { window.scroll(); return false; };
};
If your target browser doesn't gift you with querySelectorAll you just loop through all of the anchor tags to find the ones linked to #top:
var links = document.body.getElementsByTagName('a');
for (var i = links.length - 1; i >= 0; i--) {
var l = links[i];
if(l.getAttribute('href') === '#top') {
l.onclick = function() { window.scroll(); return false; }
}
}
$('a[href=#top]').click(function(){
$(window).scrollTop(0);
return false;
});
You need to stop the tag a's default event to trigger.
When handling anchor click events, always use e.preventDefault(); On Click of Anchor element. When you don't need anchor element.
e.preventDefault();
$('html, body').animate({ scrollTop: 0 }, 'slow');
This will work
$('a.standard').click(function() {
$('body,html').animate({
scrollTop: 0
});
});
Related
I've searched hours and finally found a light jQuery code which allows me to animate the click of an anchor link, but when I click on one link it animates down and then jump 100px to the top without animation because the hash is given to the url after the animation which leads to the default anchor link behavior when you click it.
I have a code sample for you with a little comment from me for a fix, or well I thought It'll be a fix...
// Scroll.js (https://css-tricks.com/snippets/jquery/smooth-
scrolling/#comment-1635851)
/*
* Scroll.js:
* 1. added -100 after the .top property which reflects the navigation height.
*/
$(document).ready(function(){
// Add smooth scrolling to all links
$('a').on('click', function(e) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
e.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-100 // /* [1] */
}, 800, function(){
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
});
Just write on the anchor href attribute javascript::void(0) as in
Though if you want it to act as an anchor and have a url... this will not work :(
I'm trying to scroll to the next section on the page based on the viewport. I do not want to keep track of each element and if they have been visited, because if the user decides to scroll up again, it should just scroll to the next section anyway. Hence why I came up with this solution:
https://jsfiddle.net/w28tfnm9/
$("#scroll-down").on("click", function() {
$(".section").each(function() {
var isInViewPort = $(this).isInViewport();
if (isInViewPort) {
$("html, body").animate({
scrollTop: $(this).next().offset().top
}, 500);
return false;
}
});
});
However, I have a slight issue: It will not scroll to the first element. That makes sense, since I check if the current element is in the viewport, then I scroll to the .next() element, but I can't figure out how to solve this, without messing up what I already have. Is there a better way?
Instead of saying .next(), I essentially want it to go to the next .section element. Since it's not guaranteed the .next() element is a section, this is not a "good" solution.
So I ended up with a hack:
https://jsfiddle.net/w28tfnm9/3/
$(window).on("scroll", function() {
if($("body").scrollTop() < $(".section").offset().top) {
hasScrolled = false;
} else {
hasScrolled = true;
}
});
I basically iterate through each element, if i === 0 it means I am at the top, but since I am trying to grab the next using .get(), I need to set the current iteration to -1. Works like a charm and "resets" when I scroll above the first element.
This is my code: Js Fiddle
As you can see I have several sections on top of each other with 100% height. I want to know how I can get it so when the user clicks on "learn more" they scroll to the next section, so the top of the section is at the top of the page.
Normally it would be quite simple as I could do this:
$('body').animate({
scrollTop:$(document).height()
});
However this won't work if the user has already scrolled halfway down on of the sections and then hits the button. It would also be good if I could use the same function for each button press, instead of having three different functions, one for each different section.
I guess the code would be something like (in pseudo): scroll to top sectiona + 1
with jQuery and smooth scrolling
$('a').click(function(){
var nextSection = $(this).closest('section').next('section');
$('html, body').animate({
scrollTop: $(nextSection).offset().top
}, 2000);
});
Why not you pass id's to each section and in href refer to that id like
<section id="sectionOne">
Move to section two
</section>
<section id="sectionTwo">
Move to section one
</section>
You can also try the following.
var amount_to_scroll_by = $(document).scrollTop() + element_to_scroll.getBoundingClientRect().top);
$(document).scrollTop(amount_to_scroll_by); // animate this scroll
Hope this helps :)
Using jquery, you can smoothly scroll to the target.
Here is a SAMPLE
JS:
$("a").click(function(e) {
e.preventDefault();
var target = $(this).attr('href');
$('html, body').animate({ scrollTop : $(target).offset().top + "px"});
});
You should first fix up your anchors and use the hash fragments to allow for native navigation between anchors.
I have created a very simple demo for you to understand this (not using your markup to keep it simple).
Demo: http://jsfiddle.net/abhitalks/9uxGq/15/
(another demo with your markup: http://jsfiddle.net/abhitalks/9uxGq/19/)
You need two anchors, one as click link and the other to mark the position of target as anchor.
For example:
<div>
<a id="LearnMore1"></a> <!-- Used for marking the anchor with hash fragment -->
<h2>Sub Heading 2</h2>
<p>
Some text content here
</p>
Learn More <!-- Used to click to got to next anchor -->
</div>
Note: Of course instead of using a second anchor as a marker, you could use the div (or in your case section) with an id. But, an a is better because it is more semantic for content navigation and it means an anchor.
Once done, this becomes a fallback for you. Now you can easily implement animations using jQuery etc.
It would be as simple as this:
// bind click on anchors (use selectors as per your requirements)
$("a").on("click", function(e) {
e.preventDefault(); // prevent the default behaviour
var nextAnchor = this.hash.replace("#", ""); // get the next marker anchor
var gotoPoint = $("#" + nextAnchor).position().top; // get the position of marker
$('body').animate({ scrollTop: gotoPoint }, 'normal'); // animate the body
});
Alternatively:
// bind click on anchors (use selectors as per your requirements)
$("a").on("click", function(e) {
e.preventDefault(); // prevent the default behaviour
var nextAnchor = $(this).attr('href'); // get the next marker anchor
var gotoPoint = $(nextAnchor).position().top; // get the position of marker
$('body').animate({ scrollTop: gotoPoint }, 'normal'); // animate the body
});
Now applying this to your use case, the demo becomes: http://jsfiddle.net/abhitalks/9uxGq/19/
Hope that helps, and you can work it out in your markup and use-case.
.
I'm currently working on a site which uses the javascript code below to animate over to the target element inside an href. How would I go about getting the code to animate when the back/forward buttons are clicked based on it's history.
/* ------ Smooth Scroll ----- */
$(document).ready(function() {
"use strict";
$('a[href*=#]').bind('click', function(e) {
e.preventDefault(); //prevent the "normal" behaviour which would be a "hard" jump
var target = $(this).attr("href"); //Get the target
// perform animated scrolling by getting top-position of target-element and set it as scroll target
$('html, body').stop().animate({ scrollTop: $(target).offset().top}, 2000, function()
{
location.hash = target; //attach the hash (#jumptarget) to the pageurl
});
return false;
});
});
You need to listen for the hash change. There are many ways to do this. You can poll for hash change or use HTML5's history api with onhashchange method to listen for changes. The easiest way to do this is probably using some kind of library that already takes care of both. I recommend jquery plugin if you are using jquery. If you are using angular js or other stuff then look for those plugins.
You would do something like
$(window).hashchange( function(){
// Do the animation here
})
You would no longer need to animate on a click.
I am an html css design type who is not that comfortable with jquery. I have inherited a site with the link default behaviours disabled with what I can see is this code:
$('a').click(function(event) {
event.preventDefault();
var locationHref = window.location.href;
var elementClick = $(this).attr("href");
var destination = $(elementClick).offset().top;
$("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination}, 1000, function() {
window.location.hash = elementClick
});
return false;
I need to add normal links to this one page website without messing with this code (it enables parallax scrolling). Is there any way I can do this link by link?
BTW I have seen solutions on here but I must confess to not quite understanding them. Thanks.
Not sure why anyone would blanket disable ALL links on a page in this way. Unfortunate that you've inherited such code. I wasn't sure if you meant you couldn't touch that code, or merely didn't want to.
If the former, you have two options:
1) Unbind this click event for certain links. For example, if you had links inside a container, #container, or all your links had a certain class, .class, you could do this:
$('#container a').off('click');
$('a.class').off('click');
These links would then be free of the inherited click event handler.
The only problem with this is you unbind all click event handlers bound to such links. Since the inherited event isn't namespaced, this is unavoidable. A second option is to...
2) Set up a second click event handler that bypasses the default action prevention of the inherited handler by forwarding users on to the link's HREF nonetheless:
$('a').on('click', function() { location.href = $(this).attr('href'); });
How about giving these special links a data-donthandle="true" attribute. Then, check for this attribute in the jQuery. If the attribute exists and is false, simply return true; at the beginning of the event handler.
This would save you looking through and disabling the onclick via javascript as already suggested.
$('a').click(function(event) {
if($(this).attr('data-donthandle')) {
return true;
}
else {
event.preventDefault();
//code here for handling clicks
alert('Stopped.');
return false;
}
});