Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.
like image 240
Karl Avatar asked Aug 02 '15 10:08

Karl


3 Answers

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!");
 });
like image 198
micnil Avatar answered Oct 20 '22 17:10

micnil


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.

like image 37
Zakaria Acharki Avatar answered Oct 20 '22 18:10

Zakaria Acharki


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/

like image 2
Oleg Avatar answered Oct 20 '22 17:10

Oleg