views:

67

answers:

1

I have a popup with drop down menus on it. I've scaled it down and simplified it for test purposes, but it still doesn't work the way I want/it should.

<!DOCTYPE html>
<html>
<head>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"&gt;&lt;/script&gt;

  <script type="text/javascript">
  jQuery(document).ready(function(){    
    jQuery('.trigger').click(function(){
      var picker = jQuery('.popup');
      jQuery('<div></div>').css({
        height: screen.height, 
        width: screen.width, 
        position: 'absolute',
        'z-index': -1,
        top: picker.offset().top*-1, 
        left: picker.offset().left*-1,
        border: '1px solid red'
      }).click(function(){
         picker.trigger('focusout');
         jQuery(this).hide();
      }).prependTo(picker); 
      picker.css('visibility', 'visible');
    });
    jQuery('.popup').live("focusout", function() {
      jQuery('.popup').fadeTo(500, 0.0, function() {
        jQuery('.popup').css('visibility', 'hidden');
        jQuery('.popup').css('opacity', '1.0');
      });
    });
  });  
  </script>
</head>
<body>
  <p>
    <input type=text class=trigger />
    <div id=popup-div class=popup style="visibility: hidden; border: 1px solid red">        
        <select>
        <option>option1</option>
        </select>
        <p>Popup text</p>       
    </div>
  </p>
</body>

When you click on the input field, a 'popup' appears, if you click outside the red border it fades away. If you click on the select option it shouldn't dissappear! However on this point, Chrome doesn't work the same as IE/FF/Opera/Safari, and makes the div dissappear.

(Using Chrome 4.0.295.0)

Does anybody knows a work-around for Chrome?
Calling event.stopPropagation() on select elements did not work so far

A: 

This seems to behave correctly in Chrome 5.0.375.23, however I'd change this up a bit to have consistent behavior in all browsers including Chrome 4, since focusout isn't necessarily a valid event on an element that can't have focus in the first place. A better approach here is to take advantage of bubbling and event order. To do this, you'd replace this:

jQuery('.popup').live("focusout", function() {
  jQuery('.popup').fadeTo(500, 0.0, function() {
    jQuery('.popup').css('visibility', 'hidden');
    jQuery('.popup').css('opacity', '1.0');
  });
});

With this:

jQuery('.popup, .trigger').live('click', function(e) {
  e.stopImmediatePropagation()
});
jQuery(document).click(function() {
  jQuery('.popup:visible').fadeTo(500, 0.0, function() {
    jQuery(this).css('visibility', 'hidden').css('opacity', '1.0');
  });
});

What this does is if the click originated inside a popup element or a trigger (opening it), the hide action isn't executed, because the execution of handlers of this event on the same element (document) is prevented (as is the bubble, but that doesn't matter in the above code). Even though .live() lives on the document, with event.stopImmediatePropagation() you can prevent handlers at the same level from executing if they were bound later, since handlers are executed in the order they were bound.

As an aside on .stopPropgation(): If you change this to just event.stopPropagation(), the other handler still executes, hiding the popup (though you could use event.stopProgation() and check event.isPropogationStopped() in the second handler).

Nick Craver