Show div when scroll to specific ID and after X seconds - javascript

I would like to show a div when user scroll to a specific ID but I want that this div appears only after X seconds since the ID is reached by scrolling.
How could I edit this fiddle to do it?
$(document).ready(function() {
$("#dvid").hide(); //hide your div initially
var topOfOthDiv = $("#othdiv").offset().top;
$(window).scroll(function() {
if($(window).scrollTop() > topOfOthDiv) { //scrolled past the other div?
$("#dvid").show(200); //reached the desired point -- show div
}
});
});
http://jsfiddle.net/DnJ2z/11/

I did add only a setTimeout and more height of the body to your code and it seems to work. Play with the snippet and ask in comments if you have any questions.
If you want to do something after some delay you can use setTimeout and if you want to do something periodically you can use setInterval. These are both javascript functions and not jQuery.
If you want you can see the jQuery's .delay() method also
$(document).ready(function() {
$("#dvid").hide(); //hide your div initially
var topOfOthDiv = $("#othdiv").offset().top;
var delay = 500;
$(window).scroll(function() {
if ($(window).scrollTop() > topOfOthDiv) { //scrolled past the other div?
setTimeout(function() {
$("#dvid").show(200); //reached the desired point -- show div
}, delay);
}
});
$('#update').on('click', function() {
delay = $('#delay').val();
});
$('#hide').on('click', function() {
$("#dvid").hide(200);
});
});
body {
height: 1200px;
font-family: 'Arial', Helvetica, Sans-Serif;
color: white;
font-weight: bold;
}
#othdiv {
height: 30px;
background-color: rgb(0, 140, 200);
/*just wanted this to be pretty :)*/
position: absolute;
top: 100px;
left: 0px;
}
#dvid {
background-color: rgb(34, 177, 76);
height: 50px;
position: absolute;
top: 140px;
left: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="delay" value="500">
<button id="update">Update Delay</button>
<button id="hide">Hide</button>
<div id="othdiv">
If you scroll past me, then you'll see the other div.
</div>
<div id="dvid">
Oh hello! :D
</div>

You just have to add setTimeout() method in your existing function. So just wrap your div.show inside of the setTimeout
$(document).ready(function() {
$("#dvid").hide(); //hide your div initially
var topOfOthDiv = $("#othdiv").offset().top;
$(window).scroll(function() {
if($(window).scrollTop() > topOfOthDiv) { //scrolled past the other div?
setTimeout(function(){$("#dvid").show(200); }, 1000);
}
});
});
This here will show your div 1 second after you scroll to it.
JSFiddle

You could just use a setTimeout
var millis = 2000;
setTimeout(function() {
$("#dvid").show(200); //reached the desired point -- show div
}, millis);
But keep in mind, that this will retrigger everytime you scroll by your "breakpoint". So you should adjust this and clear your timeout first if necessary or use a flag and don't try to show it again:
$(document).ready(function() {
var divIsShown = false;
var millis = 2000; // 2 seconds
$("#dvid").hide(); //hide your div initially
var topOfOthDiv = $("#othdiv").offset().top;
$(window).scroll(function() {
if(!divIsShown && $(window).scrollTop() > topOfOthDiv) { //scrolled past the other div
setTimeout(function() {
$("#dvid").show(200); //reached the desired point -- show div
divIsShown = true;
}, millis);
}
});
});

Related

Svelte - hide and show nav on scroll

