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

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

Во-первых:

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

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

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

Во-вторых:

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

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

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

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

Заранее благодарим за помощь,
Matt

Ответ 1

Для вашего первого вопроса: 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

Ответ 2

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

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

event.cancelBubble = true;
if(event.stopPropagation) event.stopPropagation();

Ответ 3

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

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

Ответ 5

второй:

см. также:

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

[div onmousedown="clicking = true"
     onclick = " alert('child clicked") "
     onmouseup="clicking = false"

Ответ 6

У меня была очень похожая проблема с вашим первым вопросом. Но вместо этого <div> и флажок - таблица. Посмотрите на мой НЕ РАБОТАЮЩИЙ код:

<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, как я мог это сделать, я нашел this briliant post на 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.

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

Ответ 7

Для второго вы можете поместить свой div перед изображением и не иметь тегов изображений внутри div. Это должно дать вам необходимую функциональность.

Ответ 8

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

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

Во втором случае я фактически разделил изображение на пять разделов и только поместил один из них в div, как показано ниже:

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

Kludgy, я знаю, но сначала я предпочитаю простейшие решения.

Ответ 9

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

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

Ответ 10

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

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

Ответ 11

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

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

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

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