ClearTimeout with condition is not working - javascript

Does any one know why this is not working?
http://jsfiddle.net/jonevar/2Z2NQ/5/
Here is the whole code:
function ag_alert(message) {
event.preventDefault();
//SetTimeout in case didn't close manualy
var timer = setTimeout(cls_message, 5000),
cur_url = window.location.href;
//Check if its already on
if (! $('.ag_alert_wrapper').is(':visible') ) {
//Set the language
(cur_url.indexOf('/en/') >= 0) ? cls_txt = "close" : cls_txt = "閉じる" ;
$('<div class="ag_mess ag_alert_wrapper"></div><div class="ag_mess ag_alert_wrapper_close">'+ cls_txt +'</div>')
.prependTo('body');
$('.ag_alert_wrapper')
.append('<p>'+ message +'</p>')
.animate({top : 0}, 200, function() {
$('.ag_alert_wrapper_close')
.animate({top : 90}, 200)
.on({
mouseenter : function () {
$(this).animate({
top : 100
}, 200);
},
mouseleave : function () {
$(this).animate({
top : 90
}, 200);
},
click : function () {
cls_message();
}
});
});
//Setups ESC key to close message
$(document).keydown(function(e) {
if (e.keyCode === 27) {
cls_message();
}
});
} else {
//if Alert is already visible
$('.ag_alert_wrapper')
.children('p').html(message)
.end()
.effect("highlight", {
color : '#FF0'
}, 1000);
clearTimeout(timer);
}
}
function cls_message() {
$('.ag_mess').animate({
top : -200
}, 200, function () {
$('.ag_mess').remove();
});
}

