Як зупинити поширення події за допомогою атрибута onclick inline?


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події клацання?

Відповіді:


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 = "попередження (подія);"> </div>
Морган Ченг

1
eventЗдається, вони також доступні в рамках Inline 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; [...]"

Однак, загалом кажучи, вам слід уникати обробників подій, що вбудовуються, якщо вам потрібно зробити щось складне, як, наприклад, зупинити поширення. Писати ваші обробники подій окремо та приєднувати їх до елементів - це набагато краща ідея у середньо- та довгостроковій перспективі, як щодо читабельності, так і ремонтопридатності.


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".
Pointy

1
якщо (e.cancelBubble) не здається мені правильним, ви встановите це на істину, якщо це вже правда
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;
   }
}

20

У мене була така ж проблема - поле помилок js в IE - це добре працює у всіх браузерах, наскільки я бачу (event.cancelBubble = вірно виконує роботу в IE)

onClick="if(event.stopPropagation){event.stopPropagation();}event.cancelBubble=true;"

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 зовнішнього діва є проблема цитування рядків ...?!
Ніколь

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 = аргументи [0] || window.event; [...]), я використав цей oneliner inline на onclick для швидкий злом:

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

Я знаю, що пізно, але я хотів повідомити вам, що це працює в один рядок. Брекети повертають подію, у якій в обох випадках додається функція stopPropagation, тому я спробував інкапсулювати їх у дужки, як у випадку if і .... він працює. :)


1

Це також працює - У посиланні HTML використовуйте onclick із поверненням так:

<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;
    }
};

2
Це не те, що означало питання.
jzonthemtn

@jbird Саме це означало питання. Це інший (старіший) спосіб скасувати подію, відбиваючись від дерева dom (це у специфікації dom api рівня 1).
gion_13

@ gion_13 Але дія кліку - це не те, що потрібно підтвердити користувачеві. У питанні ми хочемо, щоб дитина onclick () спрацьовувала, а не onclick батьків (). Введення підказки користувача між ними не є корисним. Я сподіваюся, ви зможете побачити цю різницю.
jzonthemtn

1
Це confirmне актуально. Я маю на увазі повернене значення . цитата: У посиланні HTML використовуйте onclick із поверненням так
gion_13

повертаючи помилкові скасування за посиланням, воно не скасовує розповсюдження на моєму хромі
commonpike

1

Чому б не просто перевірити, на який елемент було натиснуто? Якщо натиснути щось, window.event.targetприсвоюється елементу, на який було натиснуто, і елемент, який натиснув, також може бути переданий як аргумент.

Якщо мета і елемент не рівні, це подія, яка поширюється вгору.

function myfunc(el){
  if (window.event.target === el){
      // perform action
  }
}
<div onclick="myfunc(this)" />

Спасибі, товариш, це, здається, найчистіше рішення тут. У бічній примітці ви повинні врахувати, що це збігається лише тоді, коли клацнув елемент - це самий верхній елемент.
Саймон Маттес

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>

0

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

<div onclick="alert('blablabla'); (arguments[0] ? arguments[0].stopPropagation() : false);">...</div>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.