Hide block on timeout by jQuery - javascript

We have a block invisible by default and links. When we hover on link, its rel attribute puts to block like a text.
What I'm trying to do:
If link is hovered and block is invisible {
show block by fadeIn;
change text inside block (get it from link's rel);
} else {
just change text inside block (block is already visible, no fadeIn effect);
}
If link is unhovered and block is visible {
start timeout {
after 2 seconds hide block by fadeOut;
}
}
Here is what I'm currently have: http://jsfiddle.net/Bt3mL/1/
Everything works, but there is a problem - fadeOut on mouseleave should not start, if some link is currently hovered. Something like timeout reset can be useful, but I don't understand how to add it to my code.
Now, when I hover a link and then unhover it, timeout begins, but if I hover on other link while block is visible, because of the first timeout block can hide.
Please help.

Clearing the timeout will fix the problem : http://jsfiddle.net/jomanlk/veufa/
var __TIMER = null;
$("a").live('mouseenter', function(){
clearTimeout(__TIMER);
if ($("div").css('display')=='none'){
$("div").html($(this).attr("rel"));
$("div").fadeIn('fast');
} else {
$("div").html($(this).attr("rel"));
}
})
$("a").live('mouseleave', function(){
__TIMER = setTimeout(function(){
$("div").fadeOut('fast');
}, 1000);
});

try this:
var cancelHide = false;
$("a").live('mouseenter', function(){
cancelHide = true;
if ($("div").css('display')=='none'){
$("div").html($(this).attr("rel"));
$("div").fadeIn('fast');
} else {
$("div").html($(this).attr("rel"));
}
})
$("a").live('mouseleave', function(){
cancelHide = false;
setTimeout(function(){
if(cancelHide){ return; }
$("div").fadeOut('fast');
}, 1000);
});

Related

Change text if div is visible

The following jsFiddle changes text of #more depending on the visibility of #extra:
<style>
#extra{
display: none;
}
</style>
More about us
<div id="extra">Some Text</div>
<script>
$('#more').click(function() {
if ($('#extra').is(':visible')) {
$(this).text('Less about us');
} else {
$(this).text('More about us');
}
$('#extra').slideToggle('fast');
});
</script>
This works fine. However, it does not work anymore if I put the slideToggle() above the if-statement like this (see this jsFiddle):
$('#more').click(function() {
$('#extra').slideToggle('fast');
if ($('#extra').is(':visible')) {
$(this).text('More about us');
} else {
$(this).text('Less about us');
}
});
In this example, the text will remain "More about us" no matter if #extra is hidden or not. Why?
the code get's executed one line at a time, so by the time you enter the if, the slideToggle isn't finished so the element is visible.
You should put the if statement inside the slideToggle's complete callback http://api.jquery.com/slidetoggle/
$('#more').click(function() {
var _this = this;
$('#extra').slideToggle('fast', function() {
if($(this).is(':visible')) {
$(_this).text('Less about us');
}
else {
$(_this).text('More about us');
}
});
});
jsFiddle
This happens because the animation isn't done before you check the visibility. A cleaner solution would be this:
var visible = false;
$('#more').click(function() {
visible = !visible;
if (visible) $('#extra').slideDown();
else $('#extra').slideUp();
$(this).text(visible ? 'Less about us' : 'More about us');
});
Fiddle
This way you don't have to check the actual visibility of the element. You could use a callback to execute the code after the animation has completed, but that could cause an unwanted delay.

jQuery :visible working but :hidden does not

