I am having the following problem under Internet Explorer 7/8:
I have a popup that gets activated when user mouseover a link. The popup is a simple <div>
that contains some data. Inside this <div>
tag there is a <select>
tag with some <option>
s. I have attached mouseover/mouseout events to the <div
>, so that this popup will stay open while cursor is over it. The problem comes when you click on the <select>
and then move the cursor over any of the <option>
s. This triggers the mouseout event of the <div>
tag and respectively closes it.
How can I prevent the closing of the popup in IE ?
I am having the following problem under Internet Explorer 7/8:
I have a popup that gets activated when user mouseover a link. The popup is a simple <div>
that contains some data. Inside this <div>
tag there is a <select>
tag with some <option>
s. I have attached mouseover/mouseout events to the <div
>, so that this popup will stay open while cursor is over it. The problem comes when you click on the <select>
and then move the cursor over any of the <option>
s. This triggers the mouseout event of the <div>
tag and respectively closes it.
How can I prevent the closing of the popup in IE ?
Share Improve this question edited Apr 23, 2022 at 11:08 Brian Tompsett - 汤莱恩 5,88372 gold badges61 silver badges133 bronze badges asked Aug 6, 2009 at 14:59 dalizarddalizard 4711 gold badge6 silver badges15 bronze badges13 Answers
Reset to default 9 +50You should be able to detect if the situation is the one you want just with the values off the event. It is a little convoluted but it seems to work.
In the event handler of your outer div
, do something like this:
<div onmouseover="if (isReal()) { toggle(); }"
onmouseout="if (isReal()) { toggle(); }">
</div>
Then implement the isReal
method:
function isReal() {
var evt = window.event;
if (!evt) {
return true;
}
var el;
if (evt.type === "mouseout") {
el = evt.toElement;
} else if (evt.type === "mouseover") {
el = evt.fromElement;
}
if (!el) {
return false;
}
while (el) {
if (el === evt.srcElement) {
return false;
}
el = el.parentNode;
}
return true;
}
Basically the isReal
method just detects if the event was coming from within the div. If so, then it returns false which avoids calling the hide toggle.
My suggestion would be to set another flag while the select box has focus. Do not close the div while the flag is set.
How about re-showing the div when the mouse is over the <options>
s through mouseover
events of <options>
s.
Edit: execution order of mouseover of option and mouseout of div might cause problems though.
In the mouseout event for the div add a timeout to the div element that will hide the div in 200 milliseconds or so.
Then in the mouseover event for the div/select and the click event of the select clear the timeout stored in the div element.
This gives a very slight delay before hiding the div that allows the mouseover or click events to clear the timeout before it is executed. It's not pretty but it should work.
instead of using mouseout as the event to close the div, use mouseleave, then the event will only be triggered when the pointer leaves the boundary of the div, not when it moves onto other elements within it
you could try adding another mouseover event specifically for the options list.
Well, the reason for this behavior is because the mouseover/out events bubble, which effectively means that whenever you mouseover any of the elements inside the popup, the popup receives the event also.
You can read more here about these events, and here about event bubbling.
You have 3 possible solutions here:
Change the events to onmouseenter/leave. You've mentioned that this didn't help, which just sounds plain odd, since these aren't supposed to bubble.
Check srcElement in relation to from/toElement in the event.
An improved version of McKAMEY's check would be:
function isReal() {
var evt = window.event;
if (!evt) {
return true;
}
var el;
if (evt.type === "mouseout") {
el = evt.toElement;
} else if (evt.type === "mouseover") {
el = evt.fromElement;
}
if (!el) {
return false;
}
// this will also return true if el == evt.srcElement
return evt.srcElement.contains(el);
}
Does the same thing, just shorter.
3 . Another option would be to create a transparent, invisible div just under your popup that covers the area that the select box drops down into. I'm assuming that it's dropping outside the actual area of the popup.
Hope this helps!
have you tried hover
instead of mouseover/out effects?
$(".myDiv").hover(function(){
$(this).show();
}, function {
$(this).hide();
});
What about something like this:
<div id="trigger">
Hover over me!
</div>
<div class="container">
<select>
<option>Blah</option>
<option>Blah</option>
</select>
</div>
$("#trigger").mouseover(function(){
$('.container).show();
});
$(".container").mouseleave(function(){
$(this).hide();
});
The basic idea is that you show the container element when you hover over the trigger then when you leave the container you hide the container. You'd need to position the container so it clipped the trigger element, otherwise it would hide straight away.
Why have mouseover / mouseout on the <div>
? Why not just show the <div>
on the mouse over, then set <body onmouseover="hidedivs();">
I don't know if this would work, but if the <div>
is on top of the body, then the <div>
should stay visible.
Many people posting solutions/examples do not seem to realize one thing: onmouseout event on <div>
fires before onmouseover event on <select>
.
When <div>
loses focus (onmouseout) do not close it immediately, but after say, 500 milliseconds. If during this time <select>
gets focus (mouseover) do not close <div>
at all (clearTimeout).
Also, try to play with event propagation/bubling.
Given that selects in IE are a pain, especially when it comes to the whole layering issue where a select appears above a div even though it shouldn't, can I point you in the direction of YUI's Menu button controls. They look really nice, are easy to implement and won't cause this issue
Here is a link: http://developer.yahoo.com/yui/examples/button/btn_example07.html
You should use event.stopPropagation()
while in <select>
, or cancelBubble()
in <select>
element itself.