I want the nav to hide scrolling down 60px and to show when scrolling up 60px, no matter in which part of the page.
I did this, but it's incomplete, what am I missing?
<script>
let y = 0;
</script>
<svelte:window bind:scrollY="{y}" />
<nav class:hideNav={y > 60}>
<ul>
<li>link</li>
</ul>
</nav>
<style>
nav {
position: fixed;
top: 0;
}
.hideNav {
top: -70px;
}
</style>
Your code seems to perfectly hide the navbar after you scroll the specified amount, here is a REPL of your code in action. maybe the body of your content has no scroll ?
here is another implementation REPL that further elaborates how to use scrolling position
<script>
import {onMount, onDestroy} from 'svelte'
const scrollNavBar = 60
let show = false
onMount(() => {
window.onscroll = () => {
if (window.scrollY > scrollNavBar) {
show = true
} else {
show = false
}
}
})
onDestroy(() => {
window.onscroll = () => {}
})
</script>
<style>
.scrolled {
transform: translate(0,calc(-100% - 1rem))
}
nav {
width: 100%;
position: fixed;
box-shadow: 0 -0.4rem 0.9rem 0.2rem rgb(0 0 0 / 50%);
padding: 10px;
transition: 0.5s ease
}
:global(body) {
margin: 0;
padding: 0;
height: 200vh;
}
</style>
<nav class:scrolled={show}>
elemnt
</nav>
In your REPL, it seems like the nav does not reappear on scrolling up. It does appear only at the top of the page.
I am also trying to show the nav when the user scrolls up by 30px anywhere on the page, for instance. I think that it was what OP is asking as well.
I found a REPL successfully doing it with jQuery but I am struggling to make it work in Svelte at the moment. Any clue?
I will revert back if I succeed.
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
The answers here couldn't help me. So here's a REPL I made for what I'm using to achieve this in svelte:window.
How I did it;
Create a variable that will store the scroll position (in px) at the end of the scroll event - [let's call it lastScrollPosition].
let lastScrollPosition = 0
At the beginning of a scroll event; inside svelte:window, get and compare the current scroll position to the last scroll position variable we created in [1.] (lastScrollPosition)
<svelte:window on:scroll={()=>{
var currentScrollposition = window.pageYOffset || document.documentElement.scrollTop; //Get current scroll position
if (currentScrollposition > lastScrollPosition) {
showNav = false
}else{
showNav = true
}
lastScrollPosition = currentScrollposition;
}}></svelte:window>
If current scroll Position is greater than lastScrollPosition, showNav is false else, true.
NB: You can use CSS or Svelte Conditional ({#if}) to achieve the hide on scroll down and show on scroll up (This example shows CSS..).
<main>
<div class="nav {showNav == true? "show": "hide" }" >
Nav bar
</div>
<div class="content">
Content
</div>
</main>
<style>
.nav{
background-color: gray;
padding: 6px;
position: fixed;
top: 0;
width: 100%;
}
.content{
background-color: green;
margin-top: 25px;
padding: 6px;
width: 100%;
height: 2300px;
}
.hide{
display: none;
}
.show{
display: unset;
}
</style>

How to make a fixed "go to top" button on the page bottom, but above the (not fixed) footer?

I have made a page (on Shopify) and I made there a fixed "go to top" arrow on the left bottom. It's okay, but when I scroll to the page bottom the arrow is will be in front of the footer, and I want it to stay above the footer.
Here is the code that I use:
$(document).ready(function() {
$(window).scroll(function() {
if ($(this).scrollTop() > 200) {
$('.go-top').fadeIn(200);
} else {
$('.go-top').fadeOut(200);
}
});
$('.go-top').click(function(event) {
event.preventDefault();
$('html, body').animate({scrollTop: 0}, 300);
})
});
.go-top {
position: fixed;
bottom: 2em;
right: 0.5em;
text-decoration: none;
font-size: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
↑
$(document).ready(function() {
$(window).scroll(function() {
//--------------------------- Lines added ------------------------//
var footertotop = ($('.footer').position().top);
var scrolltop = $(document).scrollTop() + window.innerHeight;
var difference = scrolltop-footertotop;
if (scrolltop > footertotop) {
$('.go-top').css({'bottom' : difference});
}else{
$('.go-top').css({'bottom' : 10});
};
//--------------------------- end ---------------------------------//
if ($(this).scrollTop() > 200) {
$('.go-top').fadeIn(200);
} else {
$('.go-top').fadeOut(200);
}
});
$('.go-top').click(function(event) {
event.preventDefault();
$('html, body').animate({scrollTop: 0}, 300);
})
});
.container{height:2000px;position:relative}
.footer{height:200px;width:100%;position:absolute;bottom:0px;background:red}
.go-top {
position: fixed;
bottom: 20px;
display:none; // <---- Dont display on page load
right: 0.5em;
text-decoration: none;
font-size: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
↑
<div class="footer"></div>
</div>
add z-index to the css.
something like:
z-index: 100000
make the number as large as needed for it to be on top.

Remove an If Statement after it has been fired once

Is there anyway of removing an if statement after it has been fired once?
I have a menu container that shows on page load and want it so when the user scrolls 1px it slides away. I don't though want a the browser constantly tracking a scrollTop() method because of the performance hit from this.
What's the best way to remove or cancel an if statement after it has been used once?
The code is below and I have a codepen here: http://codepen.io/emilychews/pen/evbzMQ
jQuery(document).ready(function($) {
$(window).scroll(function() {
if ($(document).scrollTop() > 1) {
$('.menubox').css('left', '-25%');
}
});
$('.mybutton').on('click', function() {
$('.menubox').css('left', '0%');
});
});
body {
margin: 0;
padding: 0;
height: 200vh;
}
.menubox {
top: 100;
position: fixed;
width: 20%;
height: 100%;
background: red;
padding: 10px;
color: white;
transition: all 1s;
}
.mybutton {
position: fixed;
left: 40%;
top: 50px;
padding: 5px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menubox">Menu Box</div>
<button class="mybutton">menu</button>
Sounds like you actually have two conditions. One is based on the scroll position, the other is based on some state to be tracked. So just add a variable to track that state. Maybe something like:
var scrolled = false;
$(window).scroll(function() {
if ( !scrolled && $(document).scrollTop() > 1) { // check the state
$('.menubox').css('left', '-25%');
scrolled = true; // update the state
}
});
$('.mybutton').on('click', function() {
$('.menubox').css('left', '0%');
scrolled = false; // don't forget to reset the state
});
You can call off() within the if statement to remove the event handler.
Also note that if you're concerned about performance you can debounce the event handler so that it only executes the logic once scrolling stops for N ms:
var scrollTimer;
$(window).scroll(function() {
clearTimeout(scrollTimer)
scrollTimer = setTimeout(function() {
if ($(document).scrollTop() > 1) {
$('.menubox').css('left', '-25%');
$(window).off('scroll');
}
}, 150);
});

jQuery detect if div is outside of view port vertically

I'm trying to detect when my div gets opened is the top of it outside of the view-port & if it is add a class to adjust the css.
So basically in this example on hover half of the div is missing so that should then add the class that would turn the div green. Because the code is meant to detect that the div is outside the viewport.
But I just cant get it to sync. I'm obviously doing something wrong here.
UPDATE
I have just noticed that it technically is working what is happening if both the top and bottom of the div goes outside of both the bottom and top of the view port then it triggers. I need it to only trigger when it goes out of the top.
JSfiddle
$(document).on("mouseenter", ":has('.infotip')", function() {
$(this).children(".infotip").addClass("active");
});
$(document).on("mouseleave", ":has('.infotip')", function() {
$(this).children(".infotip").removeClass("active");
});
// Infotip on screen
$(document).on("mouseenter", ":has('.infotip.onscreen')", function() {
var $target = $(this).children(".infotip");
if ($target.length) {
var $bounce = $target.offset().top + $target.height();
if ($bounce > $(window).height()) {
$target.addClass("test");
} else {
$target.addClass("top");
}
}
});
.infotip {
display: none;
height:500px;
width:100px;
position:absolute;
left:50px;
top:-250px;
}
.infotip.active {
display: block;
}
/* goes red when past top of viewport (which it will not do in this example) */
.infotip.top {
background-color: rgba(249, 14, 18, 1.00)
}
/* goes green if visible (which it should do when hovering) */
.infotip.test {
background-color: rgba(35, 223, 51, 1.00)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="team-card align">
hover me
<div class="infotip onscreen">
Iam infotip
</div>
</div>
Here was the issue, on-hover it detect div height and if it overflows then changes the div to green.
$(document).on("mouseenter", function() {
var $target = $(".team-card").children(".infotip");
if ($target.length) {
var $bounce = $target.offset().top + $target.height();
if ($bounce > $(window).height()) {
$target.addClass("test");
} else {
$target.addClass("top");
}
}
});
So I figured this out myself. Finally had a brain storm after realising what the height was down as mentioned on my update.
What I should have been doing is calculating the distance from the top and then detecting if that distance is less than one e.g. 0, -5, -250 etc. Then kick my statement in.
Just wasn't thinking about this one in the right manner for a bit.
JSFiddle
$(document).on("mouseenter", ":has('.infotip')", function() {
$(this).children(".infotip").addClass("active");
});
$(document).on("mouseleave", ":has('.infotip')", function() {
$(this).children(".infotip").removeClass("active");
});
// Infotip on screen
$(document).on("mouseenter", ":has('.infotip.onscreen')", function() {
var $target = $(this).children(".infotip");
if ($target.length) {
var scrollTop = $(window).scrollTop(),
elementOffset = $target.offset().top,
bounce = (elementOffset - scrollTop);
if (bounce < 1 ) {
$target.addClass("test");
} else {
$target.addClass("top");
}
}
});
.infotip {
display: none;
height:500px;
width:100px;
position:absolute;
left:50px;
top:-250px;
}
.infotip.active {
display: block;
}
/* goes red when past top of viewport (which it will not do in this example) */
.infotip.top {
background-color: rgba(249, 14, 18, 1.00)
}
/* goes green if visible (which it should do when hovering) */
.infotip.test {
background-color: rgba(35, 223, 51, 1.00)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="team-card align">
hover me
<div class="infotip onscreen">
Iam infotip
</div>
</div>

How make a fade slideshow loop?

I am using javascript to change my css class background image every few seconds. It is working great the problem is it just stops after it shows the last image. Can anyone show me what to add to this code so that it will continuously loop itself?
$(window).load(function() {
$(document).ready(function() {
setInterval(fadeDivs, 5000); //call it every 2 seconds
function fadeDivs() {
var visibleDiv = $('.bckgnd:visible:first'); //find first visible div
visibleDiv.fadeOut(400, function() { //fade out first visible div
var allDivs = visibleDiv.parent().children(); //all divs to fade out / in
var nextDivIndex = (allDivs.index(visibleDiv) + 1) % allDivs.length; //index of next div that comes after visible div
var nextdiv = allDivs.eq(nextDivIndex); //find the next visible div
var lastDiv = $('.backgnd3');
var firstDiv = $('.backgnd1');
if (currentDiv != lastDiv) {
var nextdiv = allDivs.eq(nextDivIndex); //find the next visible div
} else {
var nextdiv = firstDiv; //the next div will be the first div, resulting in a loop
}
nextdiv.fadeIn(400); //fade it in
});
};
});
});
.backgnd1 {
width: 100%;
height: 452px;
background: url ('http://quaaoutlodge.com/sites/all/themes/marinelli/img/backgrounds/backgnd1.jpg');
background-size: cover;
background-repeat: no-repeat;
background-color: #000;
}
.backgnd2 {
width: 100%;
height: 452px;
background-image: url ('http://quaaoutlodge.com/sites/all/themes/marinelli/img/backgrounds/the_lodge.jpg');
background-size: cover;
background-repeat: no-repeat;
background-color: #000;
}
.backgnd3 {
width: 100%;
height: 452px;
background-image: url('http://quaaoutlodge.com/sites/all/themes/marinelli/img/backgrounds/getting_here.jpg');
background-size: cover;
background-repeat: no-repeat;
background-color: #000;
}
.index_roof_background {
background-color: #000;
width: 1600px;
height: 452px;
margin: 0px;
padding-top: 0px;
margin-left: auto;
margin-right: auto;
}
<div class="index_roof_background">
<div style="position:absolute; z-index: 2;display:block; background-color:#000;" class="bckgnd backgnd1"></div>
<div style="position:absolute; z-index: 2;display:none; background-color:#000;" class="bckgnd backgnd2"></div>
<div style="position:absolute; z-index: 2;display:none; background-color:#000;" class="bckgnd backgnd3"></div>
</div>
A better approach:
You don't need all those backgnd2 classes since you have only those DIVs inside a common parent.
Don't use inline styles! Use your stylesheet.
Don't use fixed width (px). Use % for responsive design.
2000*1331px images are
not suited for the web. Specially not for mobile devices. Care about
your user's bandwidth. When setting a background-image to cover you
don't need to worry about it being repeated.
Make your JS more flexible to element's indexes, count your elements using length.
Create a "current index counter", iterate over it increment it and
resetting using % (reminder).
For a better UX, allow the user to pause on hover.
Here's an eample:
jQuery(function($) { // DOM ready. $ alias in scope.
$('.gallery').each(function() {
var $gal = $(this),
$sli = $gal.find(">*"),
tot = $sli.length,
c = 0,
itv = null;
$sli.hide().eq(c).show(); // Hide all but first slide
function anim() {
c = ++c % tot; // increment/reset counter
$sli.fadeOut().eq(c).stop().fadeIn();
}
function play() {
itv = setInterval(anim, 3000);
}
function pause() {
clearInterval(itv);
}
$gal.hover(pause, play); // Pause on hover
play(); // Start loop
});
});
.gallery {
position: relative;
height: 200px;
}
.gallery>* {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: none 50%;
background-size: cover;
}
<div class="gallery">
<div style="background-image:url(http://placehold.it/800x600/0bf?text=1)"></div>
<div style="background-image:url(http://placehold.it/800x600/f0b?text=2)"></div>
<div style="background-image:url(http://placehold.it/800x600/0fb?text=3)"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
First put the firstDiv, lastDiv in their own variables.
Then you will need something like this
if (currentDiv != lastDiv) {
var nextdiv = allDivs.eq(nextDivIndex); //find the next visible div
} else {
var nextdiv = firstDiv; //the next div will be the first div, resulting in a loop
}
nextdiv.fadeIn(400); //fade it in
Tell me if you need more help.
You need to use 2 timeouts to make it loop. A timeout only fires once. The FadeOutDivs function counts down, each time setting a timeout to call itself. Then at zero it fades sets a timeout the call fadeInDivs which start the whole cycle over.
I've got this running on codepen.
$(document).ready(function () {
var interval = 2000;
var fadeDuration = 400;
var allImages = $('.bckgnd');
var count = allImages.length - 1;
var imageCount = allImages.length;
setTimeout(fadeOutDivs, interval);
function fadeOutDivs() {
allImages.eq(count).fadeOut(fadeDuration);
console.log(count);
if (count > 1) {
count--;
setTimeout(fadeOutDivs, interval);
} else {
count = allImages.length - 1;
setTimeout(fadeInDivs, interval)
}
}
function fadeInDivs() {
allImages.fadeIn(fadeDuration);
setTimeout(fadeOutDivs, interval);
}
});

Categories

Resources