Reputation: 9823
I was recently testing the click event (finding a textbox upon click) of a <label>
and found something unusual.
In the HTML markup,
<input>
is inside the <label>
, the click event on that
label is firing two times<input>
is outside the <label>
, the click event is
functioning as expectedTo 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
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);
});
Upvotes: 0
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