This seems to be working fine, test code (using jQuery, but that's not changing the conclusion):
html
<div id="msgs"></div>
js
function other_function() {
$('#msgs').append('other ');
}
function do_something(data) {
var timer = setTimeout(other_function, 500);
if (data === "condition") {
$('#msgs').append('hi ');
} else {
$('#msgs').append('clearing ');
clearTimeout(timer);
}
}
do_something('yay');
do_something('condition');
Outputs this to the div:
clearing hi other
as expected. Live example:
http://jsfiddle.net/mCdxV/
Hope this helps.

Related

Start stop function on scroll event within if/else statement

I have a script which animates a headline.
I am trying to make this script fire on page load, but if a user scrolls more than 200px, I'd like this function to stop.
Below is my animated headline script, and also my scroll/if else statement. This should fire the wordAnimate() function on page load, but stop if user scrolls more than 200px. There is also some classes being added and removed conditionally in the scroll for a sticky navbar that appears after the 200px scroll.
JS:
$(document).scroll(function() {
var scroll = $(this).scrollTop();
return (scroll < 200) && $(window).wordAnimate();
if (scroll >= 200) {
$('.logo').removeClass('transparent').addClass('opaque');
}
else {
$('.logo').removeClass('opaque').addClass('transparent');
}
});
animate-headline.js:
function wordAnimate() {
//set animation timing
var animationDelay = 2500,
//loading bar effect
barAnimationDelay = 3800,
barWaiting = barAnimationDelay - 1000, //3000 is the duration of the transition on the loading bar - set in the scss/css file
//letters effect
lettersDelay = 50,
//type effect
typeLettersDelay = 150,
selectionDuration = 500,
typeAnimationDelay = selectionDuration + 800,
//clip effect
revealDuration = 600,
revealAnimationDelay = 1500;
initHeadline();
function initHeadline() {
//insert <i> element for each letter of a changing word
singleLetters($('.cd-headline.letters').find('b'));
//initialise headline animation
animateHeadline($('.cd-headline'));
}
function singleLetters($words) {
$words.each(function(){
var word = $(this),
letters = word.text().split(''),
selected = word.hasClass('is-visible');
for (i in letters) {
if(word.parents('.rotate-2').length > 0) letters[i] = '<em>' + letters[i] + '</em>';
letters[i] = (selected) ? '<i class="in">' + letters[i] + '</i>': '<i>' + letters[i] + '</i>';
}
var newLetters = letters.join('');
word.html(newLetters).css('opacity', 1);
});
}
function animateHeadline($headlines) {
var duration = animationDelay;
$headlines.each(function(){
var headline = $(this);
if(headline.hasClass('loading-bar')) {
duration = barAnimationDelay;
setTimeout(function(){ headline.find('.cd-words-wrapper').addClass('is-loading') }, barWaiting);
} else if (headline.hasClass('clip')){
var spanWrapper = headline.find('.cd-words-wrapper'),
newWidth = spanWrapper.width() + 10
spanWrapper.css('width', newWidth);
} else if (!headline.hasClass('type') ) {
//assign to .cd-words-wrapper the width of its longest word
var words = headline.find('.cd-words-wrapper b'),
width = 0;
words.each(function(){
var wordWidth = $(this).width();
if (wordWidth > width) width = wordWidth;
});
headline.find('.cd-words-wrapper').css('width', width);
};
//trigger animation
setTimeout(function(){ hideWord( headline.find('.is-visible').eq(0) ) }, duration);
});
}
function hideWord($word) {
var nextWord = takeNext($word);
if($word.parents('.cd-headline').hasClass('type')) {
var parentSpan = $word.parent('.cd-words-wrapper');
parentSpan.addClass('selected').removeClass('waiting');
setTimeout(function(){
parentSpan.removeClass('selected');
$word.removeClass('is-visible').addClass('is-hidden').children('i').removeClass('in').addClass('out');
}, selectionDuration);
setTimeout(function(){ showWord(nextWord, typeLettersDelay) }, typeAnimationDelay);
} else if($word.parents('.cd-headline').hasClass('letters')) {
var bool = ($word.children('i').length >= nextWord.children('i').length) ? true : false;
hideLetter($word.find('i').eq(0), $word, bool, lettersDelay);
showLetter(nextWord.find('i').eq(0), nextWord, bool, lettersDelay);
} else if($word.parents('.cd-headline').hasClass('clip')) {
$word.parents('.cd-words-wrapper').animate({ width : '2px' }, revealDuration, function(){
switchWord($word, nextWord);
showWord(nextWord);
});
} else if ($word.parents('.cd-headline').hasClass('loading-bar')){
$word.parents('.cd-words-wrapper').removeClass('is-loading');
switchWord($word, nextWord);
setTimeout(function(){ hideWord(nextWord) }, barAnimationDelay);
setTimeout(function(){ $word.parents('.cd-words-wrapper').addClass('is-loading') }, barWaiting);
} else {
switchWord($word, nextWord);
setTimeout(function(){ hideWord(nextWord) }, animationDelay);
}
}
function showWord($word, $duration) {
if($word.parents('.cd-headline').hasClass('type')) {
showLetter($word.find('i').eq(0), $word, false, $duration);
$word.addClass('is-visible').removeClass('is-hidden');
} else if($word.parents('.cd-headline').hasClass('clip')) {
$word.parents('.cd-words-wrapper').animate({ 'width' : $word.width() + 10 }, revealDuration, function(){
setTimeout(function(){ hideWord($word) }, revealAnimationDelay);
});
}
}
function hideLetter($letter, $word, $bool, $duration) {
$letter.removeClass('in').addClass('out');
if(!$letter.is(':last-child')) {
setTimeout(function(){ hideLetter($letter.next(), $word, $bool, $duration); }, $duration);
} else if($bool) {
setTimeout(function(){ hideWord(takeNext($word)) }, animationDelay);
}
if($letter.is(':last-child') && $('html').hasClass('no-csstransitions')) {
var nextWord = takeNext($word);
switchWord($word, nextWord);
}
}
function showLetter($letter, $word, $bool, $duration) {
$letter.addClass('in').removeClass('out');
if(!$letter.is(':last-child')) {
setTimeout(function(){ showLetter($letter.next(), $word, $bool, $duration); }, $duration);
} else {
if($word.parents('.cd-headline').hasClass('type')) { setTimeout(function(){ $word.parents('.cd-words-wrapper').addClass('waiting'); }, 200);}
if(!$bool) { setTimeout(function(){ hideWord($word) }, animationDelay) }
}
}
function takeNext($word) {
return (!$word.is(':last-child')) ? $word.next() : $word.parent().children().eq(0);
}
function takePrev($word) {
return (!$word.is(':first-child')) ? $word.prev() : $word.parent().children().last();
}
function switchWord($oldWord, $newWord) {
$oldWord.removeClass('is-visible').addClass('is-hidden');
$newWord.removeClass('is-hidden').addClass('is-visible');
}
}
What is a better way to do this?
Currently myFunction won't fire unless I call it from the debugger in the browser dev tools.
UPDATE:
Problem solved by adding a stopAnimating() and restartAnimating() function to the large, animated headline script. This way we can call those specific functions from within the scroll if/else.
JS:
$(window).scroll(function() {
var scroll = $(this).scrollTop();
if (scroll >= 200) {
$('.nav-wrapper').removeClass('transparent').addClass('opaque');
stopAnimating();
}
else {
$('.nav-wrapper').removeClass('opaque').addClass('transparent');
restartAnimating();
}
});
animate-headline.js:
//set animation timing
var stop
var animationDelay = 2500,
//loading bar effect
barAnimationDelay = 3800,
barWaiting = barAnimationDelay - 1000, //3000 is the duration of the transition on the loading bar - set in the scss/css file
//letters effect
lettersDelay = 50,
//type effect
typeLettersDelay = 150,
selectionDuration = 500,
typeAnimationDelay = selectionDuration + 800,
//clip effect
revealDuration = 600,
revealAnimationDelay = 1500;
initHeadline();
function initHeadline() {
//insert <i> element for each letter of a changing word
singleLetters($('.cd-headline.letters').find('b'));
//initialise headline animation
animateHeadline($('.cd-headline'));
stop = false;
}
function stopAnimating() {
stop = true;
}
function restartAnimating() {
stop = false;
}
function singleLetters($words) {
$words.each(function(){
var word = $(this),
letters = word.text().split(''),
selected = word.hasClass('is-visible');
for (i in letters) {
if(word.parents('.rotate-2').length > 0) letters[i] = '<em>' + letters[i] + '</em>';
letters[i] = (selected) ? '<i class="in">' + letters[i] + '</i>': '<i>' + letters[i] + '</i>';
}
var newLetters = letters.join('');
word.html(newLetters).css('opacity', 1);
});
}
function animateHeadline($headlines) {
var duration = animationDelay;
$headlines.each(function(){
var headline = $(this);
if(headline.hasClass('loading-bar')) {
duration = barAnimationDelay;
setTimeout(function(){ headline.find('.cd-words-wrapper').addClass('is-loading') }, barWaiting);
} else if (headline.hasClass('clip')){
var spanWrapper = headline.find('.cd-words-wrapper'),
newWidth = spanWrapper.width() + 10
spanWrapper.css('width', newWidth);
} else if (!headline.hasClass('type') ) {
//assign to .cd-words-wrapper the width of its longest word
var words = headline.find('.cd-words-wrapper b'),
width = 0;
words.each(function(){
var wordWidth = $(this).width();
if (wordWidth > width) width = wordWidth;
});
headline.find('.cd-words-wrapper').css('width', width);
};
//trigger animation
setTimeout(function(){ hideWord( headline.find('.is-visible').eq(0) ) }, duration);
});
}
function hideWord($word) {
var nextWord = takeNext($word);
if($word.parents('.cd-headline').hasClass('type')) {
var parentSpan = $word.parent('.cd-words-wrapper');
parentSpan.addClass('selected').removeClass('waiting');
setTimeout(function(){
parentSpan.removeClass('selected');
$word.removeClass('is-visible').addClass('is-hidden').children('i').removeClass('in').addClass('out');
}, selectionDuration);
setTimeout(function(){ showWord(nextWord, typeLettersDelay) }, typeAnimationDelay);
} else if($word.parents('.cd-headline').hasClass('letters')) {
var bool = ($word.children('i').length >= nextWord.children('i').length) ? true : false;
hideLetter($word.find('i').eq(0), $word, bool, lettersDelay);
showLetter(nextWord.find('i').eq(0), nextWord, bool, lettersDelay);
} else if($word.parents('.cd-headline').hasClass('clip')) {
$word.parents('.cd-words-wrapper').animate({ width : '2px' }, revealDuration, function(){
switchWord($word, nextWord);
showWord(nextWord);
});
} else if ($word.parents('.cd-headline').hasClass('loading-bar')){
$word.parents('.cd-words-wrapper').removeClass('is-loading');
switchWord($word, nextWord);
setTimeout(function(){ hideWord(nextWord) }, barAnimationDelay);
setTimeout(function(){ $word.parents('.cd-words-wrapper').addClass('is-loading') }, barWaiting);
} else {
switchWord($word, nextWord);
setTimeout(function(){ hideWord(nextWord) }, animationDelay);
}
}
function showWord($word, $duration) {
if($word.parents('.cd-headline').hasClass('type')) {
showLetter($word.find('i').eq(0), $word, false, $duration);
$word.addClass('is-visible').removeClass('is-hidden');
} else if($word.parents('.cd-headline').hasClass('clip')) {
$word.parents('.cd-words-wrapper').animate({ 'width' : $word.width() + 10 }, revealDuration, function(){
setTimeout(function(){ hideWord($word) }, revealAnimationDelay);
});
}
}
function hideLetter($letter, $word, $bool, $duration) {
$letter.removeClass('in').addClass('out');
if(!$letter.is(':last-child')) {
setTimeout(function(){ hideLetter($letter.next(), $word, $bool, $duration); }, $duration);
} else if($bool) {
setTimeout(function(){ hideWord(takeNext($word)) }, animationDelay);
}
if($letter.is(':last-child') && $('html').hasClass('no-csstransitions')) {
var nextWord = takeNext($word);
switchWord($word, nextWord);
}
}
function showLetter($letter, $word, $bool, $duration) {
$letter.addClass('in').removeClass('out');
if(!$letter.is(':last-child')) {
setTimeout(function(){ showLetter($letter.next(), $word, $bool, $duration); }, $duration);
} else {
if($word.parents('.cd-headline').hasClass('type')) { setTimeout(function(){ $word.parents('.cd-words-wrapper').addClass('waiting'); }, 200);}
if(!$bool) { setTimeout(function(){ hideWord($word) }, animationDelay) }
}
}
function takeNext($word) {
if(stop == true) {
return $word.parent().children().eq(0);
}
else {
return (!$word.is(':last-child')) ? $word.next() : $word.parent().children().eq(0);
}
}
function takePrev($word) {
return (!$word.is(':first-child')) ? $word.prev() : $word.parent().children().last();
}
function switchWord($oldWord, $newWord) {
$oldWord.removeClass('is-visible').addClass('is-hidden');
$newWord.removeClass('is-hidden').addClass('is-visible');
}
Here's a way:
$(window).scroll(function() {
return ($(this).scrollTop() < 200) && $(window).myFunction();
});
The function will only execute under 200px scrollTop position.
JS Fiddle Demo
Edit Updated with your code:
$(document).scroll(function() {
var scroll = $(this).scrollTop();
return ( scroll < 200
&& $(window).wordAnimate()
&& $('.logo').removeClass('opaque').addClass('transparent')
)
|| $('.logo').removeClass('transparent').addClass('opaque');
});

setTimeout with jQuery.hover() overlapping

I've got an effect I want triggered one second after page load, then subsequently every 3 seconds (on repeat). When the user hovers over an element (#hover), the effect pauses (temporarily). When they stop hovering over it, the effect resumes after 2 seconds.
I'm having a lot of trouble with overlapping sounds and animations, particularly when I hover and then unhover over the element quickly. What's wrong with my code? (Fiddle)
var test;
function hoverTest(arg) {
if (arg == 'stop') {
clearTimeout(test);
}
if (arg == 'start') {
playSound();
$('#hover').transition({
opacity: 0,
duration: 1000,
complete: function() {
$('#hover').transition({
opacity: 1,
duration: 1000,
complete: function() {
test = setTimeout(function() { hoverTest('start'); }, 3000);
}
});
}
});
}
}
$('#hover').hover(function() {
hoverTest('stop');
}, function() {
setTimeout(function() {
hoverTest('start');
}, 2000);
});
function playSound() {
var sound = new Audio('sound.mp3');
sound.play();
}
setTimeout(function() {
hoverTest('start');
}, 1000);
copy paste this in a file and run that html file.
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<style>
#hover {
width: 100px;
height: 100px;
background: red;
}
</style>
<div id="hover"></div>
<script type="text/javascript">
var interval = null;
var hoverTest = function(method){
playSound();
$("#hover").fadeOut(1000, function() {
$(this).fadeIn(1000);
});
}
var playSound =function() {
var sound = new Audio('http://www.sounddogs.com/previews/25/mp3/306470_SOUNDDOGS__an.mp3');
sound.play();
}
$(document).ready(function(){
interval = setInterval('hoverTest()',3000);
$("#hover").mouseenter(function(){
clearInterval(interval);
}).mouseleave(function(){
interval = setInterval('hoverTest()',3000);
})
})
</script>
Try adding "clearTimeout(test);" the first thing in the hoverTest function.
eg:
var test;
function hoverTest(arg) {
clearTimeout(test);
if (arg == 'stop') {
clearTimeout(test);
}
if (arg == 'start') {
playSound();
$('#hover').transition({
opacity: 0,
duration: 1000,
complete: function() {
$('#hover').transition({
opacity: 1,
duration: 1000,
complete: function() {
test = setTimeout(function() { hoverTest('start'); }, 3000);
}
});
}
});
}
}
Try this: (clear the timer before starting)
$('#hover').hover(function() {
hoverTest('stop');
}, function() {
clearTimeout(test);
setTimeout(function() {
hoverTest('start');
}, 2000);
});

