Getting the td that was clicked when a tr was clicked - javascript

Lets say I have a click event set up for all TRs, naturally each TR is filled with TDs, so when you click a TR you are also clicking a TD. Is there anyway to capture the TD (or its index) that was clicked as a result of a TR being clicked?
I thought perhaps something like this, but I'm not getting anything out of that.
$('tbody').on('click', 'tr', function(){
var thisEq = $(this+' td').index();
alert("thisEq: "+thisEq);
});

Demo
You can get the td using event.target
$('tbody').on('click', 'tr', function(e){
var thisEq = $(e.target).index();
alert("thisEq: "+thisEq);
});
Note : .index() gives 0 to n values, so you would get 0 for first td

Reverse the problem round - detect which td is clicked and detect the parent tr.
$('td').on('click', function(){
var tr = $(this).parent('tr');
alert(tr);
});
You could also do this through use of a delegated event handler. This one hooks onto each tr element but you could hook it onto the body as another submitter has just proposed
$('tr').on( 'click', 'td', function() {
...
});

Related

How to catch td index in Datatable?

I have datatable and trying to catch column+row index when user press on it:
$('#datatable tbody').on('click', 'tr', function(){
var eq = $(this).index();
console.log(eq);
});
So, I could catch index of row (tr) by this way. However, I need also column (td index) with it. Does anyone could advise some approach?
Here is an example of similar task, just from backside (when someone needs few catchers). I am not good enought in jquery to convert it to my trouble.
You can listen for td clicks and then get the indices of both the clicked td and it's parent tr:
$('#datatable tbody').on('click', 'td', function(){
var clicked_td = $(this);
var td_index = clicked_td.index();
var tr_index = clicked_td.parent().index();
console.log(td_index);
console.log(tr_index);
});

Using jQuery, how to have click event handler respond for selected table columns?

jQuery v1.11
Given an HTML table with 6 columns, I want the cells in the table in columns two, three, five and six to respond to click events. So if a user clicks on a cell in column one or four, the click event handler should not be called.
This prevents the event handler from being called when the user clicks in the first column:
$('#my-table').on('click', 'tbody td:not(:first-child)', function (e) {
alert("I've been clicked on!");
});
And his prevents the event handler from being called when the user clicks in column 4:
$('#my-table').on('click', 'tbody td:not(:nth-child(4))', function (e) {
alert("I've been clicked on!");
});
My question is, how do I modify the above so that the event handler is not called when a click occurs in either column one or four.
JSFiddle
Edit: #micnil answered my specific question and I will find knowing the pattern he suggested useful. However, #Oleg took the time to point out a better approach. Rather than binding the event handler to each cell, he suggested that I should bind an event handler to the table. In my case this proves to be better.
Using performance.now(), discussed here, I get the following results setting up the binding for a jQuery DataTable containing 1,000 rows in Chrome:
Binding the click event to cells took 0.14627581768183972 milliseconds.
Binding the click event to the table took 0.04619236347855349 milliseconds.
You can just put a coma inside the selector:
$('#my-table').on('click', 'tbody td:not(:nth-child(4), :first-child)', function (e) {
alert("I've been clicked on!");
});
I think the best choice in your case is to use the JQuery function index() that will give you the index of clicked td and you can do the condition you want based to the returned index, take a look at Your updated fiddle.
JS :
$('#my-table').on('click', 'tbody td', function () {
if($(this).index() < 4){ //click in td between 1 and 4
alert('td between 1 and 4 clicked');
}else{ //click in another td
alert('td between 5 and 6 clicked');
}
});
Hope that help.
It's important to understand, that the code like $('#my-table').on('click', 'tbody td:not(:first-child)', function (e) {...}); creates first jQuery wrapper with all <td> element which corresponds 'tbody td:not(:first-child)' selector and then bind the event handler separately to every from DOM elements in jQuery object.
I would recommend you to choose another way. You can make one binding of click on the whole <table>. The event bubbling will forward the click on the cell to the parent <tr> and later to the <table>. It's important that e.target get your the clicked <td>.
So the code could be the following:
var columnIndexesIgnore = [0, 3];
$('#my-table').on('click', function (e) {
var $td = $(e.target).closest("td"); // e.target can be <span> instead of <td>
if ($td.length > 0 && $.inArray($td[0].cellIndex, columnIndexesIgnore) < 0) {
// cellIndex is 0-based index. We display in alert 1-based column index
alert("I've been clicked on column " + ($td[0].cellIndex + 1) + "!");
}
});
I used cellIndex property of DOM of <td>. It's 0-based index of column of the <td> element. So you need ignore clicks if $td[0].cellIndex is 0 or 3.
See your demo after the modification: http://jsfiddle.net/OlegKi/spckrjvf/5/
You can check the desired condition by doing this.
$('td').click(function () {
var col = $(this).parent().children().index($(this));
var row = $(this).parent().parent().children().index($(this).parent());
if (col == 3 || col == 0) {
alert("I have clicked on column " + col);
} else {
alert("I have clicked on another column");
}
});

