In a page I'm creating there are some WebGrid components serving as master grids, and on clicking a row, a details area is shown. Now every row shall also have a delete button, so that clicking this button, the row is deleted.
Now because I have a click handler for #myGrid tbody tr, and the button (which is actually just an image) is inside the tr, both click handlers are executed when I click on the button. What can I do to prevent this and just execute the click handler for the button, that is, for the "top" element?
Here is a jsFiddle roughly demonstrating what I'm currently doing
Is there an elegant way to do this, or is there maybe an alternative to what I'm currently doing?
For reference, here's some even shorter sample code. HTML:
<table id="tbl">
<tr>
<td><img src="someImage.png" class="delete-button" /></td>
</tr>
</table>
JavaScript:
$(document).ready(function () {
$("#tbl tr").click(function () {
alert("row click");
});
$(".delete-button").click(function () {
alert("delete-button click");
});
})
Use stopPropagation
Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
$(".delete-button").click(function (e) {
// ^
alert("delete-button click");
e.stopPropagation();
// ^^^^^^^^^^^^^^^^
});
https://jsfiddle.net/tusharj/nbvdw0q1/3/
Docs: http://api.jquery.com/event.stopPropagation/
You simply need to stop the propagation of the click event of the elements containing the button:
$(".delete-button").click(function (event) {
alert("delete-button click");
event.stopPropagation();
});
Updated fiddle.
You can just capture the parent click then compare the event target against the delete button.
(Demo)
$("#tbl tr").hover(function() {
$(this).toggleClass("clickable");
}).click(function(e) {
if ($(e.target) === $('.delete-button')) {
alert("delete-button click");
} else {
alert("row click");
}
});
Related
I have code that dynamically generates rows of the table where the first column of each row is checkbox:
let tr = $("<tr class='clickable-row'></tr>");
tr.append(`<td><input type="checkbox" class="checkbox"></td>`);
...
OnClick event displays the details of the row.
$(document).on("click", ".clickable-row", function (e) {
measurementManager.displayMeasurementsInfo(this);
});
How to prevent function calling on the first column of each row?
You need to stop the event from propagating when the first <td> element is clicked. Add the following:
$(document).on('click', '.clickable-row td:first', function(e) { e.stopPropagation() });
When I click a button, I change its ID and apply a new style to it by adding a class toMenu. What I wanted to do is, when I click the button with the new ID menu, that it adds another class menuTransition. But what now happens is that it already adds the class menuTransition when I click the button with the old ID #button. But what it's supposed to do, is not add the class menuTransition until the button with the new ID #menu is clicked.
Here's my code:
$(document).ready(function() {
$("#button").click(function(){
$("#button").addClass("toMenu")
$("#button").attr("id","menu");
});
});
$(document).on("click", "#menu", function() {
$("#menu").addClass("menuTransition");
});
What you're seeing is a bit of a race condition. With your button click event handler you're adding a class and an ID to your button. Then with your delegated event handler you're looking for any clicks on the document, even those that bubble up from descendant elements, and adding a class there as well. One way to handle this is to add a small (~ 1 msec) delay to short-circuit this race that would normally occur with your example code.
$(document).ready(function() {
$("#button").click(function() {
$("#button").addClass("toMenu")
setTimeout(function() {
$("#button").attr("id", "menu");
}, 1)
});
});
$(document).on("click", "#menu", function() {
$("#menu").addClass("menuTransition");
});
.toMenu {
font-weight: bold;
}
.menuTransition {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">
button
</button>
By adding the 1 millisecond delay, the ID is added after the click on the button has reached the document event handler, so that event handler only fires after the first click on the button.
You should not be changing the ID. Element IDs are intended to be static. You can use a class to tag the current state of the button / menu and make it behave accordingly (and at the same time avoid the inefficient delegated event handler on $(document):
$(document).ready(function() {
$("#menubutton").on('click', function() {
var $this = $(this);
if ($this.hasClass('toMenu')) {
$this.addClass('menuTransition');
} else {
$this.addClass('toMenu');
}
});
});
https://jsfiddle.net/r7a2r9eL/
$('#insertBtn').click( function(){
$('#mytable > tbody:last-child').append('<tr><td>'+$('#fnameText').val()+'</td><td>'+$('#lnameText').val()+'</td><td>'+$('#pointText').val()+'</td><td><button type="button" class="deleteClass">Delete</button></td></tr>');
$('#textTable input').val('')
});
$(".deleteClass").on("click",function() {
alert('row deleted');
});
Try typing anything into the textboxes. Then click on the insert button.
Then click on the delete button on the first column. Notice the alert didn't trigger even though the button has the intended class
What is wrong with my code?
What you are looking for is event delegation:
Use this:
$(document).on('click','.deleteClass',function()
{
//DELETE CODE HERE.
});
You can use this one instead:
$("#mytable").on("click",'.deleteClass',function() {
alert('row deleted');
});
So I have the following html
<li clas='k-item'>
<input type='checkbox'>
<span>ABC</span>
</li>
Is there any way I can bind click to only input and disable for span and li?
This is what I tried, but it doesn't seem to work
$('.k-item').on('click', function (e) {
$(this).unbind('click');
if ($(e.target).is('input')) {
$('input').bind('click');
}
});
I do not have much experience with jquery
You need to use:
$('.k-item input').click(function(){
//modify the rest handler code...
});
Update: if click is defined for li, and you don't want that to be triggered on child span then you will need to stop event propagation.
$('.k-item span').click(function(e){
e.stopPropagation();//do not trigger parent click on child span
});
Why not just target the input to begin with? You can then use e.stopPropagation() to prevent the LI from getting the click event (which is I gather your aim):
$('.k-item input').click(function (e) {
// Stop the LI from firing a click event
e.stopPropagation();
// input is clicked
});
You need only this:
$('.k-item').on('click', function (e) {
if ($(e.target).is('input')) {// or event.target.type
//do stuff
}
});
Just select the desired element and apply the event listener:
$('.k-item > input').on('click', function() { // ... });
I have a button inside a division.Both have separate onclick listeners.But since button is a part of the division,the event attached to button is also triggered when clicked.Is there a way to remove it?
i tried :not / .not.it dint work.
<div id="divson">
<button id="btn"></button>
</div>
$('#divson').not('#btn').click(function sayHello() {
alert('Helo!');
});
$('#btn').click(function sayJello() {
alert('Jelo!');
});
http://jsfiddle.net/gw3LqrcL/
Just return false; in your handler to stop the event propagation: http://jsfiddle.net/gw3LqrcL/1/
Use stopPropagation on the event passed in to the handler on #btn to stop the event bubbling to the parent element:
$('#divson').click(function () {
alert('Helo!');
});
$('#btn').click(function (e) {
e.stopPropagation();
alert('Jelo!');
});
Updated fiddle