Trigger function only once on scroll - javascript

I want to start a function when a div is scrolled into the viewport. My problem is, that the function is triggered/started again every time I continue to scroll.
HTML:
<div class="box"></div>
JS:
$(document).ready(function() {
function start() {
alert("hello");
}
$(window).scroll(function() {
if ( $(window).scrollTop() >= $('.box').offset().top - ($(window).height() / 2)) {
$(".box").addClass("green");
start();
} else {
$(".box").removeClass("green");
}
});
});
To sum up: the function "start" should be started, when the div is scrolled into the viewport. But it should be not triggered again, after it was triggered once.
Fiddle

You can setup a flag like:
var started = false;
function start() {
if(!started) {
alert("hello");
}
started = true;
}

$(document).ready(function() {
var started = 0;
function start() {
if(started==0) {
alert("Alert only once");
}
started = 1;
}
$(window).scroll(function() {
if ( $(window).scrollTop() >= $('.box').offset().top - ($(window).height() / 2)) {
$(".box").addClass("green");
start();
} else {
$(".box").removeClass("green");
}
});
});
*{margin:0;}
.box { background: red; height: 200px; width: 100%; margin: 800px 0 800px 0; }
.green { background: green; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<br />
<center>
<br />
<h1>scroll down</h1>
</center>
<div class="box"></div>

There's a bunch of ways to go about this. You could just remove the event listener (since you're using jQuery, I'll use the on and off methods):
$(window).on('scroll', function() {
if ( $(window).scrollTop() >= $('.box').offset().top - ($(window).height() / 2)) {
$(".box").addClass("green");
start();
} else {
$(".box").removeClass("green");
}
$(window).off('scroll');
});

if you want window scroll method to stop once the start method meet its requirement.. you can do it this way
$(document).ready(function() {
var toggleScroll = false;
function start() {
alert("hello");
}
$(window).one("scroll", checkToggleScroll);
function checkToggleScroll(){
if ( $(window).scrollTop() >= $('.box').offset().top - ($(window).height() / 2)) {
$(".box").addClass("green");
toggleScroll = true;
start();
} else {
$(".box").removeClass("green");
}
if(!toggleScroll){
$(window).one("scroll", checkToggleScroll);
}
}
});

Related

How to exclude multiple scrolls events for section scroll using jQuery

I'm facing problem is that even when I scroll one time, it gets scrolled multiple times automatically.
Here's my JSFiddle.
So, what I want is that only one section should be scrolled when I scroll one time. When I scroll down 1 time, next section should be seen. Similarly, when I scroll up 1 time, previous section should be seen.
I tried getting help from similar based question but I didn't get one. Thanks for the help in advance.
$(function(){
var lastScrollTop = 0, timer;
$(window).scroll(function(event){
clearTimeout(timer);
var windowH, scrollTop, currentSec = 0, scrollRatio, secOffset, secOffsetTop;
scrollTop = $(this).scrollTop();
windowH = $(window).outerHeight();
if (scrollTop == 0) {
currentSec = 1;
} else {
scrollRatio = scrollTop/windowH;
scrollRatio = Math.round(scrollRatio);
currentSec = scrollRatio + 1;
}
secOffset = $("#sec-"+currentSec).offset();
secOffsetTop = secOffset.top;
console.log("currentSec: "+currentSec);
//Stackoverflow Code
timer = setTimeout(function() {
if (scrollTop > lastScrollTop){
// downscroll code
console.log("DOWN DOWN DOWN!");
//$("#sec-" + currentSec).next("section").animate({scrollTop: 0}, 500);
var targetOffset = $("#sec-" + currentSec).next("section").offset();
$('html,body').animate({scrollTop: targetOffset.top}, 1250);
} else {
// upscroll code
console.log("DOWN DOWN UP!");
//$("#sec-" + currentSec).prev("section").animate({scrollTop: 0}, 500);
var targetOffset = $("#sec-" + currentSec).prev("section").offset();
$('html,body').animate({scrollTop: targetOffset.top});
}
lastScrollTop = scrollTop;
//Stackoverflow Code ENDS
}, 1250);
});
});
* {
box-sizing: border-box;
}
body {
margin: 0;
}
section {
height: 100vh;
color: #fff;
font-size: 60px;
padding: 15px;
}
#sec-1 {
background-color: #0ebeff;
}
#sec-2 {
background-color: #47cf73;
}
#sec-3 {
background-color: #fcd000;
}
#sec-4 {
background-color: #b9f;
}
#sec-5 {
background-color: #ff3c41;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="sec-scroll" id="sec-1">Section 1 </section>
<section class="sec-scroll" id="sec-2">Section 2 </section>
<section class="sec-scroll" id="sec-3">Section 3 </section>
<section class="sec-scroll" id="sec-4">Section 4 </section>
<section class="sec-scroll" id="sec-5">Section 5 </section>

Scroll to bottom of div when close to bottom

I am working on a chatting service and i need the site to scroll to the bottom of the chatt, and if a person whants to scroll up, the script for scrolling down will stop.
I have the chat inside a div with the id #chat_innhold, and here is my attemnt.
window.setInterval(function scrolled(o)
{
if(o.offsetHeight + o.scrollTop > o.scrollHeight - 75)
{
window.setInterval=function()
{
return false;
}
}
else
{
window.setInterval=function()
{
$("html, #chat_innhold").animate({ scrollTop: $('#chat_innhold').prop("scrollHeight")}, 'slow');
}
}
}, 1000);
When i am 75 pixels above bottom, a want to stop the scroll to bottom function.
Why are you overriding window.setInterval?
If I understood correctly, you need something like that
<div class="wrapper">
<button>Go to bottom</button>
<button class="go-top">Go to top</button>
</div>
body,
.wrapper {
margin: 0;
padding: 0;
}
.wrapper {
position: relative;
height: 1000px;
}
.go-top {
bottom: 0;
position: absolute;
left: 0;
}
var elem = $('.wrapper')[0];
if (elem.addEventListener) {
if ('onWheel' in document) {
// IE9+, FF17+, Ch31+
elem.addEventListener("wheel", onWheel);
} else if ('onmousewheel' in document) {
// old variant
elem.addEventListener("mousewheel", onWheel);
} else {
// Firefox < 17
elem.addEventListener("MozMousePixelScroll", onWheel);
}
} else { // IE8-
elem.attachEvent("onmousewheel", onWheel);
}
function onWheel(e) {
e = e || window.event;
var delta = e.deltaY || e.detail || e.wheelDelta;
if(delta < 0 || delta > 0) {
$('html, body').stop();
}
}
var deltaWindowBodyHeight = $('body').height() - $(window).height();
function goToBottom() {
$('html, body').animate({
scrollTop: deltaWindowBodyHeight - 75
}, 1000);
}
function goToTop() {
$('html, body').animate({
scrollTop: 0
}, 1000);
}
$('button').click(function() {
if($(this).hasClass('go-top')) {
goToTop();
} else {
goToBottom();
}
});
JSFiddle example

Bug with elastic scrolling and menu bar in JS

