asprin
asprin

Reputation: 9823

A puzzling click event : Why such behaviour?

I was recently testing the click event (finding a textbox upon click) of a <label> and found something unusual.

In the HTML markup,

To better understand what I'm trying to put forward, please refer to the fiddle at JS Fiddle

I'm baffled because of this and can't figure out the reason behind it. Any takers?

Upvotes: 1

Views: 54

Answers (2)

Bhushan Kawadkar
Bhushan Kawadkar

Reputation: 28513

In your case, click event is propagating from label to input and then again to label, hence you can find two alerts.

You can use below code when we can check the target element tag name and if it is INPUT then return otherwise process further.

$(".v1 li label").click(function(event){
    if(event.target.tagName=='INPUT')
      return false;
   var ct= $(this).find("input").val();     
   alert("first "+ct);      
});

JSFiddle Demo

Upvotes: 0

David Thomas
David Thomas

Reputation: 253328

If the <input> is inside the <label>, the click event on that label is firing two times

Because events 'bubble' up through the DOM, from the element recieving the initial event (the event.target, here the <input />) through ancestors. Because the listener is attached to the parent of the <input /> it first fires on the click detected on its descendant, and then again when the click bubbles to itself.

To prevent this, you can use event.stopPropagation() to prevent bubbling.

Because the event, in this case, has already bubbled to the <label> element at the point that the alert()/event-handler is fired, you'll have to explicitly call event.stopPropagation() on the <input /> itself, rather than in the event-handler attached to the <label>:

$(function() {
  $('label input').click(function(event) {
    event.stopPropagation();
  });

  $(".v1 li label").click(function() {
    var ct = $(this).find("input").val();
    alert(ct);
  });

  $(".v2 li label").click(function() {
    var ct = $(this).parent().find("input").val();
    alert(ct);
  });
});
ul {
  padding: 10px;
}
li {
  list-style: none;
  margin-bottom: 5px;
}
li label {
  display: block;
  background-color: #f0f0f0;
  padding: 5px;
  cursor: pointer;
  border: 1px solid #ccc;
}
li input {
  display: none;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3><i>input</i> inside <i>label</i></h3>

<ul class="v1">
  <li>
    <label for="l1">
      <input type="radio" name="a" value="1" id="l1" />First</label>
  </li>
  <li>
    <label for="l2">
      <input type="radio" name="a" value="2" id="l2" />Second</label>
  </li>
  <li>
    <label for="l3">
      <input type="radio" name="a" value="3" id="l3" />Third</label>
  </li>
</ul>
<hr />
<h3><i>input</i> outside <i>label<i></h3> 
<ul class="v2">
  <li>
    <label for="ll1">Fourth</label>
    <input type="radio" name="b" value="4" id="ll1" />
  </li>
  <li>
    <label for="ll2">Fifth</label>
    <input type="radio" name="b" value="5" id="ll2" />
  </li>
  <li>
    <label for="ll3">Sixth</label>
    <input type="radio" name="b" value="6" id="ll3" />
  </li>
</ul>

References:

Upvotes: 3

Related Questions