views:

1288

answers:

15

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 ?

+2  A: 

My suggestion would be to set another flag while the select box has focus. Do not close the div while the flag is set.

apathetic
I've tried this already and it doesn't work because I need use the jQuery live() function, and it doesn't support the focus event.
dalizard
A: 

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.

palindrom
IE refuses to attach eventlisteners to the <options>s. Works in Gecko/WebKit browsers, not in IE.
dalizard
I believe the problem comes from the fact that IE renders <select> tags like ActiveX elements on the top of every other element in the DOM.
dalizard
@dalizard: that's not true as of IE7, the select element is a windowless control and supports the z-index property. However, the options popup behaves as though it's not part of the DOM (even though it is) and therefore doesn't support DOM events.
Andy E
A: 

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.

David G
That's the only thing I could think of. It is set like this at the moment. Too bad I can't find anything better.
dalizard
+6  A: 

You 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.

McKAMEY
This is essentially what I came here to post. This is similar to how mootools implements their `mouseover` and `mouseout` events, but much more succint. Probably the best solution.
tj111
A: 

Try the jQuery selectbox replacement ... works great in IE w/ the behavior you want ...

http://www.brainfault.com/jquery-plugins/jquery-selectbox-replacement/

It uses a timeout if Im not mistaken ...

jonbaer
A: 

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

danwellman
Unfortunatelly, it doesn't work. Still closes the element.
dalizard
A: 

you could try adding another mouseover event specifically for the options list.

codedude
You can't add any event for the options list that would get triggered under IE.
dalizard
A: 

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:

  1. 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.

  2. 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!

SEK
A: 

have you tried hover instead of mouseover/out effects?

$(".myDiv").hover(function(){
    $(this).show();
}, function {
    $(this).hide();
});
Jason
Yes. Still doesn't work :-) That was actually how I had it originally.
dalizard
A: 

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.

Tom
A: 

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.

andrewWinn
A: 

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.

presario
A: 

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%5Fexample07.html

Zoidberg
A: 

You should use event.stopPropagation() while in <select>, or cancelBubble() in <select> element itself.

Thevs
A: 

Thanks! it worked :)... brilliantly McKAMEY :)

gsygfdsgfdsgfdsgfds