jQuery hover stuck - javascript

When I hover over an img which fades to another img and sroll off too fast, the fadeOut gets stuck and the fade stays. I've tried the .stop() as I've seen in other responses, but still won't work. Is there something else I can put instead of the .stop()?
<div class="grid big-square">
<a href="#"><img id="image2" src="img/fade/creo.png">
<img id="image1" src="img/creo.jpg"></a>
</div>
<script>
$("#image1").mouseenter(function () {
$(this).stop(true, true).fadeOut(1000);
});
$("#image2").mouseleave(function () {
$("#image1").stop(true, true).fadeIn(500);
});
</script>

I seem to remember having a similar problem when I was creating this website.
The solution is to use a combination of .hover() and .stop() to ensure that only one animation is running at a time, which I think you have. Also ensure that the mouseover image is on top of the other image, and just fade that one in and out. The image fading out gets 'stuck' because at some opacity the .mouseleave() stops firing and the .mouseenter() starts firing on the other image.
Something like:
$$ = $("#image1");
$$.hover(function () {
$$.stop().animate({
opacity: 0
}, 1000);
}, function () {
$$.stop().animate({
opacity: 1
}, 1000);
});
#image1 must be above #image2 for this to work, #image1 fades out to 'reveal' #image2 behind it. The code uses .animate() rather than .fadeIn() and .fadeOut() but the effect is the same.
Edit- to fade in another div after the end of the fadeoout animation use the complete call back of the animate function.
Something like:
$$ = $("#image1");
$$.hover(function () {
$$.stop().animate({
opacity: 0
}, 1000);
}, function () {
$$.stop().animate({
opacity: 1
}, 1000, function() {
$("#finalDiv").animate({ opacity: 1, 500 });
});
});
#finalDiv needs to be after the 2 <img />s in your html to appear above them.

