Reputation: 261
In my application, I have mulitple tables with the same class name to apply identical style.
I want to highlight a table row on click, removing previous row highlight, independant of each table. In other words clicking on one table row should not affect the highlighted row in the other table
Using the jquery code I now have, I am able to find the ID of the table whose row was clicked. But the code to remove and add the row highlight row based on the table ID does not work.
Here is the complete code:
<html>
<head>
<style>
.clickedrow {background-color: #caaf8f;}
.table-layout {
/*text-align: center;*/
border: 1px solid black;
border-collapse: collapse;
font-family:arial-narrow, helvetica, sans-serif;
font-weight:100;
font-size: 13px;
margin: 0 auto 0;
margin-bottom: 20px;
/*float:left;*/
height:100px;
overflow-x:auto;
white-space: nowrap;
}
.table-layout td, .table-layout th {
border: 1px solid grey;
padding: 3px 3px 0;
height: 20px;
line-height: 20px;
width:100px;
}
.table-layout td {
text-align: left;
background-color:#fff;
}
.table-layout th {
background-color:#eea647;
height: 22px;
line-height: 22px;
}
.selected {
color: black;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
$(document).ready(function(){
//Highlight clicked row
$('.table-layout').on('click', function(){
var clickedtableID = $(this).attr('ID');
$('#'+ clickedtableID + ' td').on('click', function(){
// Remove previous highlight class
$('tr').removeClass('clickedrow');
$(this).closest('tr').addClass("clickedrow");
});
});
});
</script>
</head>
<body>
<table id="itemtable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
<br/>
<table id="ordertable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
</body>
</html>
I am not able to figure out how to fix the issue. Can someone help me, please?
And here is the jsfiddle >> https://jsfiddle.net/g5eaLuxt/
Thank you and regards
Upvotes: 1
Views: 3349
Reputation: 253416
There were a few problems with your JS Fiddle:
.clickedrow
couldn't be applied because it was overridden by my more specific selectors that followed.To correct the code to function as you wanted it to, I'll amend your jQuery to the following:
$(document).ready(function() {
// here we bind the anonymous function as the event-handler
// for the 'click' event (as you were already doing):
$('.table-layout').on('click', function(e) {
// here we use the Event Object, to find the clicked element
// (using event.target) and convert it to a jQuery object by
// wrapping it in jQuery; we then use the closest() method
// to find the closest '<tr>' element:
let $row = $(e.target).closest('tr');
// here we find all elements in the document that have the
// class-name 'clickedrow', and we iterate over that collection
// (jQuery handles the iteration internally), and remove the
// 'clickedrow' class from each element using the removeClass()
// method:
$('.clickedrow').removeClass('clickedrow');
// we then access the cached $row (the <tr> element) and add
// the 'clickedrow' class-name to it, via the addClass() method:
$row.addClass('clickedrow');
});
});
$(document).ready(function() {
$('.table-layout').on('click', function(e) {
let $row = $(e.target).closest('tr');
$('.clickedrow').removeClass('clickedrow');
$row.addClass('clickedrow');
});
});
.table-layout {
border: 1px solid black;
border-collapse: collapse;
font-family: arial-narrow, helvetica, sans-serif;
font-weight: 100;
font-size: 13px;
margin: 0 auto 0;
margin-bottom: 20px;
height: 100px;
overflow-x: auto;
white-space: nowrap;
}
.table-layout td,
.table-layout th {
border: 1px solid grey;
padding: 3px 3px 0;
height: 20px;
line-height: 20px;
width: 100px;
}
.table-layout td {
text-align: left;
background-color: #fff;
}
.table-layout th {
background-color: #eea647;
height: 22px;
line-height: 22px;
}
.selected {
color: black;
}
.clickedrow td {
background-color: #caaf8f;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="itemtable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
<br />
<table id="ordertable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
It's worth noting that you really don't need to use jQuery for something so simple, to do the same in plain JavaScript is — while more verbose — as simple as:
// here, because I don't like typing all that much, I'm
// caching the document under the variable 'D':
const D = document,
// here we use document.querySelectorAll() to retrieve
// all elements with the class of 'table-layout':
tables = D.querySelectorAll('.table-layout'),
// here we use Arrow function syntax to define the
// toggleHighlight function; the 'e' in the parentheses
// is the Event Object, passed from the (later) use of
// EventTarget.addEventListener():
toggleHighlight = (e) => {
// within the function we retrieve all the elements
// matching the supplied CSS selector and, using
// NodeList.prototype.forEach() we iterate over
// that NodeList:
D.querySelectorAll('.clickedrow').forEach(
// 'el' is a reference to the current Node of the
// NodeList over which we're iterating;
// here we use the Element.classList API
// and its remove() method to remove the class-name
// passed into the method:
(el) => el.classList.remove('clickedrow')
);
// we then access the element that initially fired
// the click event, and use Element.closest() to navigate
// the DOM to find its ancestor <tr> element:
e.target.closest('tr')
// and again use the Element.classList API, this time
// with the add() method, to add the 'clickedrow' class to
// the found <tr> element:
.classList.add('clickedrow');
};
// here we iterate over the NodeList of elements found earlier,
// again using NodeList.prototype.forEach() and an Arrow function:
tables.forEach(
// 'table' is a reference to the current <table> element-node
// of the NodeList over which we're iterating:
(table)=>{
// here we use EventTarget.addEventListener() to bind the
// toggleHighlight() function (note the deliberate omission
// parentheses) as the event-handler for the 'click' event:
table.addEventListener('click', toggleHighlight)
});
const D = document,
tables = D.querySelectorAll('.table-layout'),
toggleHighlight = (e) => {
D.querySelectorAll('.clickedrow').forEach(
(el) => el.classList.remove('clickedrow')
);
e.target.closest('tr').classList.add('clickedrow');
};
tables.forEach(
(table)=>{
table.addEventListener('click', toggleHighlight)
});
.table-layout {
border: 1px solid black;
border-collapse: collapse;
font-family: arial-narrow, helvetica, sans-serif;
font-weight: 100;
font-size: 13px;
margin: 0 auto 0;
margin-bottom: 20px;
height: 100px;
overflow-x: auto;
white-space: nowrap;
}
.table-layout td,
.table-layout th {
border: 1px solid grey;
padding: 3px 3px 0;
height: 20px;
line-height: 20px;
width: 100px;
}
.table-layout td {
text-align: left;
background-color: #fff;
}
.table-layout th {
background-color: #eea647;
height: 22px;
line-height: 22px;
}
.selected {
color: black;
}
.clickedrow td {
background-color: #caaf8f;
}
<table id="itemtable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
<br />
<table id="ordertable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
References:
document.querySelectorAll()
.Element.classList
API.EventTarget.addEventListener()
.NodeList.prototype.forEach()
.addClass()
.closest()
.on()
.removeClass()
.Upvotes: 0
Reputation: 14312
You're nesting "click handlers, so the one for the td
wasn't getting triggered. Instead you need to:
table
of the clicked td
(so it doesn't change any other table) using closest()
find()
the row with the clickedrow
classtd
using parent()
This is the completed function:
$(document).ready(function() {
//Highlight clicked row
$('.table-layout td').on('click', function() {
// Remove previous highlight class
$(this).closest('table').find('tr.clickedrow').removeClass('clickedrow');
// add highlight to the parent tr of the clicked td
$(this).closest('tr').addClass("clickedrow");
});
});
Working Example:
$(document).ready(function() {
//Highlight clicked row
$('.table-layout td').on('click', function() {
// Remove previous highlight class
$(this).closest('table').find('tr.clickedrow').removeClass('clickedrow');
// add highlight to the parent tr of the clicked td
$(this).parent('tr').addClass("clickedrow");
});
});
.table-layout .clickedrow td{
background-color: #caaf8f;
}
.table-layout {
/*text-align: center;*/
border: 1px solid black;
border-collapse: collapse;
font-family: arial-narrow, helvetica, sans-serif;
font-weight: 100;
font-size: 13px;
margin: 0 auto 0;
margin-bottom: 20px;
/*float:left;*/
height: 100px;
overflow-x: auto;
white-space: nowrap;
}
.table-layout td,
.table-layout th {
border: 1px solid grey;
padding: 3px 3px 0;
height: 20px;
line-height: 20px;
width: 100px;
}
.table-layout td {
text-align: left;
background-color: #fff;
}
.table-layout th {
background-color: #eea647;
height: 22px;
line-height: 22px;
}
.selected {
color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="itemtable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
<br/>
<table id="ordertable" class="table-layout">
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
Note, you also need to change the CSS for the clickedrow
for it to work. You have CSS that sets the colour of .table-layout td
, so just using .clickedrow
as the selector is not specific enough - it will get overridden by the more specific selector.
The CSS selector needs to be more specific than the existing one, e.g.
.table-layout .clickedrow td{
background-color: #caaf8f;
}
Upvotes: 3