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

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:

Related

Mouse movement blocks 'transitionend'

Introduction
I'm using Semantic-UI's sidebar functionality, which gives you a button that triggers a sidebar that pushes the content from the left (in this case).
I want to unfold that same sidebar by hovering with the mouse on the left side. I realize there are several ways to do it (as these often do. Maybe just checking the X position of the mouse would work but that's beside the point); I chose to create a transparent div on the left side and make its :hover pseudo-class to trigger the sidebar:
// create sidebar and attach to menu open
$('.ui.sidebar').sidebar('attach events', '.toc.item');
// hover transparent div to trigger the sidebar too:
$('.sidebar-trigger').hover(function() {
$('.ui.sidebar').sidebar('show')
});
// hide() and show() the sidebar accordingly to use the sidebar:
$('.ui.sidebar').sidebar('setting', {
onShow: function() {
$('.sidebar-trigger').hide();
},
onHidden: function() {
$('.sidebar-trigger').show();
}
});
Problem
Now, it all works except for one occasion: when you don't stop moving the mouse as the sidebar opens. I've looked at $(document).on('transitionend', function(event) { ... } and that mouse effectively prevents the transition to finish.
Resources
I've put a blue background on my .sidebar-trigger and made a small video/gif so as to be clearer.
I moved the mouse like a crazy creature but with natural gestures the problem occurs as well.
I'm using Semantic-UI's guide on this thing: http://semantic-ui.com/modules/sidebar.html#/settings (I've also tried onVisible and onHide with no luck)
This is a OSX Yosemite 10.10.3 running Chrome 45.0.2454.101 (64-bit)
jsfiddle with the problem at hand
PS: It seems it might be an OSX Chrome bug?
I would try using one and mouseover:
$('.sidebar-trigger').one('mouseover', function() {
$('.ui.sidebar').sidebar('show')
});
Then, when it has finished animating, reattach the event:
$(document).on('transitionend', function(event) {
$('.sidebar-trigger').one('mouseover', function() {
$('.ui.sidebar').sidebar('show')
});
});
I think what is happening is that the hover event is getting called multiple times - every time the element is hovered, then goes over a child element, and then goes back over the hover element, and things are getting mixed up at some point. So you need to only call show if it's not already shown.
Here is a working example: Fiddle
I believe when the element was hovered, it was adding a classes 'uncover' and 'visible', and another called 'animating' which wouldn't fire until the mouse stopped moving. I changed the jQuery slightly to only add classes 'uncover' and 'visible', and it still animated okay. However, the body was pushing right too far by 175px, so I had to edit the class that was causing that (noted below) from 260px to 85px. This DOES get the menu acting properly though from my understanding.
$('.sidebar-trigger').mouseenter(function() {
$('.ui.sidebar').addClass('uncover, visible');
$('body').addClass('mleft175');
});
$('body').click(function() {
$('.ui.sidebar').removeClass('uncover, visible');
$('body').removeClass('mleft175');
});
and then add overriding class
.ui.visible.left.sidebar ~ .pusher
{
-webkit-transform: translate3d(85px, 0, 0);
transform: translate3d(85px, 0, 0);
}
Right now it is set to hide the menu when the body is clicked. Alternatively you can hide it when the mouse leaves the sidebar menu:
$('.ui.sidebar').mouseleave(function(){
$(this).removeClass('uncover, visible')
});
Ok, my first answer was (of course) way too much work for what it really needed. The onVisible seems to work perfectly. Was that not working for you? Demo HERE
Simply change 'onShow' to 'onVisible' in your sidebar setting:
$('.ui.sidebar').sidebar('setting', {
onVisible: function() {
$('.sidebar-trigger').hide();
},
onHidden: function() {
$('.sidebar-trigger').show();
}
});
As shown on the Semantic UI site, the onVisible fires when the animating starts. The onShow fires when the animating finishes. So what you were doing was hiding that blue / transparent bar when the animation was finally done (the .animating class noted in my previous answer), as opposed to when it starts. If you need further explanation please let me know.

Detecting .scroll on div with jQuery

EDIT: looks like I was approaching this from the wrong direction, will see if I can close this. Future reading:
Get mouse wheel events in jQuery?
I'm trying to create a scrollable <div> element (on a horizontal plane); not there with the maths yet but I'm having trouble with something more basic - the scroll event doesn't seem to be registering. Am I missing anything obvious?
I've taken out all the CSS associated with the <div> barring what you see in the samples below:
<div id="about-carousel" carousel-offset="0" style="height:20rem; background-color:red;">
</div>
$(document).ready(function() {
handleCarousels(['#about-carousel']);
});
function handleCarousels(idArray) {
for(var n in idArray) {
var target = idArray[n];
// this works
$(target).click(function() {
console.log('clicked');
});
// this doesn't
$(target).scroll(function(e) {
e.stopPropagation();
console.log('scrolls');
});
}
}
According to this answer the element needs to have overflow: scroll set, but that makes no difference. Even if I fill the <div> with images, it doesn't trigger the .scroll event at all.
Any ideas?
UPDATE BEFORE POSTING: the 'scrolls' message is being output to console if I set the div to overflow: scroll and fill it with images, but only when I drag the scroll bar. I thought it was meant to capture mouse events too?
I'm using jQuery 1.11.1.

jQuery hover stuck

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.

Don't fire onmouseout when mouse moves to something overlaying the element

I have an iframe #viewer and an absolutely positioned element #appear_above_viewer that appears above it. I want #appear_above_viewer to fade in when the mouse goes over #viewer, and fade out when the mouse leaves.
So far I have this code:
$("#viewer").hover(
function(){ $("#appear_above_viewer").animate({ opacity: 1 }, 'slow'); },
function(){ $("#appear_above_viewer").animate({ opacity: 0 }, 'slow'); }
);
It seems to work, until you hover your mouse over #appear_above_viewer, and it conveniently disappears. I presume this is because an absolutely positioned element is considered something different to the iframe, and it's position on the screen makes no difference.
I want #appear_above_viewer to only disappear when the mouse leaves #viewer, and anything above it entirely. Is this possible?
(I've read other questions about this but none of them seem to work for my situation)
Still not positive I know exactly what behavior is expected, but you likely just need to apply the pointer-events attribute in css set to none on your appear_above_viewer.
Here is a jsFiddle demonstrating something similar to what I think you want.
EDIT
You can use this question for a cross-browser solution:
Click through a DIV to underlying elements
You can try this.
onmouseout =function(e){
if ( e && e.preventDefault )
e.preventDefault();
e.stopPropagation();
else
window.event.cancelBubble = true;
window.event.returnValue = false;
return false;
}

Div is jumpy with fadeIn jQuery

When I roll over .comptext_rollover div it should hide the initial div on the page and show the minipage div. but it does but is sometimes really jumpy and also the minipage div sometimes shows below the initialpage div. any ideas? sorry i am new to coding! Thanks in advance.
$(document).ready(function() {
$('#mini_page').hide();
$('.comptext_rollover').hover(function() {
$('#initial_page').hide();
$('.register_button').hide();
$('#mini_page').fadeIn(100);
$('#container').css({
'margin-top': '-217px'
});
}, function() {
$('#mini_page').hide();
$('#initial_page').show();
$('.register_button').show();
$('#container').css({
'margin-top': '-150px'
});
});
});
I prepared a fiddle demo HERE
re-EDIT:
JSFIDDLE DEMO
(the demo may be incorrect while the main CSS is an external link)
I used:
<div id="container">
<div id="initial_page" class="page">
<div id="playvideo_hoverbutton"></div>
<div class="register_button"></div>
<div id="invisible_register2"></div>
<div id="termsandconditionsapplyshort"></div>
</div>
<div id="mini_page" class="page">
<div id="minicar_animated"></div>
<div id="worth25k"></div>
<div class="register_button"></div>
<div id="invisible_register"></div>
</div>
<!-- THE ROLLOVER IS OUT OF ALL 'PAGES'! -->
<div class="comptext_rollover">
<!--<div id="competition_text"></div>-->
</div>
</div>
$('#mini_page').hide();
$('.comptext_rollover').mouseenter(function() {
$('.page').fadeToggle(400);
});
$('.comptext_rollover').mouseleave(function() {
$('.page').fadeToggle(400);
});
In any case what you should do:
Position absolute the 2 screens you need to 'swap' into a container.
Than what you do:
Position the 'rollover' element outside the 'screens'.
Adjust the marginTop of the bigger image(car image) in the CSS (like I did) to fix the buggy 'jumps'.
IF POSSIBLE: ONLY ONE rollover ACTION ELEMENT!
Fix the margin-top of the car image. (give it a -Npx)
Doing so you don't need to do that stuff with positioning your container -Npx
There is also a simpler way to do the same effect:
you add to BOTH screens a class .swappable, making the second one (CSS)display:none; , and than you just use jQuery toggling just this class.
you've not set a great deal of time for the fade in. you're also just hiding some of the divs which makes the fade in move around depending on where you put them. maybe use slides instead. I have saved an example here: http://jsfiddle.net/kBEUH/
$(document).ready(function(){
$('#mini_page').hide();
$('.comptext_rollover').hover(function () {
$('#initial_page').fadeOut(1000);
$('.register_button').fadeOut(1000);
$('#mini_page').slideDown(1000);
}, function(){
$('#mini_page').slideUp(1000);
$('#initial_page').fadeIn(1000);
$('.register_button').fadeIn(1000);
});
});
if you put a console.log in your hover() function, you'll see hover is firing like crazy. This causes the animation to start over and over again, while moving your mouse.
You could take advantage of the jquery :animated selector:
$('.comptext_rollover').hover(function() {
//enable this line to see the hover event is firing every time your mouse moves
//console.log("hovering")
//if the div is in the middle of an animation, do nothing
if (!$("#mini_page").is(":animated")) {
$('#initial_page').hide();
$('.register_button').hide();
$('#mini_page').fadeIn(100);
$('#container').css({
'margin-top': '-217px'
});
}
}, function() {
//etc
});
EDIT:
Now I think of it, your probably want to use .mouseenter() and .mouseleave() instead of hover()
$('.comptext_rollover').mouseenter(function() {
//your code
}).mouseleave(function() {
//your code
});

Categories