I want to set up a menu bar like you see her in JSfiddle:
http://jsfiddle.net/gvjeyywa/21/
There it works exactly the way I want it to … But on the webpage it has a bug, I think it's because of the elastic scrolling in OSX … On scrolling down the menu bar should slide in from the top to set up on top:0px, being fixed there… But if you scroll back to top and the elastic scrolling scrolls higher than the body is… the menu jumps too high…
Here see the live example:
http://www.cyrill-kuhlmann.de/index.php/projects
on iOS it's a complete mess too…
Here is the JS Code:
var bitFlag = false;
var isActive = true;
var lastScrollTop = 0;
var timeoutId;
$navigation = $("#navigation");
$(window).scroll(function (event) {
var intWindowTop = $(window).scrollTop();
var intElementBottom = $navigation.offset().top + $navigation.height();
if (intWindowTop > lastScrollTop) {
isActive = true;
if (!bitFlag) {
$navigation.css("position", "absolute").css("top", intWindowTop + "px");
bitFlag = true;
}
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(function () {
if (intWindowTop > intElementBottom) {
intDelayTime = setTimeout(function () {
if (isActive) {
$navigation.animate({ top: intWindowTop + "px" }, {
duration: 800,
step: function () {
if ($(window).scrollTop() < $navigation.offset().top) {
$(this).stop(true,true);
}
},
complete: function () {
intDelayTime2 = setTimeout(function () {
$("#navigation").css("position", "fixed").css("top", "0px");
bitFlag = false;
isActive = false;
}, 1);
}
});
}
}, 500);
}
}, 100);
} else {
$navigation.css("position", "fixed").css("top", "0px");
bitFlag = false;
isActive = false;
}
lastScrollTop = intWindowTop;
});
And this is the CSS:
#navigation {
position:absolute;
top: 0px;
left: 0px;
right: 0px;
height: 80px;
background-color: #FFF;
z-index:999;
padding-top: 25px;
padding-left: 45px;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
Does someone have an idea? Unfortunately I'am a bloody starter in JS… I am thankful for any help…
problem is this: intWindowTop > lastScrollTop.
this value is true, when you scroll into the negative area, that comes with webkit.
so you have to check, if the value is positive via intWindowTop > 0
$(window).scroll(function () {
var intWindowTop = $(window).scrollTop();
var intElementBottom = $navigation.offset().top + $navigation.height();
if ( intWindowTop > lastScrollTop && intWindowTop > 0 ) {
//...
} else {
//...
}
note that i removed the variable "event" as well. you dont use it, so why declare it..?

Convert click code to hover code

How can I change the following menu code to open/close when the mouse hovers, instead of when it is clicked on?
var w = 0;
$('.slide').children().each(function () {
w += $(this).outerWidth();
});
$('.outer').width(w + 5);
$('.wrap').width(w);
$('.slide').css('left', w);
$('.open').toggle(function () {
$('.slide').stop().animate({
left: 0
});
$(this).html('close');
}, function () {
$('.slide').stop().animate({
left: w
});
$(this).html('open');
});
Please check this Demo
In Fiddle, you can see the animation works on click. I need to make it work on hover. Can you help with this ?
Use .hover() api
Try this
$('.open').hover(function () {
instead of
$('.open').toggle(function () {
Just
$('.open').toggle(function() {
$('.slide').stop().animate({
left: 0
});
$(this).html('close');
}
in this part just replace toggle with hover
Try using $('.wrap').hover. If $('.open').hover, you will not able to click the nav items.
Also, you can create another wrapper to just wrap div.outer and a.open only
$('.wrap').hover(function() {
$('.slide').stop().animate({
left : 0
});
//this is the .wrap right now
$(this).find('a.open').html('close');
}, function() {
$('.slide').stop().animate({
left : w
});
//this is the .wrap right now
$(this).find('a.open').html('open');
});
http://jsfiddle.net/rooseve/42sWB/2/
$('.open').on('mouseenter mouseleave', function(e) {
if(e.type === 'mouseleave') {
$('.slide').stop().animate({
left: w
});
$(this).html('open');
} else {
$('.slide').stop().animate({
left: 0
});
$(this).html('close');
}
});
var w = 0;
var isVisible = false;
$('.slide').children().each(function() {
w += $(this).outerWidth();
});
$('.outer').width(w+5);
$('.wrap').width(w);
$('.slide').css('left', w);
$('.open').on("mouseover", function() {
if(isVisible == false) {
$('.slide').stop().animate({
left: 0
});
$(this).html('close');
isVisible = true;
}
else {
$('.slide').stop().animate({
left: w
});
$(this).html('open');
isVisible = false;
}
});
Firstly, when you hover the element - the div will be visible, until you hover the element for the second time.
Demo: http://jsfiddle.net/42sWB/3/

jQuery - Sticky header that shrinks when scrolling down

I wonder how to make a sticky header shrink(with animation) when you scroll down the page and goes back to normal state when the page is scrolled up to the top. Here are two examples to clearify:
http://themenectar.com/demo/salient/
http://www.kriesi.at/themes/enfold/
I get the part to make it fixed, but how should I do to shrink my header when the user scrolls down?
Thanks a ton
This should be what you are looking for using jQuery.
$(function(){
$('#header_nav').data('size','big');
});
$(window).scroll(function(){
if($(document).scrollTop() > 0)
{
if($('#header_nav').data('size') == 'big')
{
$('#header_nav').data('size','small');
$('#header_nav').stop().animate({
height:'40px'
},600);
}
}
else
{
if($('#header_nav').data('size') == 'small')
{
$('#header_nav').data('size','big');
$('#header_nav').stop().animate({
height:'100px'
},600);
}
}
});
Demonstration:
http://jsfiddle.net/jezzipin/JJ8Jc/
Here a CSS animation fork of jezzipin's Solution, to seperate code from styling.
JS:
$(window).on("scroll touchmove", function () {
$('#header_nav').toggleClass('tiny', $(document).scrollTop() > 0);
});
CSS:
.header {
width:100%;
height:100px;
background: #26b;
color: #fff;
position:fixed;
top:0;
left:0;
transition: height 500ms, background 500ms;
}
.header.tiny {
height:40px;
background: #aaa;
}
http://jsfiddle.net/sinky/S8Fnq/
On scroll/touchmove the css class "tiny" is set to "#header_nav" if "$(document).scrollTop()" is greater than 0.
CSS transition attribute animates the "height" and "background" attribute nicely.
http://callmenick.com/2014/02/18/create-an-animated-resizing-header-on-scroll/
This link has a great tutorial with source code that you can play with, showing how to make elements within the header smaller as well as the header itself.
Based on twitter scroll trouble (http://ejohn.org/blog/learning-from-twitter/).
Here is my solution, throttling the js scroll event (usefull for mobile devices)
JS:
$(function() {
var $document, didScroll, offset;
offset = $('.menu').position().top;
$document = $(document);
didScroll = false;
$(window).on('scroll touchmove', function() {
return didScroll = true;
});
return setInterval(function() {
if (didScroll) {
$('.menu').toggleClass('fixed', $document.scrollTop() > offset);
return didScroll = false;
}
}, 250);
});
CSS:
.menu {
background: pink;
top: 5px;
}
.fixed {
width: 100%;
position: fixed;
top: 0;
}
HTML:
<div class="menu">MENU FIXED ON TOP</div>
http://codepen.io/anon/pen/BgqHw
I did an upgraded version of jezzipin's answer (and I'm animating padding top instead of height but you still get the point.
/**
* ResizeHeaderOnScroll
*
* #constructor
*/
var ResizeHeaderOnScroll = function()
{
this.protocol = window.location.protocol;
this.domain = window.location.host;
};
ResizeHeaderOnScroll.prototype.init = function()
{
if($(document).scrollTop() > 0)
{
$('header').data('size','big');
} else {
$('header').data('size','small');
}
ResizeHeaderOnScroll.prototype.checkScrolling();
$(window).scroll(function(){
ResizeHeaderOnScroll.prototype.checkScrolling();
});
};
ResizeHeaderOnScroll.prototype.checkScrolling = function()
{
if($(document).scrollTop() > 0)
{
if($('header').data('size') == 'big')
{
$('header').data('size','small');
$('header').stop().animate({
paddingTop:'1em',
paddingBottom:'1em'
},200);
}
}
else
{
if($('header').data('size') == 'small')
{
$('header').data('size','big');
$('header').stop().animate({
paddingTop:'3em'
},200);
}
}
}
$(document).ready(function(){
var resizeHeaderOnScroll = new ResizeHeaderOnScroll();
resizeHeaderOnScroll.init()
})
I took Jezzipin's answer and made it so that if you are scrolled when you refresh the page, the correct size applies. Also removed some stuff that isn't necessarily needed.
function sizer() {
if($(document).scrollTop() > 0) {
$('#header_nav').stop().animate({
height:'40px'
},600);
} else {
$('#header_nav').stop().animate({
height:'100px'
},600);
}
}
$(window).scroll(function(){
sizer();
});
sizer();

Categories