Jquery Smooth Scroll Onclick - javascript

I am currently using a smooth scroll script from css tricks.
The problem I'm having is that I have used 's as links with onclick links to anchor elements.
You can see it here. The problem is the script doesn't look for what I need it to, the links at the top (the divs) do not get found by the script so do not smoothly scroll to the anchor. Whereas the about, services, contact links (the text ones inside the green thingys) scroll smoothly.
I am complete jquery and javascript noob and do not know how to alter the script to include the onclick divs or to make a script to make it scroll smoothly to the anchors.
I need the script to scroll smoothly from both the div links and text links or I need a duplicate script that works with the div links (2 scripts that do text links and div links - The one I'm using atm only does text)
<script>
$(document).ready(function() {
function filterPath(string) {
return string
.replace(/^\//,'')
.replace(/(index|default).[a-zA-Z]{3,4}$/,'')
.replace(/\/$/,'');
}
var locationPath = filterPath(location.pathname);
var scrollElem = scrollableElement('html', 'body');
$('a[href*=#]').each(function() {
var thisPath = filterPath(this.pathname) || locationPath;
if ( locationPath == thisPath
&& (location.hostname == this.hostname || !this.hostname)
&& this.hash.replace(/#/,'') ) {
var $target = $(this.hash), target = this.hash;
if (target) {
var targetOffset = $target.offset().top;
$(this).click(function(event) {
event.preventDefault();
$(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
location.hash = target;
});
});
}
}
});
// use the first element that is "scrollable"
function scrollableElement(els) {
for (var i = 0, argLength = arguments.length; i <argLength; i++) {
var el = arguments[i],
$scrollElement = $(el);
if ($scrollElement.scrollTop()> 0) {
return el;
} else {
$scrollElement.scrollTop(1);
var isScrollable = $scrollElement.scrollTop()> 0;
$scrollElement.scrollTop(0);
if (isScrollable) {
return el;
}
}
}
return [];
}
});
</script>

I don't know if you use a javascript framework like jQuery. For websites like this I always use the jQuery plugin 'Localscroll'. It always works fine cross-browser.
You can see the documentation for the plugin here:
http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html
It's very easy to use.
Good luck!

You can use anchors instead of divs in the nav, right now you're doing
<div id="whatever" onclick="window.location=#portfolio">portfolio</div>
but that's not semantic, and it doesn't work the way you want it to, so that's doubleplus not good. use
<a id="whatever" href="#portfolio" style="display:block">portfolio</a>
then the code from css tricks should work... if it's clickable it should probably be a button or an anchor.
the anchor tags in your body work as expected, btw...

Related

I am trying to understand why this JS snippet isn't working, could use some guidance adding to WP

I am trying to mess around with some JS and using snippets trying to get them to work on clean WP installs so that I understand how to add them Wordpress properly.
I am working with JSFiddle
This is the link that im testing it on
(function() {
var delay = false;
$(document).on('mousewheel DOMMouseScroll', function(event) {
event.preventDefault();
if(delay) return;
delay = true;
setTimeout(function(){delay = false},200)
var wd = event.originalEvent.wheelDelta || -event.originalEvent.detail;
var a= document.getElementsByTagName('a');
if(wd < 0) {
for(var i = 0 ; i < a.length ; i++) {
var t = a[i].getClientRects()[0].top;
if(t >= 40) break;
}
}
else {
for(var i = a.length-1 ; i >= 0 ; i--) {
var t = a[i].getClientRects()[0].top;
if(t < -20) break;
}
}
$('html,body').animate({
scrollTop: a[i].offsetTop
});
});
})();
Here is the fiddle I am trying to implement.
It seems to be trying to do something on scroll and gets stuck.
Steps I have taken:
Added HTML to page
Added CSS to style.css
Added link to Jquery in header
Added the JS snippet in a tag before
I'm thinking maybe it has something to do with the fact that its got more elements on the page than just a and tag maybe? Seems to be getting caught on the header. This JS is just kind of hard for me to reverse engineer with the little that I know unfortunately.
Thanks.
The javascript listens to your mouse wheel event. If you mouse wheel up or down, it will first check if you're currently "wheeling" too fast. If you are, it will delay you. If you're not, then it will scroll (animate) to your next anchor tag and that anchor tag will be up top.
EDIT: I see you're getting a js error on your site. Remove the $ from the
$(function() {
var delay = false;
//blah blah
}

Updating the class name of Div based on top position

Actually i am trying to achieve smooth scrolling in Jquery, and whatever code i have written seems to be working fine, but i also want to implement a feature where my Nav Class Changes to active when user scroll down/up based on the position. Below link to code will give you more idea on what i am talking about. problem i am facing is even though i click on the next nav sub element active class is set to previous element. i have user window.scroll of query infact this part is actually got it from net. i really dint understand the code that is why its hard fa me debug and fix it, so if anyone is able to fix it, it would be really good if you explain me what this code is actually doing and what is the problem with current implementation.
http://codepen.io/anon/pen/GqJmK
JS
$(document).ready(function(){
var lastId,
header = $("#header"),
topMenu = $("#nav"),
topMenuHeight = topMenu.outerHeight()+header.outerHeight()+25,
menuItems = topMenu.find("a"),
//menuItems = topMenu.find("a:not([href^='http://'],[href^='/'])"),
scrollItems = menuItems.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
menuItems.on('click',function (e) {
e.preventDefault();
_this = this;
var target = _this.hash,
$target = $(target);
//menuItems.parent().removeClass("active");
//$(_this).parent().addClass("active");
$('html, body').stop().animate({
'scrollTop': ($target.offset().top) - topMenuHeight + 1
}, 900, 'swing', function () {
window.location.hash = target;
});
});
$(window).scroll(function(){
var fromTop = $(this).scrollTop()+topMenuHeight;
var cur = scrollItems.map(function(){
if (($(this).offset().top +20)< fromTop){
return this;
}
});
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
menuItems
.parent().removeClass("active")
.end().filter("[href=#"+id+"]").parent().addClass("active");
}
});
/*$( window ).resize(function() {
alert($( window ).width());
alert($( document ).width());
}); */
});
You might be best off using some sort of a plugin to achieve this effect. Something like http://lirancohen.github.io/stickUp/ or http://www.outyear.co.uk/smint/demo/ would do the trick
Just update your scroll check function & make your position check little more flexible i.e let it consider that you entered a section little before it enters it. Make this change on line 35 in your code -
if (($(this).offset().top - 50)< fromTop)
WORKING DEMO - http://codepen.io/nitishdhar/pen/LEAzI
You can also improve your UI by implementing this - http://css-tricks.com/hash-tag-links-padding/

Applying CSS based on scroll(function()

I've written a script that increases the nav menu top-margin when my website is loaded as a web app on an iPad, however I'd like to add a third condition: after the user scrolls down.
My current script:
<script type='text/javascript'>
jQuery("div").ready(function(){
if (("standalone" in window.navigator) && window.navigator.standalone) {
var array = window.navigator.userAgent.match("iPad"); if(array!=null && array.length == 1)
jQuery(".menu-secondary-wrap").css("marginTop", "20px");
};
});
</script>
I'd like to add:
jQuery(document).scroll(function(){
if(jQuery(this).scrollTop() > 175){
I'm just not sure how to do this - I can't seem to get the syntax right.
Any help would be really appreciated!
Add this script before the closing head tag
window.onscroll = function (e) {
var scrollTopVal = window.pageYOffset || document.body.scrollTop;
if(parseInt(scrollTopVal,10) > 175){
//Your Stuff Here
}
}
No need for jQuery. DEMO

Scrolling to Div IDs with Jquery

Due to css properties my scrolling to div tags has too much margin-top. So I see jquery as the best solution to get this fixed.
I'm not sure why this isn't working, I'm very new to Js and Jquery. Any help us greatly appreciated.
Here is a quick look at Js. I found that when your div ids are in containers to change the ('html, body') to ('container)
Here is my jsfiddle
jQuery(document).ready(function($){
var prevScrollTop = 0;
var $scrollDiv = jQuery('div#container');
var $currentDiv = $scrollDiv.children('div:first-child');
var $sectionid = 1;
var $numsections = 5;
$scrollDiv.scroll(function(eventObj)
{
var curScrollTop = $scrollDiv.scrollTop();
if (prevScrollTop < curScrollTop)
{
// Scrolling down:
if ($sectionid+1 > $numsections) {
console.log("End Panel Reached");
}
else {
$currentDiv = $currentDiv.next().scrollTo();
console.log("down");
console.log($currentDiv);
$sectionid=$sectionid+1;
console.log($currentDiv.attr('id'));
var divid =$currentDiv.attr('id');
jQuery('#container').animate({scrollTop:jQuery('#'+divid).position().top}, 'slow');
}
}
else if (prevScrollTop > curScrollTop)
{
// Scrolling up:
if ($sectionid-1 == 0) {
console.log("Top Panel Reached");
}
else {
$currentDiv = $currentDiv.prev().scrollTo();
console.log("up");
console.log($currentDiv);
$sectionid=$sectionid-1;
var divid =$currentDiv.attr('id');
jQuery('html, body').animate({scrollTop:jQuery('#'+divid).position().top}, 'slow');
}
}
prevScrollTop = curScrollTop;
});
});
I'm not entirely sure what you want but scrolling to a <div> with jQuery is simpler than your code.
For example this code replaces the automatic jumping behaviour of anchors with smoother scrolling:
$(document).ready(function(e){
$('.side-nav').on('click', 'a', function (e) {
var $this = $(this);
var top = $($this.attr('href')).offset().top;
$('html, body').stop().animate({
scrollTop: top
}, 'slow');
e.preventDefault();
});
});
You can of course adjust the top variable by adding or removing from it like:
var top = $($this.attr('href')).offset().top - 10;
I have also made a fiddle from it (on top of your HTML): http://jsfiddle.net/Qn5hG/8/
If this doesn't help you or your question is something different, please clarify it!
EDIT:
Problems with your fiddle:
jQuery is not referenced
You don't need jQuery(document).ready() if the jQuery framework is selected with "onLoad". Remove the first and last line of your JavaScript.
There is no div#container in your HTML so it's no reason to check where it is scrolled. And the scroll event will never fire on it.
Your HTML is invalid. There are a lot of unclosed elements and random tags at the end. Make sure it's valid.
It's very hard to figure out what your fiddle is supposed to do.

How to Set Offsett for Smooth Scroll

I have implemented the CSS Tricks Smooth Page Scroll on my site and it's working pretty nicely. However, because I have a fixed nav at the top of the page, when the page scrolls to the appropriate anchor div, the top of the div disappears behind the nav. How can I offset the scroll (about 70px) so that the whole div is shown? I tried doing this:
var targetOffset = $target.offset().top - 70;
But that doesn't quite work. The page scrolls to the appropriate spot but then it immediately jumps back up so that the top of the div is hidden. What am I missing? Here's the code in full:
$(function() {
function filterPath(string) {
return string
.replace(/^\//,'')
.replace(/(index|default).[a-zA-Z]{3,4}$/,'')
.replace(/\/$/,'');
}
var locationPath = filterPath(location.pathname);
var scrollElem = scrollableElement('html', 'body');
// Any links with hash tags in them (can't do ^= because of fully qualified URL potential)
$('a[href*=#]').each(function() {
// Ensure it's a same-page link
var thisPath = filterPath(this.pathname) || locationPath;
if ( locationPath == thisPath
&& (location.hostname == this.hostname || !this.hostname)
&& this.hash.replace(/#/,'') ) {
// Ensure target exists
var $target = $(this.hash), target = this.hash;
if (target) {
// Find location of target
var targetOffset = $target.offset().top - 70;
$(this).click(function(event) {
// Prevent jump-down
event.preventDefault();
// Animate to target
$(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
// Set hash in URL after animation successful
location.hash = target;
});
});
}
}
});
// Use the first element that is "scrollable" (cross-browser fix?)
function scrollableElement(els) {
for (var i = 0, argLength = arguments.length; i <argLength; i++) {
var el = arguments[i],
$scrollElement = $(el);
if ($scrollElement.scrollTop()> 0) {
return el;
} else {
$scrollElement.scrollTop(1);
var isScrollable = $scrollElement.scrollTop()> 0;
$scrollElement.scrollTop(0);
if (isScrollable) {
return el;
}
}
}
return [];
}
});
Thanks in advance for your help.
This always happens. I search and search for an answer, get frustrated, post a question asking for help, and then immediately find an answer to my problem. Silly. Anyway, here's the solution for anyone who might be having the same problem.
If you want to change the offset by 70px, for example, change the code to this:
var targetOffset = $target.offset().top - 70;
However, unless you remove this line from the code...
location.hash = target;
... the page will scroll to the right spot and then immediately jump back up so that the top of the div is hidden behind the header. You can remove the above line from the code and everything will work great, except for the fact that the URL will no longer change to reflect the user's position on the page.
If you want the URL to change (and I think this is a good idea for usability purposes), then all you have to do is change the CSS for the anchor divs. Add a positive value for padding-top and a negative value for margin-top. For example:
#anchor-name {
padding-top: 70px;
margin-top: -70px;
}
I only have 3 divs, so I just plugged in that CSS to each of them and voila, everything worked. However, if you have a lot of anchor divs, you might consider creating a class of .anchor, putting the CSS there, and applying the class to all the appropriate divs.
I hope this helps!
I have fixed such a kind of issue with below code:
Working demo HERE. You can play with "Post Topics" section in the sidebar and content in the main-content area.
Code
jQuery(function() {
jQuery('a[href*=#]:not([href=#])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = jQuery(this.hash);
target = target.length ? target : jQuery('[name=' + this.hash.slice(1) +']');
if (target.length) {
jQuery('html,body').animate({
scrollTop: target.offset().top -100
}, 1000);
return false;
}
}
});
});
Refer to https://codepen.io/pikeshmn/pen/mMxEdZ
Approach: We get the height of fixed nav using document.getElementById('header').offsetHeight
And offset the scroll to this value.
var jump=function(e){
e.preventDefault(); //prevent "hard" jump
var target = $(this).attr("href"); //get the target
//perform animated scrolling
$('html,body').animate(
{
scrollTop: $(target).offset().top - document.getElementById('header').offsetHeight - 5 //get top-position of target-element and set it as scroll target
},1000,function() //scrolldelay: 1 seconds
{
location.hash = target; //attach the hash (#jumptarget) to the pageurl
});
}
$(document).ready(function()
{
$('a[href*="#"]').bind("click", jump); //get all hrefs
return false;
});
Actually there's a CSS rule for that : scroll-padding-top :)
Combined with a regular padding-top for the top-most element of course.
cf. https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-padding-top
CSS scroll margin or padding
/* Scroll to 2rem above the target */
:target {
scroll-margin-top: 2rem;
}
/* Bonus for a smooth scrolling experience */
body {
scroll-behavior: smooth;
}
Read more about scroll margin and scroll padding on MDN.

Categories