简体   繁体   中英

change color table row if button clicked

I want to change the color of the table row when the button is clicked. but I have a problem with the code. when I click the button, the color of the table row does not change.

CSS :

tr.highlighted td {
    background: red;
}

HTML :

<table id="data" border="1" cellspacing="1" width="500">
    <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
    </tr>
    <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
    </tr>
    <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
    </tr>
    <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
    </tr>
</table>
<button type="button" id="change">
Change
</button>

JQuery :

$('#data tr').click(function(e) {
        $('#change').click(function() {
        $('#data tr').removeClass('highlighted');
        $(this).addClass('highlighted');
    })
});

Update

Demo 2 and Demo 3 added. One of the demos behaves as the OP commented hopefully.

  • Demo 2: The <tr> are selected by click then highlighted by clicking the button.

  • Demo 3: Same as Demo 2 except only one row can be highlighted at a time.


Delegate the click event on document object. Any click to the document (which is basically the whole page) will be detected -- this of course is not desirable.

`$(document).on("click',...`

Delegating what actually reacts to the click and what doesn't is the goal of the programming pattern called Event Delegation. jQuery provides an optional second parameter referred to as a data object in any event method signature. This parameter is basically a selector string that specifies the scope of $(this) :

`$(document).on("click', '#data td, #change', ...

So the example above delegates the click event exclusively to any <td> within #data OR #change . Clicks anywhere other than to the delegated elements is ignored (unless there's another click event handler down the line). The last parameter is the callback function that will be invoked when triggered by a click event on any <td> of #data or #change . The callback function uses $(this) and flow controls to delegate the click event and determine behavior (or outcome). In the demo it is basically .toggleClass() method that .addClass() to target <tr>(s) without the .highlighted class and inversely .removeClass() to target <tr>(s) that already has the .highlighted class.

Further details commented in demo.

Click any <td> directly and its parent <tr> class .highlighted is toggled.

Click the button and all .highlighted classes on all <tr> are toggled.

Demo 1

Click either the <tr> or button to highlight <tr>

 /* Delegate click event on document -- Consider clicks only on #data td or #change */ /* if the clicked tag is a <td>... get the .closest <tr> from that <td> and add .highlighted class if it doesn't have it otherwise remove .highlighted */ /* ...otherwise get all <tr> and toggle the .highlighted class */ $(document).on('click', '#data td, #change', function(e) { if ($(this).is('td')) { $(this).closest('tr').toggleClass('highlighted'); } else { $('#data tr').toggleClass('highlighted'); } });
 tr.highlighted td { background: red; }
 <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change"> Change </button> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Demo 2

Click <tr> to select/deselect then click button to highlight all selected <tr> .

 $(document).on('click', '#data td, #change', function(e) { if ($(this).is('td')) { $(this).closest('tr').toggleClass('selected'); } else { $('#data tr:not(.selected)').removeClass('highlighted'); $('#data tr.selected').addClass('highlighted'); } });
 tr.highlighted td { background: red; }
 <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change"> Change </button> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Demo 3

The last <tr> clicked is selected and then highlighted when button is clicked

 $(document).on('click', '#data td, #change', function(e) { if ($(this).is('td')) { $('#data tr').removeClass('selected'); $(this).closest('tr').addClass('selected'); } else { $('#data tr').removeClass('highlighted'); $('.selected').addClass('highlighted'); } });
 tr.highlighted td { background: red; }
 <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change"> Change </button> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

The nested click handler have no sense here. Instead you can add a particular class, lets call it active to the last clicked row to keep track of it. After that, when you click the change button, you can first remove the highlighted class from every row and then add it to the row that hold the active class:

 $('#data tr').click(function(e) { $('#data tr').removeClass('active'); $(this).addClass('active'); }); $('#change').click(function() { $('#data tr').removeClass('highlighted'); $("tr.active").addClass('highlighted'); });
 tr.highlighted td { background: red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change">Change</button>

You can do:

 const $dataTr = $('#data tr'); const $change = $('#change'); let $toBeChanged = null; $dataTr.click(function() { $toBeChanged = $(this); $change.prop('disabled', false); }); $change.click(function() { $dataTr.removeClass('highlighted'); $toBeChanged.addClass('highlighted'); })
 tr.highlighted td { background: red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"> </script> <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change" disabled> Change </button>

The this in $(this).addClass('highlighted'); refers to the button, not the table row, since this will be set to whatever raised to event to trigger the callback function to execute, in this case, the element with the id change . One of the easiest ways to fix this would be to assign this to another variable before you do $('#change').click(function() {...}) .

Otherwise, if you want to make sure that only one table row is being changed at a time, you should separate the ('#data tr').click(function(e) {...}) and $('#change').click(function() {...}) so that they are not nested, have a variable outside both that keeps track of which row was last clicked, and read that variable whenever $('#change').click() is raised (instead of capturing which table row was clicked when you register the callback).

You can use index and eq method of jquery. Remove the nested click . First on click of the table row get the index of the row in the table using index . The value start from 0 . Set this value to a variable. Then use on click of the button use eq to get the table row and add class to it

 let getRowIndex; let elem = $('#data tr'); elem.click(function(e) { getRowIndex = $(this).index() }); $('#change').click(function() { if (getRowIndex !== undefined) { elem.removeClass('highlighted'); elem.eq(getRowIndex).addClass('highlighted'); } })
 tr.highlighted td { background: red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change"> Change </button>

 $(document).ready(function(){ $('#data tr').click(function(e) { if($(this).attr("class") == 'highlighted'){ $(this).removeClass('highlighted'); }else{ $(this).addClass('highlighted'); } }); })
 tr.highlighted td { background: red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script> <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change"> Change </button>

You are attaching click event to table tr's and then inside the callback function you are attaching a click event to your button . Within the button click callback your $(this) will refer to your button and not clicked tr. Instead add the classes to clicked tr itself.

 $('#data tr').click(function(e) { $('#data tr').removeClass('highlighted'); $(this).addClass('highlighted'); });
 .highlighted { background: red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table id="data" border="1" cellspacing="1" width="500"> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </table> <button type="button" id="change">Change</button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM