Как я могу остановить событие onclick от запуска родительского элемента при нажатии на дочерний элемент? - PullRequest
11 голосов
/ 12 июня 2009

У меня две проблемы с событиями onclick, они чем-то похожи, поэтому я спрошу их обоих здесь.

Во-первых:

У меня есть флажок в div. Вход имеет функцию onchange, а div имеет функцию onclick.

<div onclick="doSomething()">
     <input type="checkbox" onchange="doSomethingElse()" />
</div>

Проблема в том, что, когда я ставлю / снимаю флажок, срабатывает одновременно doSomething () и doSomethingElse (). Любые идеи о том, как предотвратить это? Я попытался сделать onchange = "doSomethingElse (событие)" и функцию в doSomethingElse (e) у меня была e.stopPropagation (); и это не сработало.

Второе:

У меня есть изображение в div. У div есть функция onclick, а у изображения - нет. Изображение намеренно больше, чем div, и выходит за пределы div.

-----------------------
|        image        |
|   ---------------   |
|   |     div     |   |
|   |             |   |
|   ---------------   |
|                     |
-----------------------

Я хочу, чтобы онклик срабатывал только в том случае, если пользователь щелкает в пределах границ блока div. Тем не менее, событие onclick также запускается, если вы щелкнете мышью по части изображения, которая вышла наружу из div ... Любые идеи?

Первый вопрос для меня важнее, чем второй. Но если кто-то может ответить на оба вопроса, это было бы здорово!

Заранее спасибо за помощь,
Matt

Ответы [ 11 ]

8 голосов
/ 12 июня 2009

Для вашего первого вопроса: IE не поддерживает stopPropagation(), вместо этого вы должны использовать e.cancelBubble = true. Просто сначала проверьте функцию, чтобы выяснить, какой метод следует использовать (if (e.stopPropagation) {code}).

По второму вопросу: Может быть, включить второй div, который обрабатывает событие click?

<div><img src="image.jpg"/></div>
<div style="position:absolute" onclick="doSomething();"></div>

и затем правильно расположите второй div

5 голосов
/ 12 июня 2009

Для вашего второго вопроса вы можете получить координаты указателя, когда произошло событие щелчка, и сравнить их с координатами div. (фактическая реализация зависит от того, какую библиотеку js вы используете)

Для вашего первого вопроса, чтобы остановить всплывающее событие, вы должны использовать

event.cancelBubble = true;
if(event.stopPropagation) event.stopPropagation();
2 голосов
/ 09 мая 2014

В вашем первом примере с флажком внутри div, onchange - это не то же самое, что onclick, поэтому вызов event.stopPropagation () в обработчике onchange не остановит запуск внешнего onclick. Вам нужен дополнительный обработчик onclick для флажка, чтобы предотвратить всплывание клика.

<div onclick="doSomething()">
     <input type="checkbox" onclick="event.stopPropagation()" onchange="doSomethingElse()" />
</div>
1 голос
/ 13 ноября 2014

У меня была очень похожая проблема с вашим первым вопросом. Но вместо

и флажок это была таблица. Посмотрите на мой НЕ РАБОТАЮЩИЙ код:
<table>
  <tr onClick="alert('I expect this alert when Cell_1 or Cell_2 are clicked but not Cell_3')">
    <td>Cell_1</td>
    <td>Cell_2</td>
    <td onClick="alert('I expect this alert only when Cell_3 is clicked')">Cell_3</td>
  </tr>
<table>

При нажатии на Cell_1 или Cell_2 мой код работает, как я ожидал, но при нажатии на Cell_3 нет, потому что он показал 2 предупреждения.

Первый был:

«Я ожидаю это предупреждение только при нажатии на Cell_3»

а второй был:

Я ожидаю это предупреждение, когда на Cell_1 или Cell_2 нажимают, но не на Cell_3 .

Google, как мне это удалось, я нашел этот блестящий пост в Quirksmode .

Проще говоря, я мог бы решить головоломку следующим образом:

<table>
  <tr onClick="alert('I expect this alert when Cell_1 or Cell_2 are clicked but not Cell_3')">
    <td>Cell_1</td>
    <td>Cell_2</td>
    <td onClick="Cell_3Alert(event)">Cell_3</td>
  </tr>
<table>

И Javascript:

function Cell_3Alert(e) {
  alert('I expect this alert only when Cell_3 is clicked');

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

Я тестировал, и он работал на FireFox 3.6+, IE6 + и Chrome.

Надеюсь, это поможет!

1 голос
/ 10 октября 2010

второй:

см. Также:

[img onmousedown="if (!clicking) alert('parent clicked') " ...]

[div onmousedown="clicking = true"
     onclick = " alert('child clicked") "
     onmouseup="clicking = false"
1 голос
/ 12 июня 2009

Вам нужно остановить распространение. Вы можете использовать jQuery для этого: Остановка распространения .

0 голосов
/ 15 апреля 2016

У меня была такая же проблема. Для меня это был тег span в другом теге span для меню боковой панели. Подкатегории должны были открываться при каждом нажатии, но не при нажатии на содержимое. Но, просматривая свойства события click, я думаю, что нашел решение и написал следующее:

function sidebar_click(event)
{
    if (event.target == event.currentTarget)
        event.currentTarget.classList.toggle('open');
}

Он запускается только если target = currentTarget. Target - это элемент, на который вы нажимаете, а currentTarget - это элемент, с которым связан обработчик события. Если они одинаковы, он выполняется, если нет, то не выполняется.

Надеюсь, это поможет.

0 голосов
/ 12 июня 2009

Кроме или как альтернатива прекращению захвата пузырьков, каждая из ваших функций событий должна иметь некоторый код, который проверяет, что был выбран правильный элемент , используется event.target или event.scrElement в IE, чтобы найти нажатый элемент.

В качестве второго вопроса вы, вероятно, захотите использовать карту изображений , которая представляет собой HTML-код, предоставленный для нажатия на определенную область изображения.

0 голосов
/ 12 июня 2009

Для первой попробуйте также использовать e.preventBubble () и вернуть false из обработчика.

За секунду вы можете зафиксировать щелчок и проверить цель события. Это проще всего, если вы используете некоторую библиотеку, которая нормализует события, такие как jQuery, где e.target возвращает вам точный элемент, по которому событие было запущено. Другой вариант - поместить обработчик щелчка не на изображение, а в любой контейнер, на который вы переполняете изображение.

0 голосов
/ 12 июня 2009

Я не уверен, является ли ваш первый вариант упрощением или нет. Если это именно то, что есть, я бы просто удалил onClick из div.

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

Во втором случае я бы разделил изображение на пять частей и поместил только один из них в элемент div следующим образом:

+------------------------------------------------------+
|                     Image part 1                     |
+------------------------------------------------------+
| Image part 2 | Image part 3 (and div) | Image part 4 |
+------------------------------------------------------+
|                     Image part 5                     |
+------------------------------------------------------+

Клудги, я знаю, но сначала я стремлюсь к самым простым решениям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...