2011-01-25 2 views
0

У меня есть страница с меню панели инструментов внизу. У меня есть функция, которая проверяет свойство отображения блока, который содержит элементы меню, и устанавливает его в «none», если он «блокирует» или устанавливает его «блокировать», если «нет».jQuery events .live() wierdness

Я использую jQuery для привязки события к объекту. Я хочу использовать метод live(), потому что я могу динамически добавлять элементы на эту панель инструментов, и я хочу, чтобы событие автоматически привязывалось к новым элементам меню.

Проблема, с которой я столкнулся, заключается в том, что когда я привязываю событие к элементу с помощью live(), свойство отображения CSS элемента, который я проверяю, всегда «нет». Таким образом, меню никогда не закрывается.

Если я использую bind() вместо live(), все работает так, как я ожидаю.

Что вызывает это странное поведение с помощью live()?

Демонстрационная страница воспроизведения проблемы является http://www.ghodmode.com/tbdemo

Спасибо.

- Ghodmode

+0

Ваше демо работает отлично для меня ... – kapa

ответ

0

Поскольку обратные вызовы, которые связаны с использованием .live() выполняются посредством делегирования событий, любые обработчики между мишенью .live(), и документ будет называться. Глядя на ваш код, можно увидеть, что self.hide_menu привязан к элементу body. Когда событие пузырится от вашей цели, у которой есть класс .j_has_menu, выполняется обработчик щелчка по телу (self.hide_menu), заставляя меню закрываться. self.hide_menu не возвращает false, поэтому событие продолжается до тех пор, пока оно не достигнет корня документа и вызовет функцию, которую вы ожидали self.show_menu. Это означает, что когда меню открыто и вы нажимаете его, сначала запускается self.hide_menu, а затем self.show_menu запускается сразу после того, как меню постоянно открывается.

$(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 
}); 
+0

Конечно! Я должен был это видеть. Нажатие на элемент также является щелчком по телу, так как элемент находится внутри тела.И события тела будут происходить перед событиями элемента. Таким образом, при вызове метода у блока всегда есть свойство отображения, равное «none». –

0

Я предлагаю использовать delegate вместо live и toggle для показа/скрытия элементов.

Преимущество delegate является то, что вы можете указать корневой элемент, который обрабатывает группу событий (в случае live корня всегда document, который может быть очень 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); 
}); 

Примечание: Вам необходимо 1.4.2 delegate

0

Если вы говорите, что обработчик присоединено через .live() Никогда не костров, обычно это происходит, если у вас есть какой-то другой обработчик между мишенью .live() и document, что делает return false; или event.stopPropagation().

Причина в том, что .live()полагается на событие, пузырящееся до документа, чтобы вызвать обработчик. Все, что мешает пузыриться, убивает .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>