Остановка распространения не работает

У меня есть следующий JQuery eventhandler. Я хочу остановить все навигации на веб-странице.

$(document).click(function(event) {
            event.stopPropagation();
            event.preventDefault();
            event.cancelBubble = true;
            event.stopImmediatePropagation();
            $(document).css('border-color','');
            $(document).css('background-color',''); 
            $(event.target).css('border-color','yellow');
            $(event.target).css('background-color','#6BFF70');
            return false;
    });

Когда я использую это на странице входа в систему Facebook, он останавливает все навигационные операции. Но на главной странице Google кнопка "Я чувствую себя счастливой" все еще переходит на следующую страницу. Как его избежать?

Я использую браузер JavaFX. Он похож на браузер Safari.

Ответ 1

Если я загружаю страницу поиска Google и выполняю ее на консоли:

document.body.addEventListener(
  "click", 
  function (ev) { ev.stopPropagation(); ev.preventDefault(); },
  true);

то я больше не могу нажать кнопку "Я чувствую себя счастливой". Ключ должен использовать третий параметр и установить его на true. Вот что говорит MDN:

useCapture Необязательный

Если true, useCapture указывает, что пользователь хочет инициировать захват. После начала захвата все события указанного типа будут отправлены зарегистрированному прослушивателю перед отправкой на любой EventTarget под ним в дереве DOM.

(Акцент добавлен.)

То, что вы пытались сделать, не работает, потому что обработчик событий находится на document и поэтому будет после обработчиков событий на дочерних элементах документа. Поэтому ваш обработчик ничего не может предотвратить.

С useCapture установлено значение true, вы можете работать с событием, прежде чем он получит возможность передать дочерний элемент. Я не знаю, как обработчики событий jQuery работают так, как вы это делаете с помощью useCapture. Barmar ответ здесь говорит, что вы не можете использовать jQuery для установки такого обработчика. Я склонен ему поверить.

Ответ 2

99.99% веб-страниц не смогут остановить свою навигацию, остановив распространение события по причине, о которой я прокомментировал (вы не можете остановить событие до того, как оно инициирует все обработчики для начальной цели события). Если предотвращение навигации - это все, что вас интересует, я рекомендую использовать событие window.onbeforeunload, которое сделано для этой точной ситуации.

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

HTML:

<a href="google.com">google</a>

JS:

window.onbeforeunload = function() {
    return "Are you sure?"
}

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

Ответ 3

Попробуйте следующее:

$('body').click(function(event) {
            event.stopPropagation();
            event.preventDefault();
            event.cancelBubble = true;
            event.stopImmediatePropagation();
            $(document).css('border-color','');
            $(document).css('background-color',''); 
            $(event.target).css('border-color','yellow');
            $(event.target).css('background-color','#6BFF70');
            return false;
    });

Ответ 4

Попробуйте привязать не только к событию click, но и к событию mousedown.

Ответ 5

Попробуйте этот css:

 body * {
    pointer-events: none;
 }

или в jQuery:

 $("body *").css("pointer-events", "none");

Ответ 6

Попробуйте объявить новое событие окна, а затем прекратите распространение:

var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation)
{
   e.stopPropagation();
}

Ответ 7

Обратите внимание, что Google использует jsaction = "..." вместо onclick = "...". Попробуйте использовать метод unbind на указанной кнопке.

Также вы можете использовать динамическое вложение, например:

$(document).on('click', '*', function

Или throw new Error() (как грязный хак)

Ответ 8

preventDefault() не должен работать в этом случае, поэтому Google полагался на пользовательские прослушиватели событий для обработки событий щелчка на этой кнопке. Хотя preventDefault() предотвращает поведение браузера по умолчанию.

Например, если эта кнопка имеет тип = "отправить", предотвращение дефолта по событию клика предотвратит поведение браузера по умолчанию, которое отправляет форму. Но в этом случае клик обрабатывается eventListeners, добавленным к самой кнопке. preventDefault() не повлияет на уловку событий. Не останавливайтеPropagation(), потому что он прекращает распространение события на более высокие уровни DOM, тогда как другие eventListeners на одном уровне (кнопка в нашем случае) все равно получают событие. stopImmediatePropagation() может работать теоретически, но только если ваш eventListener был добавлен до google.

Таким образом, самый простой способ прекратить распространение - остановить событие до того, как оно достигнет кнопки node, и это на этапе захвата, потому что кнопка является самым низким элементом в иерархии. Это можно сделать, передав истинный аргумент, добавив eventListener

document.body.addEventListener("click", function (event) { 
  event.stopPropagation();
}, true);

Таким образом, событие будет остановлено до фазы пузырька, и поэтому до того, как оно достигнет значков событий, добавленных к кнопке. Подробнее о фазах захвата и пузырьков здесь

Обратите внимание, что preventDefault() в этом случае не требуется. На самом деле, эти прослушиватели событий кнопки должны предотвратить сами по умолчанию. Вот эти eventListeners для кликов и клавиш соответственно:

d = function(a) {
 c.Xa.search(c.yc(), b);
 return s_1vb(a)
}

function(a) {
 13 != a.keyCode && 32 != a.keyCode || d(a)
}

Обратите внимание на вызов s_1vb, вот его источник:

s_1vb.toString();
/*"function (a){
     a&&(a.preventDefault&&a.preventDefault(),a.returnValue=!1);
     return!1
  }"*/

В основном это функция, которая принимает событие и делает все возможное, чтобы предотвратить поведение браузера по умолчанию.

Кстати, поведение по умолчанию можно отменить на любом этапе потока событий (se Спецификация событий), включая последний этап, когда он достиг документа. Только после того, как он прошел через "все", все события не были отменены, браузер должен выполнить свое поведение по умолчанию. Поэтому привязка вашего слушателя к документу не была причиной того, что preventDefault() не работал, потому что это был неправильный парень для работы:)