Trigger function when the page stops scrolling - javascript

How can I trigger a function when the browser window stops scrolling? Either by mouse wheel, click, space bar or arrow key? Is there any event for such action? I have tried to search online but couldn't get any solution. I'm fine with a jQuery solution.

There's no "event" but you could make your own, like this:
$(function() {
var timer;
$(window).scroll(function() {
clearTimeout(timer);
timer = setTimeout(function() {
$(window).trigger("scrollStop");
}, 250);
});
});
Then you could bind to it, like this:
$(window).bind("scrollStop", function() {
alert("No one has scrolled me in 250ms, where's the love?");
});
This creates an event, there's no "stop" for this, but you can define your own... in this case "stop" is defined as "hasn't scrolled in 250ms", you can adjust the timer to your liking, but that's the idea.
Also, if you're just doing one thing there's no need for an event, just put your code where I'm calling $(window).trigger("scrollStop") and it'll run n milliseconds after the scroll stops.

The Non-jQuery Javascript version of the chosen answer:
var elem = document.getElementById('test');
(() => {
var onScrollStop = (evt) => {
// you have scroll event as evt (for any additional info)
var scrollStopEvt = new CustomEvent('scrolling-stopped', {detail: 'foobar stopped :)'});
elem.dispatchEvent(scrollStopEvt);
}
var scrollStopLag = 300 // the duration to wait before onScrollStop is triggerred.
var timerID = 0;
const handleScroll = (evt) => {
clearInterval(timerID);
timerID = setTimeout(
() => onScrollStop(evt),
scrollStopLag
)
}
elem.addEventListener('scroll', handleScroll);
})()
elem.addEventListener(
'scrolling-stopped',
(evt) => console.log(evt.detail)
)
#test {
height: 300px;
width: 300px;
overflow: auto;
}
#test #test-inner {
height: 3000px;
background: linear-gradient(lightseagreen 0%, lightyellow 40%, lightcoral 100%);
}
<h4>Scroll inside the green box below:</h4>
<div id="test">
<div id="test-inner"></div>
</div>
Good Luck...
P.S. I am a BIG fan of jQuery :)

Related

Detect when scrollIntoView stopped scrolling [duplicate]

