Как остановить распространение событий с помощью встроенного атрибута onclick?

313

Учтите следующее:

<div onclick="alert('you clicked the header')" class="header">
  <span onclick="alert('you clicked inside the header');">something inside the header</span>
</div>

Как я могу сделать так, чтобы, когда пользователь нажимает промежуток, он не запускает div запускал событие click?

Сэм
источник

Ответы:

272

Используйте event.stopPropagation () .

<span onclick="event.stopPropagation(); alert('you clicked inside the header');">something inside the header</span>

Для IE: window.event.cancelBubble = true

<span onclick="window.event.cancelBubble = true; alert('you clicked inside the header');">something inside the header</span>
Джеймс
источник
11
В FireFox нет такого объекта как событие.
Роберт С. Барт
6
Объект события является параметром обратного вызова. На самом деле в IE не существует такого объекта, как объект события, потому что этот объект доступен через window.event, а не является параметром функции :-)
Винсент Роберт,
66
Это просто неправильно - встроенные обработчики onclick не передают событие в качестве аргумента. Правильное решение - Гаретс, ниже.
Benubird
2
В Firefox вы можете получить доступ к переменному событию во встроенном скрипте, но window.event недоступен. <div onclick = "alert (event);"> </ div>
Морган Чен
1
eventПохоже, что он доступен и для встроенных событий в IOS Safari.
Юваль А.
210

Есть два способа получить объект события внутри функции:

  1. Первый аргумент в W3C-совместимом браузере (Chrome, Firefox, Safari, IE9 +)
  2. Объект window.event в Internet Explorer (<= 8)

Если вам нужно поддерживать устаревшие браузеры, которые не следуют рекомендациям W3C, обычно внутри функции вы используете что-то вроде следующего:

function(e) {
  var event = e || window.event;
  [...];
}

который проверит сначала один, а затем другой и сохранит то, что было найдено внутри переменной события. Однако в встроенном обработчике событий нет eобъекта для использования. В этом случае вам нужно воспользоваться argumentsколлекцией, которая всегда доступна и ссылается на полный набор аргументов, передаваемых функции:

onclick="var event = arguments[0] || window.event; [...]"

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

Gareth
источник
11
Из встроенного слушателя вы можете передать объект события как:, onclick="foo(event)"затем в функцию function foo(event){/* do stuff with event */}. Это работает в моделях событий IE и W3C.
RobG
5
Это «меньше или равно восьми» несколько ... неоднозначно.
TechNyquist
8
это на самом деле не отвечает на вопрос.
jcomeau_ictx
1
аккуратный ответ на другой вопрос. : - /
Арель
80

Имейте в виду, что window.event не поддерживается в FireFox, и поэтому оно должно быть примерно таким:

e.cancelBubble = true

Или вы можете использовать стандарт W3C для FireFox:

e.stopPropagation();

Если вы хотите стать модным, вы можете сделать это:

function myEventHandler(e)
{
    if (!e)
      e = window.event;

    //IE9 & Other Browsers
    if (e.stopPropagation) {
      e.stopPropagation();
    }
    //IE8 and Lower
    else {
      e.cancelBubble = true;
    }
}
Роберт С. Барт
источник
12
И чтобы это работало, нужно назвать это так:<div onclick="myEventHandler(event);">
DarkDust
1
Это может быть «событие || window.event».
Заостренный
1
если (e.cancelBubble) мне не подходит, вы устанавливаете его в true, если это уже правда
Guillaume86
e.cancelBubbleвозвращает ложь в IE! Это не может достичь e.cancelBubble = true;инструкции. Вместо этого используйте условие SoftwareARM !!
Мауретто
45

Используйте эту функцию, она проверит наличие правильного метода.

function disabledEventPropagation(event)
{
   if (event.stopPropagation){
       event.stopPropagation();
   }
   else if(window.event){
      window.event.cancelBubble=true;
   }
}
SoftwareARM
источник
20

У меня была та же самая проблема - окно ошибки js в IE - это прекрасно работает во всех браузерах, насколько я вижу (event.cancelBubble = true делает работу в IE)

onClick="if(event.stopPropagation){event.stopPropagation();}event.cancelBubble=true;"
MSC
источник
1
Спасибо @MSC именно то, что мне нужно!
DannyC
1
Встроенный скрипт. Это действительно отвечает на вопрос
Цезарь
10

