Scroll to id function jQuery - javascript

So I have been making onepage websites for a while now, and one thing witch is always annoys me is navigation functions witch i'm repeating for the amount of buttons and id's I have.
It looks like the following:
$('#homeB').click(function () {
$('html, body').animate({
scrollTop: $("#home").offset().top
}, 1000);
return false;
});
$("#aboutB").click(function() {
$('html, body').animate({
scrollTop: $("#about").offset().top
}, 1000);
return false;
});
$("#winesB").click(function() {
$('html, body').animate({
scrollTop: $("#wines").offset().top
}, 1000);
return false;
});
Question is, how do I change from here to a small function that does not need repeating.
Thanks.
Note: Preferably no 3rd party plugins etc. keep it in JavaScript/jQuery.

To avoid writing duplicate code, you could do a little something like this:
$(function() {
$('li').on('click', function(e) {
e.preventDefault();
$('html, body').animate({
scrollTop: $($(e.target).attr("href")).offset().top
}, 1000);
});
});
nav {
position: fixed;
top: 0;
left: 0;
}
div {
margin: 100px 0 0 0;
width: 100%;
height: 500px;
}
div:nth-child(even) {
background: #ccc;
}
div:nth-child(odd) {
background: #4c4c4c;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</nav>
<div id='1'></div>
<div id='2'></div>
<div id='3'></div>
<div id='4'></div>

function scrollTo($element) {
$('html, body').animate({
scrollTop: $element.offset().top
}, 1000);
return false;
}
then you can use it as
$('#homeB').click(function () {
scrollTo($("#home"));
});
$("#aboutB").click(function() {
scrollTo($("#about"));
});
$("#winesB").click(function() {
scrollTo($("#wines"));
});

There are a couple ways of tackling this. If I were to be doing it, I would make whatever is being clicked a class and then setting a data attribute to the destination id, like this
<span class='nav_link' data-dest='home2'>Click me to go to home 2</span>
Then you could do something like this
$('.nav_link').click(function() {
var dest = $(this).attr('data-dest');
$('html, body').animate({
scrollTop: $('#'+dest).offset().top
}, 1000);
})

Related

Previous and next buttons that navigate through a single page

Still a noob but I am slowly getting there.
I have a series of divs, all the same class and I have previous and next buttons that scroll to the top of the next or previous div when clicked. I would like to set an offset so that my header won't hide the div that scrolls underneath of it and I am unsure how to go about this. Code below.
<button class="prev link js-prev js-scroll-to">Previous</button>
<button class="next link js-next">Next</button>
<script>
$('.js-scroll-to').click(function(e) {
target = $($(this).attr('href'));
if (target.offset()) {
$('html, body').animate({scrollTop: target.offset().top + 'px'}, 1000);
}
e.preventDefault();
});
$('.js-next').click(function(e) {
var selected = $(".js-list-item.js-current-panel");
var anchors = $(".js-list-item");
var pos = anchors.index(selected);
var next = anchors.get(pos+1);
var prev = anchors.get(pos-1);
target = $(next);
$(selected).removeClass("js-current-panel");
$(next).addClass("js-current-panel");
if (target.offset()) {
$('html, body').animate({scrollTop: target.offset().top + 'px'}, 1000);
}
e.preventDefault();
});
$('.js-prev').click(function(e) {
var selected = $(".js-list-item.js-current-panel");
var anchors = $(".js-list-item");
var pos = anchors.index(selected);
var next = anchors.get(pos+1);
var prev = anchors.get(pos-1);
target = $(prev);
$(selected).removeClass("js-current-panel");
$(prev).addClass("js-current-panel");
if (target.offset()) {
$('html, body').animate({scrollTop: target.offset().top + 'px'}, 1000);
}
e.preventDefault();
});
</script>
For your case, I think you could just add the offset right into your animated scroll code (subtracting the height of the nav bar plus a little margin):
$('html, body').animate({scrollTop: target.offset().top - 54 + 'px'}, 1000);
I usually do this without a JS scroll by adding a span class to use as the anchor instead of anchoring on the div itself. This will work if someone links directly to the anchor point as well.
That way I can use position relative on the anchor to set an offset for the height of the nav bar.
In this case, I think you probably have some divs like this:
<div class="js-list-item js-current-panel">
content
</div>
<div class="js-list-item">
content
</div>
<div class="js-list-item">
content
</div>
I'd change it to:
<span class="anchor js-list-item js-current-panel"></span>
<div class="content">
content
</div>
<span class="anchor js-list-item"></span>
<div class="content">
content
</div>
<span class="anchor js-list-item"></span>
<div class="content">
content
</div>
With some CSS to position those new anchors (top depends on nav bar height):
.anchor {
position: relative;
top: -54px;
}
Example with some extra CSS to show how the anchors are positioned:
<style type="text/css">
.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 44px;
background: black;
}
.main {
margin-top: 54px;
}
.js-list-item {
display: inline-block;
width: 5px;
height: 5px;
background: blue;
position: relative;
top: -54px;
}
.content {
background: red;
width: 100%;
height: 500px;
margin-bottom: 25px;
}
</style>
<div class="nav">
<button class="prev link js-prev js-scroll-to">Previous</button>
<button class="next link js-next">Next</button>
</div>
<div class="main">
<span class="js-list-item js-current-panel"></span>
<div id="one" class="content">content</div>
<span class="js-list-item"></span>
<div id="two" class="content">content</div>
<span class="js-list-item"></span>
<div id="three" class="content">content</div>
<span class="js-list-item"></span>
<div id="four" class="content">content</div>
<span class="js-list-item"></span>
<div id="five" class="content">content</div>
<span class="js-list-item"></span>
<div id="six" class="content">content</div>
<span class="js-list-item"></span>
<div id="seven" class="content">content</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
$('.js-scroll-to').click(function(e) {
target = $($(this).attr('href'));
if (target.offset()) {
$('html, body').animate({scrollTop: target.offset().top + 'px'}, 1000);
}
e.preventDefault();
});
$('.js-next').click(function(e) {
var selected = $(".js-list-item.js-current-panel");
var anchors = $(".js-list-item");
var pos = anchors.index(selected);
var next = anchors.get(pos+1);
var prev = anchors.get(pos-1);
target = $(next);
$(selected).removeClass("js-current-panel");
$(next).addClass("js-current-panel");
if (target.offset()) {
$('html, body').animate({scrollTop: target.offset().top + 'px'}, 1000);
}
e.preventDefault();
});
$('.js-prev').click(function(e) {
var selected = $(".js-list-item.js-current-panel");
var anchors = $(".js-list-item");
var pos = anchors.index(selected);
var next = anchors.get(pos+1);
var prev = anchors.get(pos-1);
target = $(prev);
$(selected).removeClass("js-current-panel");
$(prev).addClass("js-current-panel");
if (target.offset()) {
$('html, body').animate({scrollTop: target.offset().top + 'px'}, 1000);
}
e.preventDefault();
});
</script>