Get the value from a particular column

I'm trying to alert message on click each column. I have a table in which three row and four column, now I want alert message with next column value on third column click of each table. I have tried this but all column get value not a particular column. my problem is this is invoke in every column click but I want alert message only when third column click of each row.
HTML
<table id='myTable'>
<tr><td>R1C1</td><td>R1C2</td><td>R1C3</td><td>R1C4</td></tr>
<tr><td>R2C1</td><td>R2C2</td><td>R2C3</td><td>R2C4</td></tr>
<tr><td>R3C1</td><td>R3C2</td><td>R3C3</td><td>R3C4</td></tr>
</table>
JS
$("#myTable tr").bind("click", function () {
alert($(this).children("td").eq(3).html());
});
Demo Here
please try this code
$(document).ready(function () {
$('#myTable tr').each(function (Mindex, Mval) {
$(Mval).find('td:eq(2)').click(function () {
alert($(Mval).find('td:eq(3)').html());
});
});
Try this
$('table#myTable tr td:nth-child(3)').on('click', function() {
alert($(this).next().html());
});
Check Here
$("#myTable tr td:nth-child(3)").click(function () {
alert($(this).next().html());
});
Try this:
$('#myTable').children('tr').children('td').eq(3).on('click', function() {
alert($(this).next().html());
});
The above function makes sure that you are calling the direct children elements but not any nested other same elements. Solves future regressions.
If your table is going to stay the same size there are answers that already work. If your table is going to grow I would recommend doing some event delegation. It will dramatically speed up the page if there are going to be a large number of event listeners.
$('#myTable').on('click', 'td:nth-child(3)', function(){
alert($(this).text());
});
See this jsfiddle, and this jquery documentation.
below code will find and set the desired column value
$('#myTable tr:gt(0)').each(function(){
// console.log($('td:eq(3)', $(this)).html());
alert($('td:eq(3)', $(this)).html());
$('#myTable').find('tr:gt(0)').find('td:eq(3)').html("hello");
});
Try this:
var thirdEle = $("#myTable tr td:nth-child(3)");
thirdEle.bind("click", function () {
alert($(this).html());
});

jquery trigger table row click event

Sample Code:
<table class="grid">
<tr>
<td>click me </td>
<td class="unitNumber"><span>Unit 1</span></td>
<td class="unitStatus">Open</td>
</tr><tr>
<td class="unitNumber"><span>Unit 2</span></td>
<td class="unitStatus">Sold</td>
</tr>
</table>
I am able to get the row index of the row selected to get the exact column data.
tr = $('.grid').find('tr');
tr.bind('click', function(event) {
unitNo = $(this).find("td.unitNumber span").html();
alert(unitNo);
});
The above tr click event is fine.
My problem now is how to trigger this tr binding event when clicking the anchor link <td>Show map </td>within the table row?
Goal:
To get first the unitNo (processed on tr.bind click event) before processing the rest of the code on anchored link?
I tried to duplicate the tr click function within the anchor link click event but got undefined value on unitNo. See my code:
$('a[id^="unit_floor_plan_preview"]').bind('click',function() {
var tr = $('.grid').find('tr');
unitNo = $(this).find("td.unitNumber span").html();
alert('From link: ' + unitNo);
});
test code:
http://jsfiddle.net/VjkML/29/
Change:
unitNo = tr.find("td.unitNumber span").html();
To:
unitNo = $(this).find("td.unitNumber span").html();
In $('a[id^="unit_floor_plan_preview"]').bind('click' You try to find "td.unitNumber span" within $(this). The problem is, this refers to the link clicked on, thus you'll never find anything!
FYI, you could easily rewrite that ENTIRE statement as follows:
$(document).on("click", '.grid tr, a[id^="unit_floor_plan_preview"]', function(e) {
e.stopPropagation(); // will prevent double click events from link being clicked within row
var unitNo = $.trim($(this).closest("tr").find(".unitNumber span").text()); // trim to remove end space, closest gets closest parent of selected type
if (e.target.tagName == "A") alert('From link: ' + unitNo);
else alert(unitNo);
});
Example
The best way is to bind the event only to your tr and use the event.target to check if it is tr or any other element that was clicked. This way your click event will not be duplicated.
This should work
var unitNo;
var tr;
tr = $('.grid').find('tr');
tr.bind('click', function (event) {
if ($(event.target).is('tr')) {
// If it is a tr that is clicked then just use find
unitNo = $(this).find("td.unitNumber span").html();
} else {
// If not tr find the closest tr and then find the element
unitNo = $(this).closest('tr').find("td.unitNumber span").html();
}
alert(unitNo);
});
Check Fiddle
Try:
var unitNo;
var tr = $('.grid').find('tr');
$('a[id^="unit_floor_plan_preview"]').on('click',function(e) {
e.stopPropagation();
unitNo = $(this).closest('tr').find("td.unitNumber span").html();
alert('From link: ' + unitNo);
});
tr.on('click', function(event) {
unitNo = $(this).find("td.unitNumber span").html();
alert(unitNo);
});
jsFiddle example
With the link you need to go up the DOM to the row (via .closest()), then use .find() to go back down the same row to find the span you want to get the Unit value.

How can I add a "selected" class to just one row of a table when a row is clicked?

I am using the following code:
$("#dataTable tbody").on("click", "tr", function (event) {
if (!$(this).hasClass('row_selected')) {
$(oTable.fnSettings().aoData).each(function () {
$(this.nTr).removeClass('row_selected');
});
$(this).addClass('row_selected');
gridClickHandler($(this));
}
});
When a row is clicked then if the row is already selected nothing happens. If not then all the rows have the class removed and the current row has the row_selected class added.
However this is slow as my tables have many rows. It does not look good with the current delay. What I thought of was moving the addClass to the start. But if I do that the the .each loop removes it.
Is there a way I could make this work more efficiently (faster response)?
<table id-"dataTable">
<tbody>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
</tr>
</tbody>
</table>
Here's a sample
$('table').on('click', 'tr', function() {
var row = $(this); //cache the row
if(!row.hasClass('selected'){
row.addClass('selected') //add class to clicked row
.siblings() //get the other rows
.removeClass('selected'); //remove their classes
gridClickHandler(row);
}
});​
The advantage of using .on() is that it binds only one event handler to the parent (in this case, table) for the children (the tr). Using .click() on each row means there is one handler for each tr element which is an overhead.
So for example, if I had a thousand rows, there would be a thousand click handlers when you use .click() as opposed to only click handler on the table to listen for all the tr's click events when using .on().
Try this:-
$("#dataTable tbody tr").on("click", "tr", function (event) {
$("#dataTable tbody tr").removeClass('row_selected');
$(this).addClass('row_selected');
}
});
$("#dataTable tbody tr").click(function () {
$('#dataTable tbody tr.selected').removeClass('selected');
$(this).addClass('selected');
gridClickHandler($(this));
});
Check this jsfiddle, works quite fast even with big tables!
-- edited after comment --
$("#dataTable").on("click", "tr", function (e) {
var $this = $(this);
// this line removes all selected classes from the rows siblings
$this.siblings().removeClass("row_selected");
// this line will toggle the selected class,
// therefore deselecting the row if it has been selected before
$this.toggleClass("row_selected");
gridClickHandler($this);
});
Or alternatively cache the previously selected row.
(function() {
var $oldSelected = null;
$("#dataTable").on("click", "tr", function (e) {
var $this = $(this);
// this line removes all selected classes from the rows siblings
$oldSelected.removeClass("row_selected");
// this line will toggle the selected class,
// therefore deselecting the row if it has been selected before
$oldSelected = $this.addClass("row_selected");
gridClickHandler($this);
});
})();
And as a side note, caching jQuery calls - or result of a function call that you need repeatedly for that matter - is always a good idea to save on processing time.

Categories

Resources