Это сработало для меня

<script>
function cancelBubble(e) {
 var evt = e ? e:window.event;
 if (evt.stopPropagation)    evt.stopPropagation();
 if (evt.cancelBubble!=null) evt.cancelBubble = true;
}
</script>

<div onclick="alert('Click!')">
  <div onclick="cancelBubble(event)">Something inside the other div</div>
</div>
Матиас Контрерас Сельман
источник
Вы уверены, что этот фрагмент кода сработал для вас? Потому что похоже, что есть проблема с цитированием строк в обработчике onclick внешнего div ...?!
Николь
7

Для веб-страниц ASP.NET (не MVC) вы можете использовать Sys.UI.DomEventобъект как оболочку нативного события.

<div onclick="event.stopPropagation();" ...

или передать событие в качестве параметра внутренней функции:

<div onclick="someFunction(event);" ...

и в некоторых функциях:

function someFunction(event){
    event.stopPropagation(); // here Sys.UI.DomEvent.stopPropagation() method is used
    // other onclick logic
}
Евгений Горб
источник
2

Я не могу комментировать из-за кармы, поэтому я пишу это как полный ответ: в соответствии с ответом Гарета (var e = arguments [0] || window.event; [...]) я использовал этот oneliner, встроенный в onclick для быстрый взлом:

<div onclick="(arguments[0] || window.event).stopPropagation();">..</div>

Я знаю, что уже поздно, но я хотел, чтобы вы знали, что это работает в одну строку. Фигурные скобки возвращают событие, к которому в обоих случаях присоединена функция stopPropagation, поэтому я попытался заключить их в фигурные скобки, как в случаях if и ...., это работает. :)

user3611941
источник
1

Это также работает - в ссылке HTML используйте onclick с return следующим образом:

<a href="mypage.html" onclick="return confirmClick();">Delete</a>

И тогда функция comfirmClick () должна выглядеть так:

function confirmClick() {
    if(confirm("Do you really want to delete this task?")) {
        return true;
    } else {
        return false;
    }
};
Rajendra
источник
2
Это не то, что имел в виду вопрос.
jzonthemtn
@jbird Это именно то, что имел в виду вопрос. Это другой (более старый) способ отменить событие, чем всплывающее дерево dom (это в спецификациях dom api level 1).
gion_13
@ gion_13 Но действие клика - это не то, что пользователь должен подтвердить. В этом вопросе мы хотим, чтобы onclick () ребенка запускался, а не onclick () родителя. Помещать подсказки между ними не полезно. Я надеюсь, что вы можете увидеть эту разницу.
jzonthemtn
1
Это confirmне актуально. Я имею в виду возвращаемое значение . цитата: В ссылке HTML используйте onclick с return, как это
gion_13
возвращая ложные отмены по ссылке, это не отменяет распространение на моем chrome
commonpike
1

Почему бы просто не проверить, какой элемент был нажат? Если вы щелкаете по чему-либо, window.event.targetон присваивается элементу, по которому был выполнен щелчок, и этот элемент также может быть передан в качестве аргумента.

Если цель и элемент не равны, это было событие, которое распространялось вверх.

function myfunc(el){
  if (window.event.target === el){
      // perform action
  }
}
<div onclick="myfunc(this)" />
CS01
источник
Спасибо, приятель, это, кажется, самое чистое решение здесь. Что касается сопутствующего примечания, вы должны учесть, что это совпадает только тогда, когда нажатый элемент является фактическим верхним элементом.
Саймон Маттес
0
<div onclick="alert('you clicked the header')" class="header">
  <span onclick="alert('you clicked inside the header'); event.stopPropagation()">
    something inside the header
  </span>
</div>
commonpike
источник
0

Лучшее решение - обработать событие с помощью функции javascript, но для того, чтобы использовать простое и быстрое решение, использующее непосредственно элемент html, и как только «event» и «window.event» устарели и не будут поддерживаться повсеместно ( https://developer.mozilla.org/en-US/docs/Web/API/Window/event ), я предлагаю следующий «жесткий код»:

<div onclick="alert('blablabla'); (arguments[0] ? arguments[0].stopPropagation() : false);">...</div>
jose.serapicos
источник