How to combine this scripts correctly?

I have 2 scripts which can't work parallel. The first one is for scrolling to the search bar when it's focused, the other one removes focus when youre scrolling (to remove keyboard on mobile).
Is there a way to combine these scripts, to have it scrolling first to the search bar and then have the second script get activated if you scroll again for removing the keyboard? Because right now it's scrolling to the search bar and then it loses focus.
To scroll it to the search bar:
$("#myInput").click(function () {
$("html, body").animate({ scrollTop: $("#osb").offset().top }, 300);
return true;
});
To remove focus when scrolling again:
document.addEventListener("scroll", function() {
document.activeElement.blur();
});
Thanks already!
Example:
$("#myInput").click(function() {
document.removeEventListener("scroll", blurElement);
$("html, body").animate({
scrollTop: $("#b").offset().top
}, 300, function() {
document.addEventListener("scroll", blurElement);
});
return true;
});
function blurElement() {
document.activeElement.blur();
}
document.addEventListener("scroll", blurElement);
#a {
height: 100px;
background: #aaa;
}
#b {
background: #bbb;
}
#c {
height: 1000px;
background: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a">
</div>
<div id="b">
<input type="text" id="myInput" placeholder="search.." title="">
</div>
<div id="c">
^ need this stay focused untill I scroll again
</div>
Maybe using a flag to prevent "blurring" while your animation is running;
var allowBlur = true;
$("#myInput").click(function () {
allowBlur = false;
$("html, body").animate({ scrollTop: $("#osb").offset().top }, 300, function() {
allowBlur = true;
});
return true;
});
document.addEventListener("scroll", function() {
if(!allowBlur) return;
document.activeElement.blur();
});
Attempt #2
$("#myInput").click(function () {
document.removeEventListener("scroll", blurElement);
$("html, body").animate({ scrollTop: $("#osb").offset().top }, 300, function() {
document.addEventListener("scroll", blurElement);
});
return true;
});
function blurElement() {
document.activeElement.blur();
}
document.addEventListener("scroll", blurElement);
Attempt #3
It appears that for some reason the "scroll" event is still being sent even when the animation is done. So based on this answer https://stackoverflow.com/a/8791175/1819684 I used a promise but I still needed a setTimeout to give the "scroll" time to end.
$("#myInput").click(function() {
document.removeEventListener("scroll", blurElement);
$("html, body").animate({
scrollTop: $("#b").offset().top
}, 300).promise().done(function() {
setTimeout(function() {
document.addEventListener("scroll", blurElement)
}, 100);
});
return true;
});
function blurElement() {
document.activeElement.blur();
}
document.addEventListener("scroll", blurElement);
#a {
height: 100px;
background: #aaa;
}
#b {
background: #bbb;
}
#c {
height: 1000px;
background: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a">
</div>
<div id="b">
<input type="text" id="myInput" placeholder="search.." title="">
</div>
<div id="c">
</div>

