stopPropagation() с событием касания

Я использую hammer.js, и кажется, что я event.stopPropagation() не работает с событием касания.

Если я щелкаю по дочернему элементу, связанное событие запускается, но также запускается родительское событие, и я этого не хочу.

$('#parent').hammer().bind('tap', function(e) {
    $(this).css('background', 'red');
});​​​​​​​​

$('#child').hammer().bind('tap', function(e) {
    e.stopPropagation();
    $(this).css('background', 'blue');
});

Вот пример: http://jsfiddle.net/Mt9gV/

Я также попробовал с jGestures, и проблема, кажется, та же самая. Как я могу достичь этого результата с одной из этих библиотек? (или другой, если это необходимо)

5 ответов

Решение

Как упоминалось в другом комментарии, можно ожидать, как и вы, что вызов event.stopPropagation() было бы все, что требуется, чтобы остановить пузыри событие до родителя.

Детали: Однако в Hammer.js это не так. Hammer создает новый конечный автомат жестов для каждого элемента, к которому вы обращаетесь $(el).hammer(), Таким образом, когда сенсорное событие инициирует дочернее событие в браузере, оно обрабатывается сначала логикой для дочернего элемента, а затем снова логикой родительского элемента. Таким образом, чтобы родитель не получил событие касания, вы должны запретить конечному автомату родителя получить исходное событие касания. Вообще звоню event.stopPropagation() также остановит распространение исходного события. Тем не менее, hammer.js's tap событие происходит touchend но originalEvent это кешируется touchstart событие. Таким образом, остановка распространения на исходном событии не имеет никакого эффекта, потому что touchstart событие давно вспыхнуло через DOM.

Решение? Я считаю, что это ошибка в молотке - отправьте запрос на удаление, который исправляет originalEvent в событии крана. Как и предполагали другие, вы можете проверить цель события, но это всегда родительский элемент - еще одна ошибка на мой взгляд. Так что вместо этого проверьте event.originalEvent.target, Вот скрипка JS с этим реализованным посредственным решением: http://jsfiddle.net/HHRHR/

У меня были похожие проблемы с сенсорными событиями.

Я решил это с помощью

return false;

что аналогично вызову e.preventDefault(); e.stopPropagation();

Поскольку я не мог получить эту работу, я использовал переменную, чтобы узнать, было ли уже запущено дочернее событие. Это работает довольно хорошо с jGestures (я не пробовал с hammer.js)

var childTriggered = false;

$('#child').bind('tapone', function(e) {
    $(this).css('background', 'red');
    childTriggered = true;
});

$('#parent').bind('tapone', function(e) {
    if(childTriggered) {
        childTriggered = false;
        return;                
    }
    $(this).css('background', 'blue');
});

Если вы не можете заставить это работать... просто вызовите другой метод на кране после проверки необходимости (arguments.callee это где я бы начал в таком случае), это будет иметь дополнительные преимущества, позволяя другим пользователям также подключить кнопку...

function myFn(a) { if(a) $(this).css('background', 'red'); else $(this).css('background', 'blue');}

$('#parent').hammer().bind('tap', function(e) {
   //Check arguments.callee or other data in event and call myFn
});​​​​​​​​

$('#children').hammer().bind('tap', function(e) {
  //Same here
});

Вы можете попробовать проверить e.currentTarget (либо это e.target?) внутри родительского обработчика, чтобы узнать, какой элемент был нажат; если это дочерний элемент, тогда просто вернитесь немедленно, иначе продолжите с функцией.

Другие вопросы по тегам