I am using Javascript method Element.scrollIntoView()
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Is there any way I can get to know when the scroll is over. Say there was an animation, or I have set {behavior: smooth}.
I am assuming scrolling is async and want to know if there is any callback like mechanism to it.
There is no scrollEnd event, but you can listen for the scroll event and check if it is still scrolling the window:
var scrollTimeout;
addEventListener('scroll', function(e) {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function() {
console.log('Scroll ended');
}, 100);
});
2022 Update:
The CSS specs recently included the overscroll and scrollend proposal, this proposal adds a few CSS overscroll attributes, and more importantly to us, a scrollend event.
Browsers are still working on implementing it. (It's already available in Chromium under the Web Platforms Experiments flag.)
We can feature-detect it by simply looking for
if (window.onscrollend !== undefined) {
// we have a scrollend event
}
While waiting for implementations everywhere, the remaining of this answer is still useful if you want to build a polyfill:
For this "smooth" behavior, all the specs say[said] is
When a user agent is to perform a smooth scroll of a scrolling box box to position, it must update the scroll position of box in a user-agent-defined fashion over a user-agent-defined amount of time.
(emphasis mine)
So not only is there no single event that will fire once it's completed, but we can't even assume any stabilized behavior between different browsers.
And indeed, current Firefox and Chrome already differ in their behavior:
Firefox seems to have a fixed duration set, and whatever the distance to scroll is, it will do it in this fixed duration ( ~500ms )
Chrome on the other hand will use a speed, that is, the duration of the operation will vary based on the distance to scroll, with an hard-limit of 3s.
So this already disqualifies all the timeout based solutions for this problem.
Now, one of the answers here has proposed to use an IntersectionObserver, which is not a too bad solution, but which is not too portable, and doesn't take the inline and block options into account.
So the best might actually be to check regularly if we did stop scrolling. To do this in a non-invasive way, we can start an requestAnimationFrame powered loop, so that our checks are performed only once per frame.
Here one such implementation, which will return a Promise that will get resolved once the scroll operation has finished.
Note: This code misses a way to check if the operation succeeded, since if an other scroll operation happens on the page, all current ones are cancelled, but I'll leave this as an exercise for the reader.
const buttons = [ ...document.querySelectorAll( 'button' ) ];
document.addEventListener( 'click', ({ target }) => {
// handle delegated event
target = target.closest('button');
if( !target ) { return; }
// find where to go next
const next_index = (buttons.indexOf(target) + 1) % buttons.length;
const next_btn = buttons[next_index];
const block_type = target.dataset.block;
// make it red
document.body.classList.add( 'scrolling' );
smoothScroll( next_btn, { block: block_type })
.then( () => {
// remove the red
document.body.classList.remove( 'scrolling' );
} )
});
/*
*
* Promised based scrollIntoView( { behavior: 'smooth' } )
* #param { Element } elem
** ::An Element on which we'll call scrollIntoView
* #param { object } [options]
** ::An optional scrollIntoViewOptions dictionary
* #return { Promise } (void)
** ::Resolves when the scrolling ends
*
*/
function smoothScroll( elem, options ) {
return new Promise( (resolve) => {
if( !( elem instanceof Element ) ) {
throw new TypeError( 'Argument 1 must be an Element' );
}
let same = 0; // a counter
let lastPos = null; // last known Y position
// pass the user defined options along with our default
const scrollOptions = Object.assign( { behavior: 'smooth' }, options );
// let's begin
elem.scrollIntoView( scrollOptions );
requestAnimationFrame( check );
// this function will be called every painting frame
// for the duration of the smooth scroll operation
function check() {
// check our current position
const newPos = elem.getBoundingClientRect().top;
if( newPos === lastPos ) { // same as previous
if(same ++ > 2) { // if it's more than two frames
/* #todo: verify it succeeded
* if(isAtCorrectPosition(elem, options) {
* resolve();
* } else {
* reject();
* }
* return;
*/
return resolve(); // we've come to an halt
}
}
else {
same = 0; // reset our counter
lastPos = newPos; // remember our current position
}
// check again next painting frame
requestAnimationFrame(check);
}
});
}
p {
height: 400vh;
width: 5px;
background: repeat 0 0 / 5px 10px
linear-gradient(to bottom, black 50%, white 50%);
}
body.scrolling {
background: red;
}
<button data-block="center">scroll to next button <code>block:center</code></button>
<p></p>
<button data-block="start">scroll to next button <code>block:start</code></button>
<p></p>
<button data-block="nearest">scroll to next button <code>block:nearest</code></button>
<p></p>
<button>scroll to top</button>
You can use IntersectionObserver, check if element .isIntersecting at IntersectionObserver callback function
const element = document.getElementById("box");
const intersectionObserver = new IntersectionObserver((entries) => {
let [entry] = entries;
if (entry.isIntersecting) {
setTimeout(() => alert(`${entry.target.id} is visible`), 100)
}
});
// start observing
intersectionObserver.observe(element);
element.scrollIntoView({behavior: "smooth"});
body {
height: calc(100vh * 2);
}
#box {
position: relative;
top:500px;
}
<div id="box">
box
</div>
I stumbled across this question as I wanted to focus a particular input after the scrolling is done (so that I keep the smooth scrolling).
If you have the same usecase as me, you don't actually need to wait for the scroll to be finished to focus your input, you can simply disable the scrolling of focus.
Here is how it's done:
window.scrollTo({ top: 0, behavior: "smooth" });
myInput.focus({ preventScroll: true });
cf: https://github.com/w3c/csswg-drafts/issues/3744#issuecomment-685683932
Btw this particular issue (of waiting for scroll to finish before executing an action) is discussed in CSSWG GitHub here: https://github.com/w3c/csswg-drafts/issues/3744
Solution that work for me with rxjs
lang: Typescript
scrollToElementRef(
element: HTMLElement,
options?: ScrollIntoViewOptions,
emitFinish = false,
): void | Promise<boolean> {
element.scrollIntoView(options);
if (emitFinish) {
return fromEvent(window, 'scroll')
.pipe(debounceTime(100), first(), mapTo(true)).toPromise();
}
}
Usage:
const element = document.getElementById('ELEM_ID');
scrollToElementRef(elment, {behavior: 'smooth'}, true).then(() => {
// scroll finished do something
})
These answers above leave the event handler in place even after the scrolling is done (so that if the user scrolls, their method keeps getting called). They also don't notify you if there's no scrolling required. Here's a slightly better answer:
$("#mybtn").click(function() {
$('html, body').animate({
scrollTop: $("div").offset().top
}, 2000);
$("div").html("Scrolling...");
callWhenScrollCompleted(() => {
$("div").html("Scrolling is completed!");
});
});
// Wait for scrolling to stop.
function callWhenScrollCompleted(callback, checkTimeout = 200, parentElement = $(window)) {
const scrollTimeoutFunction = () => {
// Scrolling is complete
parentElement.off("scroll");
callback();
};
let scrollTimeout = setTimeout(scrollTimeoutFunction, checkTimeout);
parentElement.on("scroll", () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(scrollTimeoutFunction, checkTimeout);
});
}
body { height: 2000px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="mybtn">Scroll to Text</button>
<br><br><br><br><br><br><br><br>
<div>example text</div>
i'm not an expert in javascript but i made this with jQuery. i hope it helps
$("#mybtn").click(function() {
$('html, body').animate({
scrollTop: $("div").offset().top
}, 2000);
});
$( window ).scroll(function() {
$("div").html("scrolling");
if($(window).scrollTop() == $("div").offset().top) {
$("div").html("Ended");
}
})
body { height: 2000px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="mybtn">Scroll to Text</button>
<br><br><br><br><br><br><br><br>
<div>example text</div>
I recently needed callback method of element.scrollIntoView(). So tried to use the Krzysztof Podlaski's answer.
But I could not use it as is. I modified a little.
import { fromEvent, lastValueFrom } from 'rxjs';
import { debounceTime, first, mapTo } from 'rxjs/operators';
/**
* This function allows to get a callback for the scrolling end
*/
const scrollToElementRef = (parentEle, childEle, options) => {
// If parentEle.scrollTop is 0, the parentEle element does not emit 'scroll' event. So below is needed.
if (parentEle.scrollTop === 0) return Promise.resolve(1);
childEle.scrollIntoView(options);
return lastValueFrom(
fromEvent(parentEle, 'scroll').pipe(
debounceTime(100),
first(),
mapTo(true)
)
);
};
How to use
scrollToElementRef(
scrollableContainerEle,
childrenEle,
{
behavior: 'smooth',
block: 'end',
inline: 'nearest',
}
).then(() => {
// Do whatever you want ;)
});

How to constantly trigger an event when hovered over that element?

So, I have a button and I want to constantly have an event triggering when the button is hovered. If I use mouseover, then this event triggers only once when the cursor comes on it from somewhere outside.
btn.addEventListener("mouseover", function(){
console.log("Hello");
});
For instance, I want this console log to happen constantly while the cursor is over the button.
Please check if mousemove event works for you.
let interval = null;
btn.addEventListener("mousemove", function(){
console.log("Hello");
});
btn.addEventListener('mouseenter', function(){
interval= setInterval(()=>console.log('Hello'), 100)
})
btn.addEventListener('mouseout', function(){
clearInterval(interval)
})
#btn{
width: 300px;
height: 60px;
border-radius: 8px;
}
<button id="btn">
hover me
</button>
You could do this by using mouseover and mouseout (and a setInterval). Basically, start an interval when the mouse enters, and clear it when it exits.
let interval;
btn.addEventListener("mouseover", function(){
interval = setInterval(function() {
console.log("Hello");
}, 100);
});
btn.addEventListener("mouseout", function(){
clearInterval(interval);
});
You can use a combination of
flags, either on the elements themselves as here, or as separate variable(s)
a setInterval function
to figure out which elements are being hovered at any given time. (This is obviously a slightly silly example since you can't very well mouse-over multiple elements that sit next to each other at a time.)
function addEventListeners(button) {
button.addEventListener("mouseover", () => button.dataset.hovered = "1");
button.addEventListener("mouseout", () => button.dataset.hovered = "0");
}
function reportHovers(elements) {
const hoveredIds = elements.filter(el => el.dataset.hovered === "1").map(el => el.id);
document.getElementById("out").value = `${Math.floor(new Date() / 1000)}\n${JSON.stringify(hoveredIds)}`;
}
var buttons = Array.from(document.querySelectorAll("button"));
buttons.forEach(button => addEventListeners(button));
setInterval(() => reportHovers(buttons), 100);
<button id="b1">Button 1</button>
<button id="b2">Button 2</button>
<button id="b3">Button 3</button>
<textarea id="out"></textarea>

Avoid mouseover mouseleave conflicts

I'm working with this js fiddle here: http://jsfiddle.net/tPx6x/
The animation works like so
You hover over the text, a circle fades in & begins to pulse 1 second later for as long as your mouse is over the text.
When your mouse pointer leaves the text, the pulse stops after one second and the circle fades out.
The issue arises when you do this:
Put your mouse over the text, remove the pointer from the text, THEN place the pointer back over the text before the script has a chance to finish(1-1.4s).
You won't be able to make the circle appear properly agin...you will have to allow the script to reset. That is the problem.
What is the best way to tackle this issue?
Example code:
<div class='circle__title_project-management'>
<h1>project management</h1>
</div>
<div class='circle__project-management hidden'></div>
.circle__project-management, .circle__title_project-management
{
display: inline-block;
cursor: pointer;
}
.circle__project-management
{
margin-left: 8px;
vertical-align: -4.07px;
background-color: transparent;
border: 2px solid #00DBFF;
width: 30px;
height: 30px;
border-radius: 90px;
top: 280px;
left: 40px;
}
.hidden
{
visibility: hidden;
}
.visible
{
visibility: visible;
}
.animate-infinite
{
animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-webkit-animation-iteration-count: infinite;
}
var circleTitle = $('.circle__title_project-management h1');
var circle = $('.circle__project-management');
var initTimeout = 1000;
var initTimeoutPlus = 1400;
circleTitle.mouseover( function() {
circle.removeClass('hidden');
circle.addClass('animated fadeIn');
setTimeout( function() {
circle.addClass('pulse animate-infinite');
circle.removeClass('fadeIn');
}, initTimeout);
});
circleTitle.mouseleave( function() {
setTimeout( function() {
circle.stop().removeClass('pulse animate-infinite visibility');
circle.addClass('fadeOut');
}, initTimeout);
setTimeout( function() {
circle.removeClass('fadeOut');
circle.addClass('hidden');
}, 1400);
});
You should note that setTimeout has a return value. You want to clear previous timeouts before you start new ones; otherwise you can get a timeout queue which completely skews your animations. Something like this:
var myTimeout;
...
clearTimeout(myTimeout);
myTimeout = setTimeout(...);
Not sure if this is exactly what you were going for, but along these lines: http://jsfiddle.net/FYY38/
More info here: http://www.w3schools.com/js/js_timing.asp
Also, it looks like the circle.stop() call is doing nothing (as it's css-animated)
To avoid antagonist behaviours, maybe add a class to your element to tag it when the event is triggered and remove it when another is triggered.
That way you can stay in control of what's going on.
you can set time out to mouse over function to cover the time delay for mouseleave.
note that the first run must be without delay
var initTimeout = 1000;
var initTimeoutPlus = 1400;
var firstrun = true;
circleTitle.mouseover( function() {
if (firstrun) {
initTimeoutPlus = 0;
firstrun = false;
} else initTimeoutPlus = 1400;
setTimeout(function() {
circle.removeClass('hidden');
circle.addClass('animated fadeIn');
setTimeout( function() {
circle.addClass('pulse animate-infinite');
circle.removeClass('fadeIn');
}, initTimeout);
}, initTimeoutPlus);
});
Probably if you just add a key on mouseover, and toggle it after mouseleave, and before you trigger any mouseleave timeout events, check the key, if it is set, ignore, else go ahead and execute mouseleave
this way if the key is "on" it means a mouse over occurred, if it was off, it means the mouseleave occurred and it is still occurring
var key = false;
circleTitle.mouseover( function() {
key = true;
circle.removeClass('hidden');
circle.addClass('animated fadeIn');
setTimeout( function() {
circle.addClass('pulse animate-infinite');
circle.removeClass('fadeIn');
}, initTimeout);
});
circleTitle.mouseleave( function() {
key = false;
setTimeout( function() {
if (!key){
circle.stop().removeClass('pulse animate-infinite visibility');
circle.addClass('fadeOut');
}
}, initTimeout);
setTimeout( function() {
if (!key){
circle.removeClass('fadeOut');
circle.addClass('hidden');
}
}, 1400);
});

Disable scrolling, but maintain ability to zoom

On a responsive site I'm developing I have my own little lightbox-script which opens images fullscreen while maintaining their aspect ratio. It's pretty simple, uses 2 divs (outer fullscreen-div with black background "lbBlack" and inner div with image "lbImg"):
//super small lightbox ;)
$("#posts").on("click", ".img", function(event) {
$('#lbBlack').css('top',$(document).scrollTop());
$('#lbImg').attr('src', $(this).attr('src'));
$('#lbBlack').css('width',$(window).width());
$('#lbBlack').css('height',window.innerHeight);
$('#lbBlack').fadeIn(500);
$('#lbImg').css('margin-top',((window.innerHeight-$('#lbImg').height()))/2);
document.body.style.overflow="hidden";
document.ontouchmove = function(event){
event.preventDefault();
}
$('#lbBlack').on("click", "#lbImg, body", function(event) {
$('#lbBlack').fadeOut(500);
document.body.style.overflow="visible";
document.ontouchmove = function(event){
return true;
}
});
});
For iOS, I had to add the ontouchmove-prevention, because body-overflow-hidden wasn't enough to avoid scrolling while the lightbox is opened.
Now the "big problem" for this working solution above: I want to enable zooming on the image. This is prevented with the "ontouchmove"-code.
Any ideas?
HTML-code:
<body>
<div id="lbBlack">
<img id="lbImg">
</div>.....
CSS-code:
#lbBlack {
display: none;
position: absolute;
left: 0;
background-color: black;
z-index: 2001;
text-align: center;
}
#lbBlack #lbImg {
max-height: 100%;
max-width: 100%;
position: relative;
}
So I think what I am looking for is a method to prevent scrolling while still maintaining the possibility to zoom. I still don't get it why body-overflow:hidden still has the ability to scroll on iOS??
Well, Raphael,
this might not be perfect, but it should get you going in the right direction. I tested on Android, my buddy who handles the Apple stuff is unavailable at the moment. Scrolling and other moving is disabled, but you can zoom. One problem, however, is when you are actually in the process of pinch zooming you can move the picture around. You could always snap the picture back to the center after the pinch zoom is complete. (That might even look neat).
Notice I added a method to the jQuery prototype and a property to the jQuery.Event prototype.
/*global console, $*/
/*jslint browser: true*/
(function () {
"use strict";
$.fn.detectPinch = function () {
var numTouches = 0;
// each finger touch triggers touchstart
// (even if one finger is already touching)
$(document).on('touchstart', function (event) {
// if numTouches is more than 1, reset it to 0
// or else you can have numTouches >= 2 when
// actually only one finger is touching
numTouches = (numTouches > 1) ? 0 : numTouches;
// if numTouches is 0 or 1, increment it
numTouches = (numTouches < 2) ? numTouches += 1 : 2;
console.log(numTouches + ' start');
}).on('touchend', function (event) {
// another safety check: only decrement if > 0
numTouches = (numTouches > 0) ? numTouches -= 1 : 0;
console.log(numTouches + ' end');
});
// all event objects inherit this property
$.Event.prototype.isPinched = function () {
return (numTouches === 2) ? true : false;
};
return this;
};
$(document).ready(function (event) {
// call the method we added to the prototype
$(document).detectPinch();
$("#posts").on("click", "img", function (event) {
$(this).css('visibility', 'hidden');
$('#lbBlack').css('top', $(document).scrollTop());
$('#lbImg').attr('src', $(this).attr('src'));
$('#lbBlack').css('width', $(window).width());
$('#lbBlack').css('height', window.innerHeight);
$('#lbBlack').fadeIn(500);
$('#lbImg').css('margin-top', ((window.innerHeight - $('#lbImg').height())) / 2);
document.body.style.overflow = "hidden";
});
$('#lbBlack').on("click", "#lbImg, body", function (event) {
$('#lbBlack').fadeOut(500);
$('#posts img').css('visibility', 'visible');
document.body.style.overflow = "visible";
});
}).on('touchmove', function (event) {
// prevent one-finger movements
if (!event.isPinched()) {
event.preventDefault();
console.log('prevented');
}
});
}());

Button hiding not functioning properly

HTML Code:
<div id="slick-slidetoggle">wxyz</div>
<div id="slickbox" >abcd</div>​
JavaScript:
var hoverVariable=false;
var hoverVariable2=false;
$('#slickbox').hide();
$('#slick-slidetoggle').mouseover(function() {
hoverVariable2=true;
$('#slickbox').slideToggle(600);
return false;
})
$('#slick-slidetoggle').mouseleave(function() {
hoverVariable2=false;
setTimeout(function (){
if(!hoverVariable && !hoverVariable2){
$('#slickbox').slideToggle(600);
return false;}
}, 1000);
})
$('#slickbox').mouseleave(function() {
hoverVariable=false;
setTimeout(function (){
if(!hoverVariable && !hoverVariable2){
$('#slickbox').slideToggle(600);
return false;}
return false;
}, 1000);
})
$('#slickbox').mouseover(function() {
hoverVariable2=false;
hoverVariable=true;
})​
CSS Code:
#slickbox {
background: black;
width:100px;
height: 135px;
display: none;
cursor:pointer;
color:white;
}
#slick-slidetoggle{
background: yellow;
width:100px;
height: 135px;
cursor:pointer;
color:black;
}
​
Now the desired behaviour is that when mouse is slide over yellow div("wxyz") black div("abcd") should slide down and if mouse is moved out of yellow without moving on to black div, the black div should hide after two seconds.
This is happening. If mouse is moved over black div immediately after moving out of yellow div the black div should not hide as long as the mouse is on the black div. This is also happening.
Next steps are bit difficult to explain but I'll try, when mouse is moved over yellow div and black div comes out then mouse is moved over black div and within two seconds if it moved out of it(black div) then the whole animation goes haywire. Its behaviour is reversed. But if the mouse is kept on black div for more than two seconds and then it is moved out then the whole script runs fine.
This is the link to explain better. http://jsfiddle.net/HAQyK/381/
Try replacing slideToggle() with the appropriate slideUp() and slideDown() calls. http://jsfiddle.net/tppiotrowski/HAQyK/386/
var hoverVariable = false;
var hoverVariable2 = false;
$('#slickbox').hide();
$('#slick-slidetoggle').mouseover(function() {
hoverVariable2 = true;
$('#slickbox').slideDown(600);
return false;
})
$('#slick-slidetoggle').mouseleave(function() {
hoverVariable2 = false;
setTimeout(function() {
if (!hoverVariable && !hoverVariable2) {
$('#slickbox').slideUp(600);
return false;
}
}, 1000);
})
$('#slickbox').mouseleave(function() {
hoverVariable = false;
setTimeout(function() {
if (!hoverVariable && !hoverVariable2) {
$('#slickbox').slideUp(600);
return false;
}
return false;
}, 1000);
})
$('#slickbox').mouseover(function() {
hoverVariable2 = false;
hoverVariable = true;
})​
I re-coded a solution. Checkout the fiddle here
var hideB;
var $black = $('#slickbox');
var $yellow = $('#slick-slidetoggle');
function showBlack() {
if( hideB ) window.clearTimeout( hideB );
$black.stop( true, true );
$black.slideDown(600);
}
function hideBlack() {
hideB = setTimeout( function( ) {
$black.stop( true, true );
$black.slideUp( 600 ); }
, 1000 );
}
$black.hide();
$yellow.mouseenter(function() {
showBlack();
})
$yellow.mouseleave(function() {
hideBlack();
});
$black.mouseleave( function( ) {
hideBlack();
});
$black.mouseenter( function( ) {
showBlack();
});
Your problem seems to be that the slideToggle in firing twice in quick succession because of your duplicate timeout functions. The cleanest way to deal with timeouts or intervals is to store them in a variable to give you the control of removing them when not needed:
// Defined in global scope
var timer;
$('#slick-slidetoggle').mouseleave(function() {
hoverVariable2=false;
// Timer set as function
timer = setTimeout(function (){
if(!hoverVariable && !hoverVariable2){
$('#slickbox').slideToggle(600);
// Timer no longer need and so cleared
clearTimeout(timer);
return false;}
}, 1000);
});
EDIT: Neglected to add the slideUp/slideDown instead of Toggle as per the correct answer above. See the updated jsFiddle which is now correct: http://jsfiddle.net/HAQyK/390/
Another way you could approach your script is to use jQuerys delay funciton and the stop(); method for animation. Wrap the divs in a container and you've got a much simpler block of code:
$('#slick-container').mouseenter(function() {
$('#slickbox').stop().slideDown(600);
}).mouseleave(function(){
$('#slickbox').stop().delay(1000).slideUp(600);
});
Check it out here: http://jsfiddle.net/HAQyK/387/

Categories