Smooth scrolling unit without using the attribute a [href ^ = "#"]

How to implement the transition when you click on the block with the class
<div class="btn">button-scroll </div>
Do not use aa [href ^ = "#"] One
<aside>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
<li>Six</li>
</ul>
</aside>
$(document).ready(function(){
// = Вешаем событие прокрутки к нужному месту
// на все ссылки якорь которых начинается на #
$('a[href^="#"]').bind('click.smoothscroll',function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top-($('ul').height()+ 100)
}, 900, 'swing', function () {
window.location.hash = target;
});
});
});
#main h2 {
margin-top:400px;
}
ul{
position:fixed;
top: 0px;
}
ul li{
display:inline-block;
}
Hi you can try with following
Instead of <div class="btn">button-scroll </div> add attribute 'target'like <div class="btn" target="targetDivId">button-scroll </div>
and in JavaScript
$(document).ready(function(){
$('.btn').bind('click',function (e) {
e.preventDefault();
var target = $(this).attr('target'),
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top-(100)
}, 900, 'swing');
});
});

Scroll to next section

My code looks like this:
<div id="arrow">
<a class="next"></a>
<a class="previous"></a>
</div>
<section id="first">
...
</section>
<section id="second">
...
</section>
<section id="third">
...
</section>
The element #arrow has position: fixed, and I'm trying to make the window scroll to the next section when a.next is clicked.
Ex: The first time a.next is clicked, the window scrolls to section#first, the second time, the window scrolls to section#second, etc. The same thing happens to a.previous.
Does someone know how to solve this problem?
Thanks a lot!
EDIT
My JS code:
$('#arrows a.previous').click(function() {
$.scrollTo($(this).closest('section').prev(),800);
});
$('#arrows a.next').click(function() {
$.scrollTo($(this).closest('section').next(),800);
});
You will need to handle to 3 events in this case:
Current page position - updated each time.
User scrolls manualy the page.
User clicks the prev or next button.
2, 3 need to use the current page position and update him according to the direction that the page is scrolling.
My quick demos : Vertical Version jsFiddle --- Horizontal Version jsFiddle
Vertical Version snippet :
$(function(){
var pagePositon = 0,
sectionsSeclector = 'section',
$scrollItems = $(sectionsSeclector),
offsetTolorence = 30,
pageMaxPosition = $scrollItems.length - 1;
//Map the sections:
$scrollItems.each(function(index,ele) { $(ele).attr("debog",index).data("pos",index); });
// Bind to scroll
$(window).bind('scroll',upPos);
//Move on click:
$('#arrow a').click(function(e){
if ($(this).hasClass('next') && pagePositon+1 <= pageMaxPosition) {
pagePositon++;
$('html, body').stop().animate({
scrollTop: $scrollItems.eq(pagePositon).offset().top
}, 300);
}
if ($(this).hasClass('previous') && pagePositon-1 >= 0) {
pagePositon--;
$('html, body').stop().animate({
scrollTop: $scrollItems.eq(pagePositon).offset().top
}, 300);
return false;
}
});
//Update position func:
function upPos(){
var fromTop = $(this).scrollTop();
var $cur = null;
$scrollItems.each(function(index,ele){
if ($(ele).offset().top < fromTop + offsetTolorence) $cur = $(ele);
});
if ($cur != null && pagePositon != $cur.data('pos')) {
pagePositon = $cur.data('pos');
}
}
});
section { min-height:800px; }
#arrow {
position:fixed;
right:0;
top:0;
background-color:black;
color:white;
}
#arrow a{
display:inline-block;
padding:10px 20px;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="arrow">
<a class="next">next</a>
<a class="previous">prev</a>
</div>
<section style="background-color:green">...</section>
<section style="background-color:blue">...</section>
<section style="background-color:red">...</section>
All you need, to allow the user to use both arrows and scrollbar:
var $sec = $("section");
$(".prev, .next").click(function(){
var y = $sec.filter(function(i, el) {
return el.getBoundingClientRect().bottom > 0;
})[$(this).hasClass("next")?"next":"prev"]("section").offset().top;
$("html, body").stop().animate({scrollTop: y});
});
*{margin:0;padding:0;}
#arrow{
position:fixed;
width:100%;
text-align:center;
}
#arrow a{
display:inline-block;
background: tomato;
padding:6px 15px;
border-radius:3px;
cursor:pointer;
}
section{
height:1200px;
border:3px solid #444;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="arrow"><a class="prev">↑</a><a class="next">↓</a></div>
<section>1</section>
<section style="height:500px;">2</section>
<section>3</section>
<section style="height:600px;">4</section>
<section>5</section>
To explain the jQuery a bit:
// Cache your selectors
var $sec = $("section");
// On any of both arrows click
$(".prev, .next").click(function(){
// We need to get current element
// before defining the `.next()` or `.prev()` element to target
// and get it's `offset().top` into an `y` variable we'll animate to.
// A current element is always the one which bottom position
// (relative to the browser top) is higher than 0.
var y = $sec.filter(function(i, el) {
return el.getBoundingClientRect().bottom > 0;
})[$(this).hasClass("next")?"next":"prev"]("section").offset().top;
// (Line above:) if the clicked button className was `"next"`,
// target the the `.next("section")`, else target the `.prev("section")`
// and retrieve it's `.offset().top`
$("html, body").stop().animate({scrollTop: y});
});
i have tried to do with .closest("section") but it only works when the section is a parent of the element you clicked so this is the best way i got
sections=$("section");
s=0;
$(".next").click(function() {
if(s<sections.length-1){
s++;
$('html, body').animate({
scrollTop: sections.eq(s).offset().top
}, 500);
}});
$(".previous").click(function() {
if(s>0){
s--;
$('html, body').animate({
scrollTop: sections.eq(s).offset().top
}, 500);
}});
section{
background-color:#bbb;
width:100%;
height:700px;
border-bottom:2px solid #eee;
}
#arrow{
position:fixed;
}
#first{
background-color: red;
}
#second{
background-color:green;
}
#third{
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="arrow">
<a class="next">next</a>
<a class="previous">prev</a>
</div>
<section id="first">
...
</section>
<section id="second">
...
</section>
<section id="third">
...
</section>

