2009-11-18 7 views
1

У меня есть DIVсобытие делегации Просто нажмите кнопку не работает

<div class="myDiv"> 
    <a href="#" class="myLink">somelink</a> 
    <div class="anotherDiv">somediv</div> 
</div> 

Теперь, используя делегирование событий и понятие пропускании я хотел бы перехватывать щелчки любого из myDiv, MyLink и anotherDiv.

Согласно передовой практике это может быть сделано путем прослушивания кликов по всему миру (отсюда термин «делегация») на самом документе

$(document).click(function(e) { 
    var $eventElem = $(e.target); 
    var bStopDefaultClickAction = false; 

    if ($eventElem.is('.myDiv')) 
    { 
    alert('Never alerts when clicking on myLink or anotherDiv, why????'); 
    bStopDefaultClickAction = true; 
    } 

    return bStopDefaultClickAction; 
}); 

Смотрите мое предупреждение вопрос выше. У меня создалось впечатление, что клики пузырьков. И это несколько потому, что документ фактически получает мой клик и начинает делегировать. Но механизм пузырьков для кликов на myLink и anotherDiv, похоже, не работает, так как оператор if не вступает.

Или это выглядит так: щелчок только пузырька на один шаг, от щелкнутого элемента src до назначенный объект делегирования (в данном случае документ)? Если это так, то мне нужно обрабатывать делегацию так:

$('.myDiv').click(function(e) { 
    //...as before 
}); 

Но этот вид defeates с целью делегирования как я теперь должен иметь много обработчиков «myDiv» и, возможно, других ... он мертв легко просто иметь один объект делегирования событий документа.

Кто-нибудь знает, как это работает?

+0

Я считаю, что вы должны сделать 'вар $ eventElem = $ (e.target)' в порядке для проверки ниже, чтобы работать. –

+0

Не часть проблемы на самом деле, поскольку я написал это из памяти, но теперь я ее отредактировал. – Tommy

+1

Я думаю, что ваше понимание немного выключено. Я думаю, вы считаете, что он должен вызывать щелчок для каждого элемента. Вы будете получать только один клик на каждом уровне иерархии в dom. Попробуйте добавить обработчик click для mydiv div. Вы увидите, что событие запускалось сначала, а затем обработчик щелчка документа, но цель всегда одна и та же. – redsquare

ответ

0

Цель события не изменится. Вам нужно отразить, что делает jquery live, и на самом деле проверить, соответствует ли $ eventElem.closest ('. MyDiv').

Try:

$(document).click(function(e) { 
    var $eventElem = $(e.target); 
    var bStopDefaultClickAction = false; 

    if ($eventElem.closest('.myDiv').length) 
    { 
    alert('Never alerts when clicking on myLink or anotherDiv, why????'); 
    bStopDefaultClickAction = true; 
    } 

    return bStopDefaultClickAction; 
}); 
+0

Но что случилось с пузырьками событий? Зачем искать myDiv, когда механизм барботирования должен исправить это? Или я совершенно здесь не прав? Сила пузырьков - это механизм делегирования событий. В противном случае документ не получил бы щелчок на myDiv в первую очередь. – Tommy

+0

Ну, это не вызывает событие click для каждого родительского элемента. Помните о том, что вы слушаете самое верхнее событие. – redsquare

+0

Вы правы, THX для сортировки! – Tommy

2

Вы должны использовать живое событие с JQuery (с 1.3), она использует делегирование событий:

http://docs.jquery.com/Events/live

Так вы код будет:

$(".myDiv").live("click", function(){ 
     alert('Alert when clicking on myLink elements. Event delegation powaa !'); 

}); 

с этим, у вас есть все преимущества делегирования событий (быстрее, один прослушиватель событий и т. д.), без боли ;-)

+0

Но я хочу, чтобы это было на документе, чтобы я мог обрабатывать ВСЕ мои клики в одном месте. Верно ли, что live использует ближайший() внутри? Если да, то почему? Почему концепция барботажа не заботится об этом? – Tommy

+1

В живую входят некоторые штрафные санкции. Особенно, когда вы начинаете добавлять несколько живых делегатов. родная делегация всегда лучше - до следующей версии jq 1.4, где вы можете передавать в контекст, чтобы слушать, а не быть документом каждый раз – redsquare

+0

Это звучит здорово. – Tommy

0

Event.target всегда является элементом, вызвавшим событие, поэтому когда вы нажимаете «myLink» или «anotherDiv», вы храните ссылку на эти объекты, используя $ (e.target); Итак, что вы делаете: $ ('. MyLink'). Is ('. MyDiv'), который возвращает false, и поэтому alert() не выполняется.

Если вы хотите использовать делегирование событий таким образом, вы должны проверить Wheter event.target является элементом или любой из его детей, с помощью JQuery это можно сделать так:

$(e.target).is('.myDiv, .myDiv *') 
+0

Конечно, но щелчок на myDiv должен пузыриться, вызывая неоднократное событие. В конечном итоге eventElem будет (или должен быть) myDiv. – Tommy

+0

event.target не изменяется во время фазы захвата и пузырения - это всегда ссылка на элемент, который вызвал событие. AFAIK нет другого способа узнать, было ли событие инициировано дочерним элементом данного элемента, отличным от того, чтобы пройти дерево DOM или использовать некоторые библиотечные функции. – pawel

0

Кажется, работает отлично мне. Попробуйте его здесь: http://jsbin.com/uwari

+1

Это работает, но способ, которым это работает, - это точная проблема, которую OP хочет решить. – pawel

+0

Точно. Я хочу использовать все возможности делегирования событий и пузырей, но, похоже, это невозможно. – Tommy

0

Проверьте это: Один клик обработчик на одной странице

var page = document.getElementById("contentWrapper"); 
page.addEventListener("click", function (e) { 
    var target, clickTarget, propagationFlag;  
    target = e.target || e.srcElement; 
    while (target !== page) { 
     clickTarget = target.getAttribute("data-clickTarget"); 
     if (clickTarget) { 
      clickHandler[clickTarget](e); 
      propagationFlag = target.getAttribute("data-propagationFlag"); 
     } 
     if (propagationFlag === "true") { 
      break; 
     } 
     target = target.parentNode; 
    } 
}); 
Смежные вопросы