I'm not sure how you're trying to accomplish this but I do know how it should be done.
Try this http://jsfiddle.net/xy5dj/
Make sure to listen for both events on the same element (preferably a wrapper element).
Take note that fadeOut actually removes the element from the rendered content (display: none) making sure that the mouse events won't fire on that element.
Side note:
A dirty trick that I used once (if you have to do this then you're doing something wrong) is to clear the style of the element after animation using the callback ability of the animate function i.e.
$('el').animate({opacity:0}, 500, function(){$(this).attr('style', '')});

fiddle
You should use the animation/transition in form:
.fadeTo( duration, opacity, complete )
where complete is callback function.

Related

Fading a <div> With 'onmouseover' and 'onmouseout' Happens Several Times

I have a <div> on my web page that I would like to have an opacity of 1 while you're hovering over it, but when the mouse is not hovering over it I would like it to fade to an opacity of 0.3. My problem is that currently when I hover over the <div> it starts fading in and out several times (rather than just once). I'm not sure if this is why, but I suspect it's because it detects the mouse rolling over the multiple <div>s that are within the one that I set to fade out.
Here is a very simplified segment of my web page to illustrate what I have so far:
<div id="div1">
<div id="div2" onmouseover="fadeElementTo('div1', 500, 1)" onmouseout="fadeElementTo('div1', 500, 0.3)">
<div id="div3">
<div id="div4">
</div>
</div>
<button id="myButton" onclick="doACoolAnimation()" ></button>
</div>
</div>
My fadeElementTo() function is pretty simple:
function fadeElementTo(eid, speed, opacity, callback) {
$("#" + eid).fadeTo(speed, opacity, callback);
}
In case it's relevant, I also have a button that animates the same div by simply moving it left or right when the button is clicked.
function doACoolAnimation() {
var hiddenState = GLOBAL_VAR.hiddenState;
// If the <div> is already hidden, make it visible
if (hiddenState == null || hiddenState == 1) {
GLOBAL_VAR.hiddenState = 0;
$("#div1").animate({
left: "0px"
}, 1500);
}
// Otherwise, hide it
else {
GLOBAL_VAR.hiddenState = 1;
$("#div1").animate({
left: "-800px"
}, 1500);
}
}
Any ideas what might be causing my bug? And better yet, what can I do to fix it?
Try onmouseenter instead of onmouseover and use jQuery to attach/bind those events rather than the attributes so it works the same across all browsers.
$('#outer').mouseenter(function() {
$('#log').append('<div>Handler for .mouseenter() called.</div>');
});
see here
Use mouseenter event to stop event bubbling, and stop method to make sure you clear unfinished animations on that element.
$('#div2').mouseenter(function(){
$('#div1').stop().fadeTo(500,1);
});
It detects the events multiple times. For example, if you want to change the size, going on and off fast changes the size even when the mouse is not on the div. The code needs to exit the program when the mouse is not on the div. To do that, you might include the code in something that kills the code when the mouse is not on top of the div so that the queued fades/animations do not run.
Edit:
Try looking at the JQuery documentation to see if there is anything that you can use.
You might able to use these:

Timed transition between image swaps with JQuery?

I have this code:
$('.pic_windows img').mouseenter(function () {
$(this).effect('shake', {
times : 4,
distance : 5
}, 15).attr('src', $(this).attr('src').replace(/.jpg/, '-1.jpg'))
});
$('.pic_windows img').mouseleave(function () {
$(this).attr('src', $(this).attr('src').replace(/-1.jpg/, '.jpg'))
});
where I'm using JQuery's .attr to swap the images, but I'd like the swapping to occur over the course of around 1 second. I've googled this and get all these complicated "CSS3 transitions with JQuery fallback" tutorials. Is there a way to 'animate' an .attr change?
I think I should do a fadeOut while the other fadeIn but I don't know how to write it, as I'm almost a complete JQuery newbie. I have a number of these transitions to do over the course of several pages. It'd be a cinch if I needed to write this for just one instance.
UPDATE On mouseenter, the image shakes and then should during this shake, fade from one picture to its swapped picture. On mouseleave, the image should just fade back to the original picture. Unfortunately I have also found that the shake effect is breaking on IE, all versions, as well as the image swap (it doesn't see image 2 at all)
No, you cannot animate an attribute change. What you can do is clone an element, change an attribute and transition between them.
var target = $(this).fadeOut();
var src = target.attr('src').replace(/-1.jpg/, '.jpg');
var copy = target.clone()
.attr('src', src)
.hide()
.insertAfter(target)
.fadeIn();
EDIT: Thank you for clarifying your intentions, I would advise not playing with the 'src', which will essentially require building a small stateful plugin. Instead, stick with the desired effect here, reveal an image on hover. jsFiddle
HTML
<div class="shaker">
<img src="http://lorempixel.com/output/nature-q-c-360-240-3.jpg" />
<img class="hover" src="http://lorempixel.com/output/technics-q-c-360-240-9.jpg" />
</div>​
CSS
.shaker {
position: relative;
}
.shaker img {
position: absolute;
}
.hover {
display: none;
}
JS
$('.shaker').hover(function () {
$(this).effect('shake', {
times: 4,
distance: 5
}, 15);
$(this).find('.hover').fadeIn();
}, function () {
$(this).find('.hover').stop().fadeOut();
});​
http://jsfiddle.net/eHQ3t/13/

jquery .animate() - this code sort of does what i want

I am trying to make a div slide down when the mouse moves over another div just above it. Basically the div above it is just the trigger that makes the div slide down. Mouseover of .trigger makes .slidedown expand, and mouseout of .slidedown makes itself slide back up. Here's the code i have so far:
$(document).ready(function() {
$('.slidedown').hide();
//When mouse rolls over
$('.trigger').mouseover(function(){
$('.slidedown').stop().animate({
height: ['toggle', 'swing'],
}, 600, function() {
// Animation complete.
});
});
//When mouse is removed
$('.slidedown').mouseout(function(){
$('.slidedown').stop().animate({
height:'0px'
}, 600, function() {
// Animation complete.
});
});
});
This works, but there are just two teaks i need help with. Firstly, after mouseout and the .slidedown div slides up and disappears, if i then mouse over the .trigger div again, nothing happens. It should make the .slidedown move down again. I need it to every time keep working. I tried removing the .stop() but it still doesn't work.
Also can i make it also slide back up if the mouse moves out of .trigger but only if it isn't moving out of .trigger into .slidedown? This is so incase the user doesn't move the mouse into .slidedown, it would remain forever which isn't good. Or just have a time limit that it can remain expanded if the mouse doesn't move over .slidedown.
Second, is there a way to make a delay of around 1 second between mouseout and the div sliding back up? Thanks for your help!
You might try using the jQuery hover event. For the delay, you can put the closing animation in setTimeout:
$(document).ready( function(){
$('.trigger').hover( function(){ // enter animation
$('.slidedown').stop(true,true).animate({
height: ['toggle', 'swing'],
}, 600, function() { /* animation done */ });
}, function(){ // leave animation
setTimeout( function(){
$('.slidedown').stop(true,true).animate({
height: '0px',
}, 600, function() { /* animation done */ });
}, 1000 );
});
});
You might also look into the hoverIntent plug-in for more nuanced control over the mouseenter/mouseleave behavior, including timing.
I think you'll find that setting a numerical height in $('.trigger').mouseover() may help the animation be repeatable. FYI, you can set an integer number for something like height or width in jQuery and it will automatically set the unit to px for you.
As Ken pointed out, setTimeout is useful for a delay in code, but keep it in your $('.slidedown').mouseout() event or the slideown div will hide after you mouseout of the trigger div instead of when you leave the slidedown div as you specified.

Looped jQuery slideshow with smooth cross-fades

I'm trying to do a simple rotating image on the home page. Under the hood I'm reading a directory and then populating urls for the images into an array. What I want to do is cross-fade the images. If it was just a matter of showing the next one, it's easy, but since I need to cross-fade, it's a bit harder. I think what I want to do is do the fades by calling animate() on the opacity value of the <img> tag, and in between swapping out the css background-image property of the enclosing <div>. But the results are not that great.
I've used tools for more full featured slideshows, but I don't want the overhead of adding a plugin if I can avoid it, and a simple crossfade seems like it should be easier.
Here's my JavaScript (I'm using jQuery 1.3.2):
var slideshow_images = ["http:\/\/example.com\/wordpress\/wp-content\/themes\/testtheme\/sidebar-home-bg\/bg1.jpg","http:\/\/example.com\/wordpress\/wp-content\/themes\/testtheme\/sidebar-home-bg\/bg2.jpg","http:\/\/example.com\/wordpress\/wp-content\/themes\/testtheme\/sidebar-home-bg\/bg3.jpg"];
var slideshow_index = 0;
var delay = 4000;
var swapSlides = function() {
var slideshow_count = slideshow_images.length;
// initialize the background to be the current image
$('#home-slideshow').css({
'background-image': 'url(' + slideshow_images[slideshow_index] + ')',
'background-repeat:': 'no-repeat',
'width': 200,
'overflow': 'hidden'
});
slideshow_index = ((slideshow_index + 1) == slideshow_count) ? 0 : slideshow_index + 1;
// fade out the img
$('#home-slideshow img').animate({opacity: 0}, delay);
// now, the background is visible
// next change the url on the img
$('#home-slideshow img').attr('src', slideshow_images[slideshow_index]);
// and fade it up
$('#home-slideshow img').animate({opacity: 1.0}, delay);
// do it again
setTimeout('swapSlides()', 4000);
}
jQuery(document).ready(function(){
if (swapSlides) {
swapSlides();
}
});
And here's the markup I'm using:
<div id="home-slideshow"><img src="http://example.com/wordpress/wp-content/themes/testtheme/sidebar-home-bg/bg1.jpg" alt="" /></div>
The first thing that you should be aware of and that must be causing problems with your code : the animate methods are not synchronous ! So when you do :
$('#home-slideshow img').animate({opacity: 0}, delay);
// now, the background is visible
// next change the url on the img
$('#home-slideshow img').attr('src', slideshow_images[slideshow_index]);
You start to animate, but the method immediately returns. You can imagine the animation as a background thread , although there is no such thing as a thread in JavaScript and everything is implemented using settimeout calls.
So in your code, at the moment you change the src attribute, the image is probably still 99% visible. And then you start to animate it back to 100% opacity, but at this point it is still at say 98%, and the two "threads" will try to simultaneously make it appear/disappear !
So in your code will need to either set timeouts to execute the tasks in the correct order (always leaving a few milliseconds of margin inbetween), or, safer but maybe less readable when you have many successive function calls, use the callback function of the animate method. For example :
$('#home-slideshow img').animate({opacity: 0}, delay, function(){
// now, the background is visible
// next change the url on the img
$('#home-slideshow img').attr('src', slideshow_images[slideshow_index]);
// and fade it up
$('#home-slideshow img').animate({opacity: 1.0}, delay, function(){
// do it again
setTimeout('swapSlides()', 4000);
});
});
Finally, what you are doing is a fade-out + fade in. If you want a real cross fade you'll need to have 2 element simultaneously at some point :
start : there is only one element, with opacity 100%
build your new element with the right url for the background image (or use an img element)
add the new element to the dom tree with opacity 0%, as a sibling to the existing one
start to animate simultaneously the opacity of the current element from 100% to 0% and the opacity of the new element from 0% to 100%
remove the old, now invisible element
try this:
DEMO: http://jsbin.com/ipudo/7
few line of jQuery
$(function(){
$('#home-slideshow img:gt(0)').hide();
setInterval(function(){
$('#home-slideshow :first-child').fadeOut()
.next('img').fadeIn()
.end().appendTo('#home-slideshow');},
3000);
});
2 line of CSS
#home-slideshow { position:relative; height:332px; width:500px; }
#home-slideshow img { position:absolute; left:0; top:0; }​
your HTML
<div id="home-slideshow">
<img src="image.jpg" alt=""/>
<img src="image.jpg" alt=""/>
<img src="image.jpg" alt=""/>
...
...
</div>

jQuery - Fading animation on hover

I have a little jQuery animation which fades in a link when hovering an :
$(function() {
$('.delete').hide();
$('#photos img').hover(function() {
$(this).parents('li').children('.delete').fadeIn('fast');
}, function() {
$(this).parents('li').children('.delete').fadeOut('fast');
});
});
But if I quickly move my mouse in and out of the image, the new animation is always added to the queue and when I stop I can see the link pulsating for a while. I tried using .stop(true), but then sometimes the fade in effect doesn't work at all (or just up to some opacity value less than 1). What can I do?
Thanks, Eric
The best way is to use hoverIntent plugin. This deals with the issues above. It also adds a slight delay to the animation so if a user happens to quickly move the mouse over all the links you do not get an ugly animation flow of all the links.
One way to prevent such problems occuring is to use stop() in conjunction with fadeTo(), as in the snippet below:
$(function() {
$('.delete').fadeTo(0, 0);
$('#photos img').hover(function() {
$(this).parents('li').children('.delete').stop().fadeTo('fast', 1);
}, function() {
$(this).parents('li').children('.delete').stop().fadeTo('fast', 0);
});
});
Hope this solves your issue!

Categories