Animate content in a list

I want to make it so that when I hover over one of the items in a list, it moves that element.
Here is my HTML code for the list:
<ul class="nav">
<li class="test">Home</li>
<li>News</li>
<li>About us</li>
<li>Venue</li>
<li>Affiliations</li>
<li>Players & Officers</li>
<li>Fixtures & Results</li>
<li>Coaching</li>
<li>Contact us</li>
</ul>
And here is my Jquery code:
$(document).ready(function() {
$('').mouseenter(function() {
$(this).animate({ left: '+=100px' });
});
$('').mouseleave(function() {
$(this).animate({ left: '-=100px' });
});
});
Basically, my question is what goes in the quote marks in the JQuery functions?
Use the on event
$(document).ready(function () {
$('.nav').on({
mouseenter : function(){
$(this).animate({left: '+=100px'});
},
mouseleave : function(){
$(this).animate({left: '-=100px'});
}
}, 'li');
});
Try this:
$(document).ready(function()
{
$('.nav li').mouseenter(function()
{
$(this).animate({left: '+=100px'});
});
$('.nav li').mouseleave(function()
{
$(this).animate({left: '-=100px'});
});
});
You can use $('.nav li') to target list items of your nav:
$(document).ready(function () {
$('.nav li').mouseenter(function () {
$(this).animate({
left: '+=100px'
});
});
$('.nav li').mouseleave(function () {
$(this).animate({
left: '-=100px'
});
});
});
Also, you need to set position: relative for your list items, so the left value can work:
.nav li {
position: relative;
}
Fiddle Demo
You might want to consider the .on and event map approach.
$('.nav').on({
mouseenter : function(){
$(this).animate({left: '+=100px'});
},
mouseleave : function(){
$(this).animate({left: '-=100px'});
}
}, 'li');
HTML Code:
<ul class="nav">
<li>Home</li>
<li>News</li>
<li>About us</li>
<li>Venue</li>
<li>Affiliations</li>
<li>Players & Officers</li>
<li>Fixtures & Results</li>
<li>Coaching</li>
<li>Contact us</li>
</ul>
Javascript:
$(document).ready(function () {
$('.nav li').mouseenter(function () {
$(this).animate({
left: '+=100px'
});
});
$('.nav li').mouseleave(function () {
$(this).animate({
left: '-=100px'
});
});
});
A little CSS tweek to make the list hover animation work:
.nav {
padding: 20px 0 0 20px;
}
.nav li {
position: relative;
}
Check the demo at: DEMO

Categories

Resources