Reputation: 18747
Setup:
I have written a jQuery function to update table cells of table_2, when a row in table_1 is clicked. Here is what I have written:
<script type="text/javascript">
$("tr").live('click',function() {
var host = $(this);
alert('A row in table 1 is clicked!');
var count = host.find("td").eq(2).text();
$("#myTable_2 tr:eq(0) td:eq(1)").text(count);
$("#myTable_2 tr:eq(1) td:eq(1)").text(5);
});
</script>
The Problem:
When I step-through this function using FireBug, I can see the cell data in myTable_2 is being changed. BUT, for every click, the function is executed twice. I can see the alert box appearing twice for each click.
Can somebody tell me why does this happen? And how to avoid this?
Upvotes: 11
Views: 18614
Reputation: 3403
Some elements may have the same properties (class name, tag name ect.) wich you may overlook. This can cause such a conflict. In the example below the "tr" element is used as the selector for the alert, but the script has two nested "tr" elements that contain the "text" target. Thus, with a single click you get an alert fired for each (from inside out) "tr" element seperately. This is called bubbling. You could simply use stopPropogation() to stop the bubbling.
$("tr").live('click',function() {
alert('A row in table 1 is clicked!');
event.stopPropogation();
});
<table>
**<tr>**
<td>
<table id="myTable_1">
**<tr>**
<td>Test</td>
**</tr>**
</table>
</td>
**</tr>**
</table>
Upvotes: 0
Reputation: 1
It is because $("tr").live('click',function() {}); ^^^^^ has 2 counts in the html. To ensure .live () or .delegate() is executed once, the selector in $(selector).delegate() is better to be "$(table[name=users])" rather than $('td') or $('tr')
Upvotes: 0
Reputation: 2199
just simply avoid the propagation of the click
$("tr").live('click',function() {
...
$( event.toElement ).one('click', function(e){ e.stopImmediatePropagation(); } );
});
Upvotes: 12
Reputation: 348972
Either of the following:
To solve this, make your selector more specific. If you're using jQuery 1.7+, use .on
instead of live
: http://jsfiddle.net/6UmpY/3/
$(document).on("click", "#myTable_1 > tbody > tr", function() {
// This selector will only match direct rows of the myTable_1 table
Note: Using .on
instead of live
did not solve the problem.
Using a more specific selector did fix the issue.
If you love live
, the following would also work: http://jsfiddle.net/6UmpY/4/
$("#myTable_1 > tbody > tr").live("click", function() {
Upvotes: 11
Reputation: 87073
assume table_1
is the id of first table.
$("#table_1 tbody").on('click','tr', function() {
var host = $(this);
alert('A row in table 1 is clicked!');
var count = host.find("td").eq(2).text();
$("#myTable_2 tr:eq(0) td:eq(1)").text(count);
$("#myTable_2 tr:eq(1) td:eq(1)").text(5);
});
NOTE: live()
has been deprecated, so write like above. you code execute twice because tr
selector belongs to both tables and event bind twice.
You can also use delegate()
:
$("#table_1 tbody").delegate("tr", "click", function(){
var host = $(this);
alert('A row in table 1 is clicked!');
var count = host.find("td").eq(2).text();
$("#myTable_2 tr:eq(0) td:eq(1)").text(count);
$("#myTable_2 tr:eq(1) td:eq(1)").text(5);
});
Upvotes: 3