I'm working on this website.
Here is the code for the menu trigger on the left sidebar:
jQuery(document).ready( function(){
jQuery('.nav-animate nav').hide('slide', 500);
jQuery('.nav-animate').hide();
jQuery(".x-btn-navbar").click(function(){
jQuery('#dimmer').fadeToggle(500);
jQuery('.nav-animate').fadeToggle(500);
jQuery('.nav-animate nav').toggle('slide', {direction: "left"}, 750);
// I am trying to show only the middle line when the navigation is closed
// and change the `.menu-p` text by checking whether the navigation has
// display:none or display:block, like this:
if(jQuery(".nav-animate").is(":visible")) {
jQuery("span.line.top").css('background-color', '#fff');
jQuery('span.line.bottom').css('background-color', '#fff');
jQuery('.menu-p').html('CLOSE')
}
// The above part works perfectly, however the part below doesn't:
if(!jQuery(".nav-animate").is(':visible')) {
alert('hidden');
jQuery('span.line.top').css('background-color', '#262628');
jQuery('span.line.bottom').css('background-color', '#262628');
jQuery('.menu-p').html('MENU');
}
});
});
I tried using if(jQuery(".nav-animate").is(":hidden")) {//...}, and if(jQuery(".nav-animate").css('display') == 'none') {//...} but both doesn't work.
My guess, when you click to "CLOSE" it does the :visible or :hidden check, but the menu is still open at the time you click so it still doesn't have the display:none until the click event performs that. In that case, what can I do?
Thanks in advance for your time and suggestions.
animation related methods will affect the visibility check, so check the state before call to toggle
jQuery(document).ready(function () {
jQuery('.nav-animate nav').hide('slide', 500);
jQuery('.nav-animate').hide();
jQuery(".x-btn-navbar").click(function () {
jQuery('#dimmer').fadeToggle(500);
//negate since fadetoggle will toggle the state
var visible = !jQuery('.nav-animate').stop().is(':visible');
jQuery('.nav-animate').fadeToggle(500);
jQuery('.nav-animate nav').toggle('slide', {
direction: "left"
}, 750);
// I am trying to show only the middle line when the navigation is closed
// and change the `.menu-p` text by checking whether the navigation has
// display:none or display:block, like this:
if (visible) {
jQuery("span.line.top").css('background-color', '#fff');
jQuery('span.line.bottom').css('background-color', '#fff');
jQuery('.menu-p').html('CLOSE')
} else {
// The above part works perfectly, however the part below doesn't:
alert('hidden');
jQuery('span.line.top').css('background-color', '#262628');
jQuery('span.line.bottom').css('background-color', '#262628');
jQuery('.menu-p').html('MENU');
}
});
});
Just add condition else on one your block condition right.. It's mean will be run if first condition block not true.
if(!jQuery('.nav-animate').stop().is(':visible')) {
jQuery("span.line.top").css('background-color', '#fff');
jQuery('span.line.bottom').css('background-color', '#fff');
jQuery('.menu-p').html('CLOSE')
}
else{
// to do
}

jQuery Animations Control Sequence

I'm am attempting to build a homepage that has animations. I am having hard time controlling my animations though. All I need is to hide elements, and then show elements after a certain time. Loop through that sequence, and pause and show all elements when the someone hovers over the box. Example simple animation.
I have a long way to go. At first I tried using the .css() visibility property, now I'm using .show() and .hide().
I need a way to loop through my animations. I attempt to add another
setTimeout(clear1(), 3000);
to the end of my box1 function, but that wouldn't work for some reason.
I need a way to on a user hover over #box1, that all animations stop. I have tried using .clearQueue, but I couldn't get that to work.
First of all, set to your css:
.box {display: none;}
SHOW ALL BOXES ON HOVER See Demo
This will show all boxes on hover and then continue the animation from where it stopped (will hide the boxes that hadn't shown up during the animation). I think that is what you are after.
var index = 0; // To keep track of the last div showed during animation
var time_of_delay = 1000; // Set the time of delay
// Start the animation
$(document).ready(function () {
box1(time_of_delay);
});
// The hover states
$("#box1_1").hover(
function() {
box1(0);
}, function() {
box1(time_of_delay);
});
// The animation function
function box1 (delay_time) {
var time=delay_time;
if(time>0) {
$(".box").slice(index).each(function() {
$(this).hide().delay(time).show(0);
time=time+time_of_delay;
});
index=0;
} else {
$(".box:visible").each(function() {
index++;
});
$(".box").stop(true).show(0);
}
}
PAUSE ON HOVER See Demo
This will only pause the animation and continue from where it stopped.
var time_of_delay = 1000; // Set the time of delay
// Start the animation
$(document).ready(function () {
box1(time_of_delay);
});
// The hover states
$("#box1_1").hover(
function() {
box1(0);
}, function() {
box1(time_of_delay);
});
// The animation function
function box1 (delay_time) {
var time=delay_time;
if(time>0) {
$(".box:hidden").each(function() {
$(this).delay(time).show(0);
time=time+time_of_delay;
});
} else {
$(".box").stop(true);
}
}
I used setTimeout and clearTimeout and periodically call a function that increments (and resets) the box to display. Since I assign setTimout to boxt, I am able to call clearTimeout(boxt) on box1's hover event so that I can stop specifically that loop. Here's my jsfiddle. It might not be the exact effect you're trying to achieve, but it should be the right functionality and be easily adaptable with a few tweaks. Let me know if this works for you and if you have any questions about how it works :)
LIVE DEMO
var $box = $('#box1').find('.box'),
boxN = $box.length,
c = 0,
intv;
$box.eq(c).show(); // Show initially the '0' indexed .box (first one)
function loop(){
intv = setInterval(function(){
$box.eq(++c%boxN).fadeTo(400,1).siblings().fadeTo(400,0);
},1000);
}
loop(); // Start your loop
$('#box1').on('mouseenter mouseleave', function( e ){
return e.type=='mouseenter' ? (clearInterval(intv))($box.fadeTo(400,1)) : loop();
});
Where ++c%boxN will take care to loop your animation using the Modulo % (reminder) operator inside a setInterval. Than all you need to do is to register a mouseenter and mouseleave on the parent element to:
clear the Interval on mouseenter + fade all your elements
restart your loop function on mouseleave.
Here's one way to do it:
// hide all of the boxes
$('.box').hide();
// reference to each box, the current box in this list and a flag to stop the animation
var divs = box1.getElementsByClassName('box');
var i = 0;
var run = true;
// this will animate each box one after the other
function fade(){
if(i < divs.length && run){
$(divs[i++]).fadeIn(500, function(){
setTimeout(fade, 1000);
});
}
};
fade();
// stop the above function from running when the mouse enters `box1`
$('#box1').on('mouseenter', function(){console.log('enter');
run = false;
});
// start the function again from where we stopped it when the mouse leaves `box1`
$('#box1').on('mouseleave', function(){console.log('leave');
run = true;
fade();
});
Demo: http://jsfiddle.net/louisbros/dKcn5/

Removing and Adding CSS Class with jQuery

I've an area which I'd like to add an CSS animation to when it's clicked, and then bring it back with another animation when it's loading.
I'm using Twitter's Bootstrap's tabs and turned on the "fade" transition between the tabs, but want to specifically animate something inside of those tabs while they're switching. I don't want to mess with the root J.S. code there so I'll just settle with a work around.
Heres my code:
$(".tabit").click(function (){
//Drop Center Icon on click
if ($('.centericon').hasClass('fadeInDown')) {
$(".centericon").removeClass('fadeInDown').addClass("fadeOutDown").delay(100).queue(function(next){
$(this).removeClass("fadeOutDown").addClass("fadeInDown");
});
}
else{
$(".centericon").addClass("fadeOutDown").delay(100).queue(function(next){
$(this).removeClass("fadeOutDown").addClass("fadeInDown");
});
}
});
The .centericon class is repeated, so after 1 click, multiple instances will have the "fadeInDown" class. Works fine when I click one time, but if I click twice, then the .centericon only gets class .fadeOutDown.
$(".tabit").click(function (){
//Scroll to top when navigating through tabs
//Drop Center Icon on click
if ($('.centericon').hasClass('fadeInDown')) {
$(".centericon").removeClass('fadeInDown').addClass("fadeOutDown");
$(".centericon").delay(100).queue(function() {
$(this).removeClass('fadeOutDown');
$(this).dequeue();
});
$(".centericon").delay(100).removeClass('fadeOutDown').addClass("fadeInDown");
}
else{
$(".centericon").addClass("fadeOutDown");
$(".centericon").delay(100).queue(function() {
$(this).removeClass('fadeOutDown').addClass("fadeInDown");
$(this).dequeue();
});
}
});
Change click to toggle
$(".tabit").toggle(function () {
$(".centericon").removeClass('fadeInDown').addClass("fadeOutDown").delay(100).queue(function (next) {
$(this).removeClass("fadeOutDown").addClass("fadeInDown");
});
}, function () {
$(".centericon").addClass("fadeOutDown").delay(100).queue(function (next) {
$(this).removeClass("fadeOutDown").addClass("fadeInDown");
});
});

Delay animation until other animation is complete (sliding content(

I have this code which animates between divs sliding out. If an item is clicked, it's relevant content slides out. If another item is clicked, the current content slides back in and the new content slides out.
However,
var lastClicked = null;
var animateClasses = ['ale', 'bramling', 'bullet', 'miami-weisse'];
for (var i=0; i<animateClasses.length; i++) {
(function(animCls) {
$('.each-brew.'+animCls).toggle(function() {
if (lastClicked && lastClicked != this) {
// animate it back
$(lastClicked).trigger('click');
}
lastClicked = this;
$('.each-brew-content.'+animCls).show().animate({ left: '0' }, 1000).css('position','inherit');
}, function() {
$('.each-brew-content.'+animCls)
.animate({ left: '-33.3333%' }, 1000, function() { $(this).hide()}) // hide the element in the animation on-complete callback
.css('position','relative');
});
})(animateClasses[i]); // self calling anonymous function
}
However, the content sliding out once the already open content slides back is sliding out too quickly - it needs to wait until the content has fully slided back in before it slides out. Is this possible?
Here's a link to what I'm currently working on to get an idea (http://goo.gl/s8Tl6).
Cheers in advance,
R
Here's my take on it as a drop-in replacement with no markup changes. You want one of three things to happen when a menu item is clicked:
if the clicked item is currently showing, hide it
if something else is showing, hide it, then show the current item's content
if nothing is showing, show the current item's content
var lastClicked = null;
// here lastClicked points to the currently visible content
var animateClasses = ['ale', 'bramling', 'bullet', 'miami-weisse'];
for (var i=0; i<animateClasses.length; i++) {
(function(animCls) {
$('.each-brew.'+animCls).click(function(event){
if(lastClicked && lastClicked == animCls){
// if the lastClicked is `this` then just hide the content
$('.each-brew-content.'+animCls).animate(
{ left: '-33.3333%' }, 1000,
function() {
$(this).hide();
}).css('position','relative');
lastClicked = null;
}else{
if(lastClicked){
// if something else is lastClicked, hide it,
//then trigger a click on the new target
$('.each-brew-content.'+lastClicked).animate(
{ left: '-33.3333%' }, 1000,
function() {
$(this).hide();
$(event.target).trigger('click');
}).css('position','relative');
lastClicked = null;
}else{
// if there is no currently visible div,
// show our content
$('.each-brew-content.'+animCls).show()
.animate({ left: '0' }, 1000)
.css('position','relative');
lastClicked = animCls;
}
}
});
})(animateClasses[i]); // self calling anonymous function
}
Well, I'm pretty sure there are other more easy possibilities and I didn't have much time but here is a working jsfiddle: http://jsfiddle.net/uaNKz/
Basicly you use the callback function to wait until the animation is complete. In this special case it's the complete: function(){...}
$("document").ready(function(){
$('#ale').click(function(){
if ($('div').hasClass('toggled')){
$('.toggled').animate({ width: "toggle" }, { duration:250, complete: function(){
$('#alecont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');}
}).removeClass('toggled');
}else{
$('#alecont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');
}
});
$('#bramling').click(function(){
if ($('div').hasClass('toggled')){
$('.toggled').animate({ width: "toggle" }, { duration:250, complete: function(){
$('#bramcont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');}
}).removeClass('toggled');
}else{
$('#bramcont').animate({ width: "toggle" }, { duration:250 }).addClass('toggled');
}
});
});
I give a toggled class if a div is expanded. Since the animation on your page seems to be pretty much broken I think this would be a better way to do this. But remember: my code isn't really good. Just fast and it can be refactored. It's working tho..
Rather than using toggles, bind an on "click" handler to your ".each-brew" divs. In the handler, first hide content divs and then show the appropriate content when that animation completes. You can do that with either a promise or a callback. Something like this...
$(".each-brew").on("click", function (event) {
$(".each-brew-content").show().animate({ left: "0" }, 1000, function() {
// Get the brew name from the class list.
// This assumes that the brew is the second class in the list, as in your markup.
var brew = event.currentTarget.className.split(/\s+/)[1];
$(".each-brew-content." + brew).animate({ left: "-33.3333%" }, 1000, function() { $(this).hide(); });
});
});
I think an event and observer would do the trick for you.
set up the callback function on completion of your animation to fire an event.
the listener would first listen for any animation event and after that event is triggered listen for the completion event. when the completion event is fired execute the initial animation event.run method (or whatever you would want to call it)
Within the listener
on newanimationeventtriger(new_anim) wait for x seconds (to eliminate infinite loop poss) while if this lastevent triggers done == true{
new_anim.run();
}

Categories