开发者

jQuery events .live() wierdness

开发者 https://www.devze.com 2023-02-06 10:53 出处:网络
I have a page with a toolbar menu at the bottom.I have a function which checks the display property of a block that contains the menu items and sets it to \"none\" if it\'s \"block\" or sets it to \"b

I have a page with a toolbar menu at the bottom. I have a function which checks the display property of a block that contains the menu items and sets it to "none" if it's "block" or sets it to "block" if it's "none".

I'm using jQuery to bind the event to the object. I want to use the live() method because I may dynamically add items to this toolbar and I want the event to automatically be attached to new menu elements.

The problem that I'm experiencing is that when I bind the event to the element with live(), the CSS display property of the element I'm checking is always "none". So, the menu never closes.

If I use bind() instead of live(), everything works开发者_开发技巧 like I expect it to.

What's causing this strange behavior with live()?

The demo page reproducing the problem is http://www.ghodmode.com/tbdemo

Thank you.

-- Ghodmode


Because callbacks that are bound using .live() are executed through event delegation, any handlers between the target of .live() and the document will be called. Looking at your code can see that self.hide_menu is bound to the body element. When the event bubbles up from your target that has the class .j_has_menu, the click handler on body (self.hide_menu) is executed causing the menu to close. self.hide_menu does not return false, so the event continuse bubbling up until it reaches the document root and calls the function that you expected self.show_menu. This means that when the menu is open and you click it, self.hide_menu is run first and then self.show_menu is run right after so that the menu is perpetually open.

$(document).ready(function () {
    var self = new Toolbar();
    $(".j_has_submenu").live("mouseover", self.show_submenu);
    $(".j_has_submenu .j_submenu").live("mouseout", self.delay_hide);
    $(".j_has_menu").live("click", self.show_menu);
    $('.j_toolbar').siblings().add('body').click(self.hide_menu); // <-- the culprit
});


If you're saying that a handler attached via .live() never fires, this usually happens if you have some other handler between the target of .live() and the document that does a return false; or event.stopPropagation().

The reason is that .live() relies on the event bubbling up to the document in order to invoke the handler. Anything that prevents bubbling, kills .live().

<document> <!-- gets a $('p > span').live( 'click', func ) -->
<html>
   <body>
      <div id="someElem">  <!-- bind click handler that does "return false;" -->
         <p>
             <span>Hi there!</span> <!-- Intended target of the .live() click 
                                             handler won't work because one of 
                                             its ancestors has a click with  
                                             "return false" -->
         </p>
      </div>
   </body>
</html> 


I suggest using delegate instead of live and toggle for showing/hiding the elements.

The advantage of delegate is that you can specify the root element which handles a group of events (in case of livethe root is always the document, which can be very inefficent). [Working demo]

$(document).ready(function () {
    var self = new Toolbar();
    $(".j_toolbar")
      .delegate(".j_has_submenu", "mouseover", self.show_submenu)
      .delegate(".j_has_submenu .j_submenu", "mouseout", self.delay_hide)
      .delegate(".j_has_menu", "click", self.show_menu);
    $("body").click(self.hide_menu);
});

Note: You need 1.4.2 for delegate

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号