JavaScript Image Flip

I have some code that is running a JavaScript image flip, I'm new to JS and I need the image to flip when hovered and and hovered off, if I put it to onhover it flips everytime the mouse is moved, not when the mouse is off.
Here is the code:
$(document).ready(function () {
setInterval(function () {
$('.sponsorFlip').load('script.js');
$('.sponsorFlip').load('jquery.flip.min.js');
}, 30000);
$('.sponsorFlip').one("mouseenter mouseleave", function () {
var elem = $(this);
if (elem.data('flipped')) {
elem.revertFlip();
elem.data('flipped', false)
}
else {
elem.flip({
direction: 'rl',
speed: 250,
onBefore: function () {
elem.html(elem.siblings('.sponsorData').html());
}
});
elem.data('flipped', true);
}
});
$('.sponsorFlip').bind("click", function () {
var elem = $(this);
if (elem.data('flipped')) {
elem.revertFlip();
elem.data('flipped', false)
}
else {
elem.flip({
direction: 'rl',
speed: 250,
onBefore: function () {
elem.html(elem.siblings('.sponsorData').html());
}
});
elem.data('flipped', true);
}
});
});
Make use of classes. ;) Preview - http://jsfiddle.net/TJZmM/3/
$('div').bind('mouseover mouseout', function(){
var self = $(this);
if(self.toggleClass('flipped').hasClass('flipped')) {
self.html('rl');
}
else {
self.html('lr');
}
});​

