14

In the following snippet, why does divClicked() trigger twice when the <label> is clicked, but only once when <input> is clicked?

function divClicked(_index) {
  console.log("div click event");
}

function inputClicked(_index) {
  console.log("input click event");
}
<div class="option" onclick="divClicked(1)">
  <input id="1_1" name="group_1" type="radio" value="1" onclick="inputClicked(1)" />
  <label for="1_1">label</label>
</div>

Note: I want to know why this happens, not a "quick fix" like: put onclick() on label.

Zze
  • 18,229
  • 13
  • 85
  • 118
  • Possible duplicate of [Jquery click event triggers twice when clicked on html label](http://stackoverflow.com/questions/17185265/jquery-click-event-triggers-twice-when-clicked-on-html-label) – Nishanth Matha Apr 03 '17 at 00:39
  • 1
    @NishanthMatha Not sure how this is a dup of that because no where in that question are events attached to the containing div. – Zze Apr 03 '17 at 00:43
  • 1
    @NishanthMatha How is present Question a duplicate of linked Question? – guest271314 Apr 03 '17 at 00:43
  • @Zze @guest271314 not having a `div` or exact wordings in question doesn't make it unique. You see the explanation here: `And depending if you click on checkbox or the label, the callback for $('#test label') is called once or twice because the input element is part of the label and is one union and therefor also received the event if the label is click` – Nishanth Matha Apr 03 '17 at 00:48
  • 2
    @NishanthMatha But the div event handler is executing twice, not the input handler – Andrew Li Apr 03 '17 at 00:49
  • @NishanthMatha What @Andrew Li stated... the `inputClicked()` is only triggered once - maybe you should look at my example and question properly. – Zze Apr 03 '17 at 00:50
  • 1
    @NishanthMatha How does that explain why `divClicked` is called twice at present Question at `click` at `label` element? – guest271314 Apr 03 '17 at 00:51
  • @guest271314 Was that comment for me or @NishanthMatha? If it was for me, then I'm afraid i'm not certain what you're asking me? – Zze Apr 03 '17 at 00:53
  • 1
    @Zze Corrected addressee of comment – guest271314 Apr 03 '17 at 00:56

2 Answers2

17

This happens because of what the HTML spec describes at 4.10.4:

For example, on platforms where clicking a checkbox label checks the checkbox, clicking the label in the following snippet could trigger the user agent to run synthetic click activation steps on the input element, as if the element itself had been triggered by the user:

<label><input type=checkbox name=lost> Lost</label>

On other platforms, the behavior might be just to focus the control, or do nothing.

This means that when a <label> is clicked, the browser creates a second "synthetic" click event on the associated <input> element, in order to toggle its state.

The reason divClicked is triggered twice, is because the first event which comes from the <label> bubbles up to the <div>, and also the second, synthetic click event bubbles up to the <div>.

4castle
  • 32,613
  • 11
  • 69
  • 106
  • For what it's worth, my answer consisted of this part of the spec and a bit more and explained the bubbling, step by step. Since this answer would've been shorter and more concise, it's better. – Andrew Li Apr 03 '17 at 01:20
  • Add e.preventDefault(); at last line , in my case , its fixed – Wagner Pereira Sep 29 '20 at 19:12
0

This is usually be cause of the bubbling principle of click event:

When an event happens on an element, it runs on it, its associated elements,its parent and other ancestors.

Now, The relation is when you click on label there a are two events which bubbles up here:

1) Click on div (which you expect)

2) Click on input (which is also expected)

2.1) When click on input is triggered then a click on div is also triggered again here

You can confirm this behavior by using event.bubbles prop.

EDIT:

The reason for the connection between label and input: (I know this is absolutely not required, as it's present all over the place yet)

A <label> can be associated with a control either by placing the control element inside the <label> element, or by using the for attribute. Such a control is called the labeled control of the label element. One input can be associated with multiple labels.

Taken from: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label

Which means placing for on label referencing id of an input element will stimulate the behavior as if the element is inside the label. This would bubble a event on input onto label like any event on child to parent

Nishanth Matha
  • 5,993
  • 2
  • 19
  • 28
  • 1
    You've only described a single event, bubbling up through multiple elements. Bubbling doesn't create multiple events, it just describes the behavior of how one event triggers handlers on all ancestors. – 4castle Apr 03 '17 at 01:21
  • @4castle I guess The more important part is `2.1` which is highlighted! the concept of event bubbling is just to tell that `click` on label or `click` on input would trigger a click on `div`...then comes the actual reason which is `2.1` – Nishanth Matha Apr 03 '17 at 01:23
  • 1
    The part that's missing from your answer is: Why does clicking on the label produce a second, separate event on the input element? You've described bubbling, but not explained how the `` handler is toggled by clicking on the label, even though the `` isn't an ancestor of the ` – 4castle Apr 03 '17 at 01:28
  • @4castle that's all over the internet..(even in my comment to OP)! Yet if you think that's what missing refer to my edit!! – Nishanth Matha Apr 03 '17 at 01:35
  • 1
    Your edit still doesn't describe why clicking on the label would trigger a click on the ``. Events don't bubble downwards to child elements or sibling elements, only to ancestor elements. – 4castle Apr 03 '17 at 01:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139715/discussion-between-4castle-and-nishanth-matha). – 4castle Apr 03 '17 at 01:45