check if the page is on the top of the window - javascript

I need to check if an html page is on the top of the window or not.
So, i am using this code:
$(window).scroll(function(){
a = ($(window).scrollTop());
if (a>0) {
alert('page not in top');
}
});
But this is not working as expected because the event should be fired only when the user stops the scroll action. Any idea?

Try this:
var timer = null;
$(window).addEventListener('scroll', function() {
if(timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(function() {
// do something
}, 150);
}, false);
Or this one:
var timer;
$(window).bind('scroll',function () {
clearTimeout(timer);
timer = setTimeout( refresh , 150 );
});
var refresh = function () {
// do stuff
console.log('Stopped Scrolling');
};

Use setTimeout:
var timeout;
$(window).scroll(function() {
clearTimeout(timeout);
timeout = setTimeout(function(){
a = $(window).scrollTop();
if ( a > 0 ) {
alert('page not in top');
}
}, 100);
});

Related

How to detect "scrollstop" event in a browser

I know that there is no scrollstop event in an official browser DOM documentation but how to detect it?
The most logical way to do this is to listen for a timeout.
var timer = null;
var timeout = 150; //ms
window.addEventListener('scroll', function() {
if(timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(function() {
// do something
}, timeout);
}, false);
If it is still not scroll after 150ms it means the scroll has stopped!
You can change this timeout as you see fit. Again, I think the most logical thing is to choose a value between 150 and 250ms.
var timer = null;
var timeout = 150; //ms
window.addEventListener('scroll', function() {
if (timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(function() {
console.log('Scroll Stopped');
}, timeout);
}, false);
html,
body {
padding-top: 100rem;
}

Scripts crashing each other

well my problem is hopefully easy: 3 actions that shall happen while hovering a photo. The timer at the bottom works now, the other things crashed. A Page shall open in 5 seconds and the photo shall move out of the display before. Sounds easy, doesnt it? I hope so.
Do you guys know what I can do?
Thanks already and best regards!
<script>
var interval;
var timer = 5;
$('.HoverBalken').on({'mouseover': function () {
timer = setTimeout(function () {
$('.HoverBalken').toggleClass('HoverBalken-active');
$('.N').toggleClass('N-active');
$('.K').toggleClass('K-active');
}, );
timer = setTimeout(function () {
window.location = "FoliagePlates.html"
}, 5000);
}, 'mouseover': function () {
interval = setInterval(function() {
timer--;
$('.timer').text(timer);
if (timer === 0) clearInterval(interval);
}, 1000);
}, 'mouseout' : function () {
clearTimeout(timer);
$('.HoverBalken').removeClass('HoverBalken-active');
$('.N').removeClass('N-active');
$('.K').removeClass('K-active');
clearInterval(interval);
timer = 5;
$('.timer').text(timer);
}
});
</script>
<script>
var interval;
var timer = 5;
var timeout1,timeout2;
$('.HoverBalken')
.mouseover(function() {
//use different variable than your timer
timeout1 = setTimeout(function () {
$('.HoverBalken').toggleClass('HoverBalken-active');
$('.N').toggleClass('N-active');
$('.K').toggleClass('K-active');
}, 2000); //forgot time here
//use different variable than your timer and first timeout
timeout2 = setTimeout(function () {
window.location = "FoliagePlates.html"
}, 5000);
//stay in same scope, don't define event again
interval = setInterval(function() {
timer--;
$('.timer').text(timer);
if (timer === 0) clearInterval(interval);
}, 1000);
})
.mouseout(function() {
//clear both timers
clearTimeout(timeout1);
clearTimeout(timeout2);
$('.HoverBalken').removeClass('HoverBalken-active');
$('.N').removeClass('N-active');
$('.K').removeClass('K-active');
clearInterval(interval);
timer = 5;
$('.timer').text(timer);
});
</script>
this should fix it, notice the comments in code

How to incorporate delay on a function?

I'm trying to implement a delay on a function. Should I wrap the function inside a delay function? Or can I somehow add more code, so that the animation doesn't start before 5 sec after page load?
var typeThis = "blablablabla";
var displayText = "";
function type(fullString, typedSoFar) {
if (fullString.length != typedSoFar.length) {
typedSoFar = fullString.substring(0, typedSoFar.length + 1);
document.getElementById("logoType").innerText = typedSoFar;
setTimeout(function() {
type(fullString, typedSoFar)
}, 150);
}
}
document.getElementById("logoType").innerHtml = typeThis;
var element = document.createElement('h2');
element.innerHTML = typeThis;
typeThis = element.textContent;
type(typeThis, displayText);
<a class="navbar-brand" id="topper" href="#"><p id="logoType"></p></a>
I think what you are looking for is setTimeout.
window.setTimeout(function () {
type(typeThis, displayText);
}, 5000);
You can also add that to a listener to know when the window has finished loading:
window.addEventListener('load', function () {
window.setTimeout(function () {
type(typeThis, displayText);
}, 5000);
});
A full example:
var typeThis = "blablablabla";
var displayText = "";
function type(fullString, typedSoFar) {
if (fullString.length != typedSoFar.length) {
typedSoFar = fullString.substring(0, typedSoFar.length + 1);
document.getElementById("logoType").innerText = typedSoFar;
setTimeout(function() {
type(fullString, typedSoFar)
}, 150);
}
}
document.getElementById("logoType").innerHtml = typeThis;
var element = document.createElement('h2');
element.innerHTML = typeThis;
typeThis = element.textContent;
window.addEventListener('load', function() {
window.setTimeout(function() {
type(typeThis, displayText);
}, 5000);
});
Waiting 5 seconds...
<a class="navbar-brand" id="topper" href="#"><p id="logoType"></p></a>
Your best bet is not going to be adding more code to delay, but wrap this all in a Timeout: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
Use setTimeout() like so:
var timeoutID;
function delayedAlert() {
timeoutID = window.setTimeout(slowAlert, 2000);
}
function slowAlert() {
alert("That was really slow!");
}
function clearAlert() {
window.clearTimeout(timeoutID);
}
Source: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

Automaticly scrollTo closest div

I'm building a single page ScrollTo website with 4 div's. These divs represent my pages.
Home -> My work -> About me -> Contact
The width and hight are defined by a small piece of javascript that reads the users screen resolution on bodyload or resize. So the divs are always the inner-width and height of the users screen.
function resize() {
document.getElementById("home").style.height = viewportheight+"px";
document.getElementById("work").style.height = viewportheight+"px";
document.getElementById("about").style.height = viewportheight+"px";
document.getElementById("contact").style.height = viewportheight+"px";
What I'm trying to accomplish is that once the user scrolls (let's say 100px down or up), the window automaticly snaps to the top of the nearest div.
Something like:
onScroll("100px") up or down { scrollTo("closest #div") };
The methods you can use to start here are:
//OnScroll:
$(window).scroll(function(){
//Get current scoll position:
var iSrollT = $(document).scrollTop();
//Get the position of your element:
var iOffT = $('#home').offset().top;
});
//Set scroll top using an animation:
$('html, body').animate({
scrollTop: iOffT
}, 300);
But you will have to implement more ... e.g. prevent that the scoll position always snaps to the next div and scolling is no more possible.
var STELLARJS = {
init: function() {
var self = this;
$(function(){
self.$sections = $('#landing_page, #work, #about, #contact').each(function(index){
$(this).data('sectionIndex', index);
});
self.handleEvents();
});
},
handleEvents: function() {
var self = this,
//Debounce function from Underscore.js
debounce = function(func, wait) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
func.apply(context, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
}
},
handleScroll = function() {
var scrollTop = $(window).scrollTop(),
sectionIndex = Math.round((scrollTop) / self.$sections.first().outerHeight()),
$activeSection = self.$sections.eq(sectionIndex);
if ($activeSection.length === 0) {
$activeSection = self.$sections.last();
}
if ($activeSection.length === 0) return;
$(window).unbind('scroll.stellarsite');
if (scrollTop === 0) {
$(window).unbind('scroll.stellarsite').bind('scroll.stellarsite', debounce(handleScroll, 500));
} else {
$('html,body').animate({
scrollTop: $activeSection.offset().top
}, 600, 'easeInOutExpo', function() {
setTimeout(function(){
$(window).unbind('scroll.stellarsite').bind('scroll.stellarsite', debounce(handleScroll, 500));
}, 10);
});
}
$(window).bind('mousewheel', function(){
$('html,body').stop(true, true);
});
$(document).bind('keydown', function(e){
var key = e.which;
if (key === 37 || key === 39) {
$('html,body').stop(true, true);
}
});
};
if (window.location.href.indexOf('#show-offset-parents-default') === -1) {
$(window).bind('scroll.stellarsite', debounce(handleScroll, 500));
}
} });

How do I know when I've stopped scrolling?

How do I know when I've stopped scrolling using Javascript?
You can add an event handler for the scroll event and start a timeout. Something like:
var timer = null;
window.addEventListener('scroll', function() {
if(timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(function() {
// do something
}, 150);
}, false);
This will start a timeout and wait 150ms. If a new scroll event occurred in the meantime, the timer is aborted and a new one is created. If not, the function will be executed. You probably have to adjust the timing.
Also note that IE uses a different way to attach event listeners, this should give a good introduction: quirksmode - Advanced event registration models
There isn't a "Stopped Scrolling" event. If you want to do something after the user has finished scrolling, you can set a timer in the "OnScroll" event. If you get another "OnScroll" event fired then reset the timer. When the timer finally does fire, then you can assume the scrolling has stopped. I would think 500 milliseconds would be a good duration to start with.
Here's some sample code that works in IE and Chrome:
<html>
<body onscroll="bodyScroll();">
<script language="javascript">
var scrollTimer = -1;
function bodyScroll() {
document.body.style.backgroundColor = "white";
if (scrollTimer != -1)
clearTimeout(scrollTimer);
scrollTimer = window.setTimeout("scrollFinished()", 500);
}
function scrollFinished() {
document.body.style.backgroundColor = "red";
}
</script>
<div style="height:2000px;">
Scroll the page down. The page will turn red when the scrolling has finished.
</div>
</body>
</html>
Here's a more modern, Promise-based solution I found on a repo called scroll-into-view-if-needed
Instead of using addEventListener on the scroll event it uses requestAnimationFrame to watch for frames with no movement and resolves when there have been 20 frames without movement.
function waitForScrollEnd () {
let last_changed_frame = 0
let last_x = window.scrollX
let last_y = window.scrollY
return new Promise( resolve => {
function tick(frames) {
// We requestAnimationFrame either for 500 frames or until 20 frames with
// no change have been observed.
if (frames >= 500 || frames - last_changed_frame > 20) {
resolve()
} else {
if (window.scrollX != last_x || window.scrollY != last_y) {
last_changed_frame = frames
last_x = window.scrollX
last_y = window.scrollY
}
requestAnimationFrame(tick.bind(null, frames + 1))
}
}
tick(0)
})
}
With async/await and then
await waitForScrollEnd()
waitForScrollEnd().then(() => { /* Do things */ })
(function( $ ) {
$(function() {
var $output = $( "#output" ),
scrolling = "<span id='scrolling'>Scrolling</span>",
stopped = "<span id='stopped'>Stopped</span>";
$( window ).scroll(function() {
$output.html( scrolling );
clearTimeout( $.data( this, "scrollCheck" ) );
$.data( this, "scrollCheck", setTimeout(function() {
$output.html( stopped );
}, 250) );
});
});
})( jQuery );
=======>>>>
Working Example here
I did something like this:
var scrollEvents = (function(document, $){
var d = {
scrolling: false,
scrollDirection : 'none',
scrollTop: 0,
eventRegister: {
scroll: [],
scrollToTop: [],
scrollToBottom: [],
scrollStarted: [],
scrollStopped: [],
scrollToTopStarted: [],
scrollToBottomStarted: []
},
getScrollTop: function(){
return d.scrollTop;
},
setScrollTop: function(y){
d.scrollTop = y;
},
isScrolling: function(){
return d.scrolling;
},
setScrolling: function(bool){
var oldVal = d.isScrolling();
d.scrolling = bool;
if(bool){
d.executeCallbacks('scroll');
if(oldVal !== bool){
d.executeCallbacks('scrollStarted');
}
}else{
d.executeCallbacks('scrollStopped');
}
},
getScrollDirection : function(){
return d.scrollDirection;
},
setScrollDirection : function(direction){
var oldDirection = d.getScrollDirection();
d.scrollDirection = direction;
if(direction === 'UP'){
d.executeCallbacks('scrollToTop');
if(direction !== oldDirection){
d.executeCallbacks('scrollToTopStarted');
}
}else if(direction === 'DOWN'){
d.executeCallbacks('scrollToBottom');
if(direction !== oldDirection){
d.executeCallbacks('scrollToBottomStarted');
}
}
},
init : function(){
d.setScrollTop($(document).scrollTop());
var timer = null;
$(window).scroll(function(){
d.setScrolling(true);
var x = d.getScrollTop();
setTimeout(function(){
var y = $(document).scrollTop();
d.setScrollTop(y);
if(x > y){
d.setScrollDirection('UP');
}else{
d.setScrollDirection('DOWN');
}
}, 100);
if(timer !== 'undefined' && timer !== null){
clearTimeout(timer);
}
timer = setTimeout(function(){
d.setScrolling(false);
d.setScrollDirection('NONE');
}, 200);
});
},
registerEvents : function(eventName, callback){
if(typeof eventName !== 'undefined' && typeof callback === 'function' && typeof d.eventRegister[eventName] !== 'undefined'){
d.eventRegister[eventName].push(callback);
}
},
executeCallbacks: function(eventName){
var callabacks = d.eventRegister[eventName];
for(var k in callabacks){
if(callabacks.hasOwnProperty(k)){
callabacks[k](d.getScrollTop());
}
}
}
};
return d;
})(document, $);
the code is available here: documentScrollEvents
Minor update in your answer. Use mouseover and out function.
$(document).ready(function() {
function ticker() {
$('#ticker li:first').slideUp(function() {
$(this).appendTo($('#ticker')).slideDown();
});
}
var ticke= setInterval(function(){
ticker();
}, 3000);
$('#ticker li').mouseover(function() {
clearInterval(ticke);
}).mouseout(function() {
ticke= setInterval(function(){ ticker(); }, 3000);
});
});
DEMO
I was trying too add a display:block property for social icons that was previously hidden on scroll event and then again hide after 2seconds. But
I too had a same problem as my code for timeout after first scroll would start automatically and did not had reset timeout idea. As it didn't had proper reset function.But after I saw David's idea on this question I was able to reset timeout even if someone again scrolled before actually completing previous timeout.
problem code shown below before solving
$(window).scroll(function(){
setTimeout(function(){
$('.fixed-class').slideUp('slow');
},2000);
});
edited and working code with reset timer if next scroll occurs before 2s
var timer=null;
$(window).scroll(function(){
$('.fixed-class').css("display", "block");
if(timer !== null) {
clearTimeout(timer);
}
timer=setTimeout(function(){
$('.fixed-class').slideUp('slow');
},2000);
});
My working code will trigger a hidden division of class named 'fixed-class' to show in block on every scroll. From start of latest scroll the timer will count 2 sec and then again change the display from block to hidden.
For more precision you can also check the scroll position:
function onScrollEndOnce(callback, target = null) {
let timeout
let targetTop
const startPosition = Math.ceil(document.documentElement.scrollTop)
if (target) {
targetTop = Math.ceil(target.getBoundingClientRect().top + document.documentElement.scrollTop)
}
function finish(removeEventListener = true) {
if (removeEventListener) {
window.removeEventListener('scroll', onScroll)
}
callback()
}
function isScrollReached() {
const currentPosition = Math.ceil(document.documentElement.scrollTop)
if (targetTop == null) {
return false
} else if (targetTop >= startPosition) {
return currentPosition >= targetTop
} else {
return currentPosition <= targetTop
}
}
function onScroll() {
if (timeout) {
clearTimeout(timeout)
}
if (isScrollReached()) {
finish()
} else {
timeout = setTimeout(finish, 500)
}
}
if (isScrollReached()) {
finish(false)
} else {
window.addEventListener('scroll', onScroll)
}
}
Usage example:
const target = document.querySelector('#some-element')
onScrollEndOnce(() => console.log('scroll end'), target)
window.scrollTo({
top: Math.ceil(target.getBoundingClientRect().top + document.documentElement.scrollTop),
behavior: 'smooth',
})
Here's an answer that doesn't use any sort of timer, thus in my case predicted when the scrolling actually ended, and is not just paused for a bit.
function detectScrollEnd(element, onEndHandler) {
let scrolling = false;
element.addEventListener('mouseup', detect);
element.addEventListener('scroll', detect);
function detect(e) {
if (e.type === 'scroll') {
scrolling = true;
} else {
if (scrolling) {
scrolling = false;
onEndHandler?.();
}
}
}
}

Categories

Resources