How to activate setInterval() incase a text control has the focus

Actually I have an update enquery into this point .
I have smth like that :
$(document).ready(function() {
setInterval(doSmth, 10000);
function doSmth() {
var result = document.getElementById("fooText").value;
if (result != "") {
doSmthElse(result);
}
});
}
}
});
I need to activate the interval ,that is fired each 10 seconds, in case only a text control has the focus else do nothing !!
Code for you is:
$(document).ready(function() {
setInterval(function(){
var result = $("#fooText").val();
if (result != "") {
// if
} else {
// else
}
}, 10000);
You can set the interval on focus of the field, and clear it on blur:
var interval;
$(field).focus(function() {
interval = setInterval(doMsth, 10000);
});
$(field).blur(function() {
clearInterval(interval);
});
(the interval var has to be global)
You can implement this in 2 ways,
Let the timer run and inside the function check if the activeElement == <text input>, then execute the rest of the function else return.
$(document).ready(function() {
setInterval(doSmth, 5000);
function doSmth() {
var resultEl = document.getElementById("fooText");
if (document.activeElement.id != resultEl.id) { return false; }
if (resultEl.value != "") {
doSmthElse(resultEl.value);
}
}
function doSmthElse(result) { alert(result);}
});
DEMO here
Set the timer on focus of the text box and remove the timer onblur of the input box.
$('#fooText').focus ( function () {
timer = setInterval(function() {
var textVal = $('#fooText').val();
if (textVal != '') {
doSmthElse(textVal );
}
}, 5000);
});
$('#fooText').blur (function () {
if (timer != '') clearInterval(timer);
});
DEMO here

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