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

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;
}

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.

Drag Leave and Drag Enter

When I drag a file over to my window I wish to show an overlay, and when the file is dragged off the window I wish to remove the overlay.
$(window).on('dragleave', this.onDragLeave);
$(window).on('dragenter', this.onDragEnter);
p.onDragEnter = function(e) {
console.log('ENTER');
};
p.onDragLeave = function(e) {
console.log('LEAVE');
};
The above works fine, when I enter and leave the window it logs correctly.
The problem starts when I start fading in and out my overlay:
p.onDragEnter = function(e) {
console.log('ENTER');
$('#drag-overlay').fadeIn();
};
p.onDragLeave = function(e) {
console.log('LEAVE');
$('#drag-overlay').fadeOut();
};
With the above, it just fades in and out again and again. I'm not sure whats going on, it's as if when the overlay fades in it fires a drag leave, i'm not sure why?
The overlay is just an absolute div, width and height 100%.
The problem is that by showing an overlay, you are causing the dragged item to leave the parent and drag into the overlay. Then hiding the overlay causes drag to trigger in the parent.
Fortunately, the solution is simple and can be done in css:
#drag-overlay
{
pointer-events: none;
...
}
See this jsfiddle for a working solution.
If you remove pointer-events:none you get the same behaviour. pointer-events:none just means that the parent ondragleave method isn't fired when dragging over the overlay.

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:

Javascript/jQuery scrollTop issue

I've re-created a simple version of what I'm trying to do here (jsFiddle)
The header should stay where it is, and as you scroll down, when you click the header div it should scroll back up to the top, which it does. But if you focus on the input, or click the "logo", the scroll should stay where it is.
With the first method I've tried is by using jQuery's .css and setting the input/logo's z-index as higher than the header, then getting the current scroll and keeping it at that position.
This sort of works, but once you click the input or logo, the header scroll no longer works.
I've also tried changing the logo/input jQuery to .animate with a slow speed, and it stays static for a couple seconds and then scrolls to the top even though I've not set it to do so. Here is the second example - jsFiddle
Doing it with the second example however doesn't stop the other function from working.
Is there any reason for this behaviour that I'm missing?
You can prevent the click event from propagating to the header.
$("#logo, #input").click(function(e) {
e.stopPropagation();
});
Check out this interesting article about event order, all you have to do is stop propagation. Here your modified Fiddle
$("#logo, #input").click(function(e) {
e.stopPropagation();
var y = window.scrollY;
$('html').animate({
scrollTop: y
}, 'slow');
$('body').animate({
scrollTop: y
}, 'slow');
});
All you need to do is stop the propegation of the event. To do this you return false from your click function.
$("#logo, #input").click(function() {
return false; // Add this line
});
Here is your fiddle updated: http://jsfiddle.net/BRnvT/

prevent window for scrolling after div box scrolling

I have a small div box that has a vertical scroll bar and sits within an html page that also has a vertical scroll bar.
My problem is when the user reaches the end of the small DIV box scrolling, the ENTIRE html page that contains the div box then begins to scroll (assuming the user is scrolling via the mouse scroll and NOT by actually clicking the DIV box scroll buttons themselves)
is there a way to prevent the entire html page from scrolling once a user reaches in end of my small DIV box scroll? Any help would be much appreciated! Thank you!
I have tried this (but it cancels scrolling for even the div box):
if (window.addEventListener)
/** DOMMouseScroll is for mozilla. */
window.addEventListener('DOMMouseScroll', handleWheelEvent, false);
/** IE/Opera. */
window.onmousewheel = document.onmousewheel = handleWheelEvent;
function handleWheelEvent(e){
e.preventDefault();
}
I didn't look too much into your code and the problem, but I wanted to throw out a suggestion before I move on :P.
window.addEventListener
and
document.onmousewheel = handleWheelEvent;
are normally good ways to apply what you want to do the ENTIRE document, whereas if you want to apply a specific value (in this case scroll = false) to a specific element, then you need to set the reference to that specific reference (i.e. getElementById() and then it applies only to the element of the document).
Idk - maybe that helps, maybe it doesn't :P good luck.
-J
You would need to modify the handleWheelEvent function and check the srcElement property of the e event and call preventDefault() when it's not scrolling the DIV box. Here's a link with some code examples:
http://www.webdeveloper.com/forum/archive/index.php/t-158824.html
I had a similar problem. Google led me here. Over 1700 views, in 4 years, of an incomplete answer. I figured once I had coded a solution, I'd pop it in a JSFiddle and share it. Better late than never.
Tested on MacOSX / Chrome.
http://jsfiddle.net/mF8Pr/
My problem involved being able to scroll inside a textarea, within a lightbox, and disabling scrolling on the rest of the page beneath the overlay.
bind mouse wheel event to document
when event fires (optional: test to make sure overlay is visible)
check target is obj we want to have scrolling enabled
make sure 0 < obj.scrollTop < (obj.scrollHeight - obj.clientHeight)
check direction of attempted scroll event.originalEvent.deltaY
UP == negative
DOWN == positive
event.preventDefault()
$(document).bind('mousewheel', function(e){
//if($overlay.is(':visible'))
{
if(e.target != null && e.target.type != 'textarea')
{
e.preventDefault();
}
else
{
if(e.originalEvent.deltaY < 0 && e.target.scrollTop == 0)
{
e.preventDefault(); // already at top
}
else if(e.originalEvent.deltaY > 0 && e.target.scrollTop >=
(e.target.scrollHeight - e.target.clientHeight))
{
// must use greater than because sometimes
// the math is wrong by 1px
e.preventDefault(); // already at bottom
}
}
}
});
-Amanda

Categories