Javascript - Highlight a column name when clicking on it only - javascript

I have a html table (with column names: T1, T2, T3). I want to highlight a column name (T1) ONLY when it is clicked on by the user, the rest of the column names don’t have a highlight (T2, T3). Then when the user clicks on another column name (T2), it is highlighted, but I want all the other column names to be reset with no highlight (T1, T3).
How can I do it using only javascript, css, and/or html? Please dont include JQuery, I cannot use it.

var elems = document.querySelectorAll('td');
var fnClick = function(){
var ie = document.querySelectorAll('td');
for(var x = 0; x < ie.length; x++){
elems[x].classList.remove("red");
}
this.classList.add("red");
}
for (var i = 0; i < elems.length; i++){
elems[i].addEventListener("click", fnClick);
}
.red { background-color: red; }
<table>
<tr>
<td>test</td>
<td>test</td>
<td>test</td>
</tr>
<tr>
<td>test</td>
<td>test</td>
<td>test</td>
</tr>
<tr>
<td>test</td>
<td>test</td>
<td>test</td>
</tr>
</table>

When clicking, iterate through all column names and remove the class, lets say, "highlight".
After that add the class "highlight" to the column name clicked.
Or, look for elements by class name "highlight", and remove the class from all of them, then proceed to add the class to the clicked element.

First of all add an unique class to all the column elements for example- T1 for T1, T2 for T2, etc.
Then create a css class "highlight" with appropriate background color to create the highlight effect.
Then within the tags write an onclick function call like <td class="T1" onclick="addHighlight(T1)">...</td>
After that you can use JavaScript to create a function 'addHighlight' which is triggered when the user clicks on a column element. Within that function you can use getElemenstbyClassname to access the elements with class name of the column that was clicked(you passed in the class name use it as a parameter) and addClass method to add the class highlight.
To remove the highlight effect once another column is clicked just search for elements with the class "highlights" and use removeClass to remove that class and thus the highlight effect.
Refer to w3schools.com for further guidance. All is clearly explained there :)

You can do this by styling the :focus pseudo class for your td elements. In order to make your td element focus-able you would have to set the tabindex attribute to your td elements as well.
Index.html
<html>
<head>
<title>
Table Highlight
</title>
<style>
table {
border: solid;
}
td {
width: 100px;
height: 100px;
border: dotted 1px;
}
td:focus {
background-color: blue;
}
</style>
</head>
<body>
<table>
<tr>
<td tabindex="1">T1</td>
<td tabindex="1">T2</td>
<td tabindex="1">T2</td>
</tr>
<tr>
<td>10</td>
<td>11</td>
<td>12</td>
</tr>
<tr>
<td>20</td>
<td>21</td>
<td>22</td>
</tr>
</table>
</body>
</html>
Here is a codepen as POC:
https://codepen.io/anon/pen/eKMgvJ
If you want to highlight the corresponding column name (table head element) of the clicked table cell, then you would need to add a click handler on your table.

Related

HTML - JS - multiple buttons that change css of table columns

I have a HTML document with a table in it
<table>
<tr>
<th class="street">Street</th>
<th class="city">City</th>
<th class="country">Country</th>
</tr>
<tr>
<td class="street">street-1</td>
<td class="city">city-1</td>
<td class="country">country-1</td>
</tr>
<tr>
<td class="street">street-2</td>
<td class="city">city-2</td>
<td class="country">country-2</td>
</tr>
</table>
Now I am looking for a way to implement buttons.
For example
<button id="button_street">TOGGLE STREET</button>
<button id="button_city">TOGGLE CITY</button>
<button id="button_country">TOGGLE COUNTRY</button>
If a button is pressed, the corresponding column in the table should be hidden.
Even better (than hidden) it would be if I could change the css design with the buttons.
My (temporary) solution is quite cumbersome...
It's a javascript solution that changes one class (visible) to another (hidden).
Spry.Utils.addLoadListener(function() {
let buttonToggle = document.getElementById('button_street');
buttonToggle.addEventListener('click', toggleClass);
function toggleClass() {
let collection = document.getElementsByClassName("street");
for (var i=0; i<collection.length; i++) {
collection[i].classList.toggle('street_design2');
}
}
}
This javascript must be repeated for each button.
where the css is the following:
.street {
background-color: blue;
}
.street_design2 {
background-color: red;
}
If I want to hide the "street-column" I can use display: none
I haven't found any other javascript solution to address all elements with class street. Maybe there is a better solution?
also it would be good if i could pass the function to an array like this:
const array = ["street", "city", "country"]
instead of repeating it for each button. Maybe there is a solution (a loop?)?
You can use document.querySelectorAll to address all elements with same tagName, class, etc, and then use .forEach() to add the EventListener to all elements at once for your case.
function toggleClass(collection) {
document.querySelectorAll('.' + collection).forEach(function(element) {
element.classList.toggle(collection + '_design2');
});
}
document.querySelectorAll('button').forEach(function(button) {
button.addEventListener('click', function(e) {
let collection = this.id.split('_').pop();
toggleClass(collection);
});
});
.street {
background-color: blue;
}
.street_design2 {
background-color: red;
}
.city_design2 {
background-color: yellow;
}
.country_design2 {
background-color: green;
}
<table>
<tr>
<th class="street">Street</th>
<th class="city">City</th>
<th class="country">Country</th>
</tr>
<tr>
<td class="street">street-1</td>
<td class="city">city-1</td>
<td class="country">country-1</td>
</tr>
<tr>
<td class="street">street-2</td>
<td class="city">city-2</td>
<td class="country">country-2</td>
</tr>
</table>
<button id="button_street">TOGGLE STREET</button>
<button id="button_city">TOGGLE CITY</button>
<button id="button_country">TOGGLE COUNTRY</button>
You can use the data property to specify which node to target. It will help in avoiding the name conflicts in the future and also callback will only execute for the specific button where data-table-toggle property is specified so it will avoid conflicts with other buttons.
Code will adds an event listener to all the buttons in a web page that have a custom data attribute "data-table-toggle". When the user clicks on one of these buttons, the tableToggle() function is executed.
The tableToggle() function first retrieves the value of the "data-table-toggle" attribute of the clicked button using this.getAttribute("data-table-toggle"). It then uses this value to select all the table rows that have a class attribute matching the value of the "data-table-toggle" attribute. This is done using the document.querySelectorAll() method with a CSS selector string that targets all the elements that have a child element with the specified class.
Finally, the function toggles the class of each selected table row between two different styles: the original class associated with the value of "data-table-toggle" attribute and a new class with "-_design2" appended to it. This is done using the classList.toggle() method.
Overall, this code dynamically modifies the styles of table rows based on the clicked button, allowing for a simple toggle effect.
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.2/axios.min.js" integrity="sha512-NCiXRSV460cHD9ClGDrTbTaw0muWUBf/zB/yLzJavRsPNUl9ODkUVmUHsZtKu17XknhsGlmyVoJxLg/ZQQEeGA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="script.js"></script>
<style>
table .street-_design2 {
display:none;
}
table .city-_design2 {
display:none;
}
table .country-_design2 {
display:none;
}
</style>
</head>
<body>
<table>
<tr>
<th class="street">Street</th>
<th class="city">City</th>
<th class="country">Country</th>
</tr>
<tr>
<td class="street">street-1</td>
<td class="city">city-1</td>
<td class="country">country-1</td>
</tr>
<tr>
<td class="street">street-2</td>
<td class="city">city-2</td>
<td class="country">country-2</td>
</tr>
</table>
<button data-table-toggle="street">TOGGLE STREET</button>
<button data-table-toggle="city">TOGGLE CITY</button>
<button data-table-toggle="country">TOGGLE COUNTRY</button>
</body>
window.onload = function () {
Array.from(document.querySelectorAll("button")).forEach(function (element) {
if (!element.getAttribute("data-table-toggle")) return;
element.addEventListener('click', tableToggle);
});
function tableToggle() {
const attribute = this.getAttribute("data-table-toggle");
Array.from(document.querySelectorAll(`tr .${attribute}`)).forEach(function (selector) {
selector.classList.toggle(`${attribute}-_design2`);
})
}
};

Element in div gets removed as a child but can't be used again

I am trying to display a hidden table in a div then hide it again with display: none/block toggle. It works. But, I can't get it to appear again once I toggle to display: none to hide it.
HTML:
The HTML has an empty div with id = tableContainer.
Next to it, I have a table with the names of animal families in each cell, along with a button. When the button is clicked, it takes the name of the animal family from that particular cell, finds the table of animal species with that name and switches from display: none to display:block and display it /inside the div. Then, if I click the button again, it toggles the display back to display: none.
When I click a button in another cell, it clears the div and displays the new table.
All good.
But, if I click a button that was previously used, the table that has now gone is no longer available.
I have gone through all sorts of hoops playing with removeChild and all that but no luck. I am currently using innerHTML to clear the div, but I'm missing something with the class name.
Console error says: tabletest2.html:523 Uncaught TypeError: Cannot read property 'classList' of null
at toggle (tabletest2.html:523)
at HTMLButtonElement.onclick (tabletest2.html:72)
So, it seems to me that it can't toggle any more because the table now no longer exists, or I may be wrong with that as I didn't delete the child element (I think).
<body>
<table>
<tbody>
<tr>
<td>Genus</td>
<td>Benthobatis
<button onclick="toggle(this, parentNode.firstChild)">Click me</button></td>
</tr>
<tr>
<td>Genus</td>
<td>Diplobatis
<button onclick="toggle(this, parentNode.firstChild)">Click me</button></td>
</tr>
</tbody>
</table>
<!-- <======== div display container here ================>-->
<div id="tableContainer"></div>
<table id="Benthobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th>Benthobatis</th>
</tr>
<tr>
<td>Benthobatis kreffti</td>
<td>Brazilian Blind Electric Ray</td>
</tr>
</tbody>
</table>
<!-- <==================================-->
<table id="Diplobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th> Diplobatis </th>
</tr>
<tr>
<td>Diplobatis colombiensis</td>
<td>Colombian electric ray</td>
</tr>
</tbody>
</table>
</body>
<script>
function toggle(ele, tableName) {
var myTableDisplayDiv = document.getElementById("tableContainer").childNodes;
if (myTableDisplayDiv.length != 0) {
document.getElementById("tableContainer").innerHTML = "";
}
var myTableName = tableName.textContent;
var myTable = document.getElementById(myTableName);
myTable.classList.toggle("hide");
document.getElementById("tableContainer").appendChild(
document.getElementById(myTableName)
);
}
</script>
<style>
.hide {
display: none;
}
Explanations
"Why are my tables deleted if I'm only changing display option, not removing the child node?".
This destroys everything within:
document.getElementById("tableContainer").innerHTML = "";
This moves the chosen table to #tableContainer:
document.getElementById("tableContainer").appendChild(
document.getElementById(myTableName)
So in three clicks there's nothing left. Of course this is if the table can be identified correctly which it wasn't. The .textContent of .parentNode.firstChild reference was lost because this refers to a global context not the button. This is why on-event attributes (among other various reasons) are discouraged. Although not a critical issue as the ones previously mentioned, you should seriously have some variations to the names:
tableName
myTableName
myTable
myTableDisplayDiv
tableContainer
I'm pretty sure this naming scheme did not facilitate debugging.
Solutions
Before you place a table into #tableContainer where it gets destroyed, make a copy with .cloneNode().
Remove the onclick attributes and either use onclick property (like in the demo) or .addEventListener().
Register an ancestor element of both buttons (i.e. tbody), from there both buttons can be clicked and easily isolated and referenced by using event.target.
Now the reference to the clicked button (event.target) can now be referenced:
var tableName = event.target.parentNode.firstChild.textContent
And then the table can finally be referenced:
var table = document.getElementById(tableName)
Demo
document.querySelector('tbody').onclick = toggle;
function toggle(event) {
var clicked = event.target;
if (clicked.tagName === 'BUTTON') {
var genus = clicked.parentNode.firstChild.textContent;
var table = document.querySelector('#' + genus);
var display = document.getElementById("display");
display.innerHTML = "";
var clone = table.cloneNode(true);
display.appendChild(clone);
clone.classList.toggle('hide');
}
}
.hide {
display: none;
}
<table>
<tbody>
<tr>
<td>Genus</td>
<td>Benthobatis
<button>Click me</button></td>
</tr>
<tr>
<td>Genus</td>
<td>Diplobatis
<button>Click me</button></td>
</tr>
</tbody>
</table>
<!-- <======== div display container here ================>-->
<div id="display"></div>
<table id="Benthobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th>Benthobatis</th>
</tr>
<tr>
<td>Benthobatis kreffti</td>
<td>Brazilian Blind Electric Ray</td>
</tr>
</tbody>
</table>
<!-- <==================================-->
<table id="Diplobatis" class="hide">
<tbody>
<tr>
<th>Genus</th>
<th> Diplobatis </th>
</tr>
<tr>
<td>Diplobatis colombiensis</td>
<td>Colombian electric ray</td>
</tr>
</tbody>
</table>
Your code is kind of complex to understand but if you just want to toggle the table, I think this is the best way.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.hide {
display: none;
}
</style>
</head>
<body>
<div class="table-container">
<button class="toggle-btn">Click me</button>
<table>
<tr>
<td>Genus</td>
<td>Benthobatis</td>
</tr>
<tr>
<td>Genus</td>
<td>Diplobatis</td>
</tr>
</table>
</div>
<script>
const table = document.querySelector('table'),
btn = document.querySelector('.toggle-btn');
btn.addEventListener("click", () => {
table.classList.toggle("hide")
})
</script>
</body>
</html>

Table with select/deselect and summarize option

I've created a table. Now I'm trying to have an onClick event add an option where I can click the squares inside the table to select them and click again to deselect them. At the end I wish to have it to display the total amount, by that I mean that it adds together the selected squars like a calculator would do.
<style>
table, td, th {
border: 1px solid black;
}
table {
border-collapse: collapse;
}
</style>
<table>
<tr>
<td bgcolor="b8cce4">Modell</td>
<td>Trend</td>
<td>Titanum</td>
<td>Familiepakke</td>
<td>Førerassistentpakke</td>
<td>Stilpakke</td>
<td>Final price</td>
</tr>
<tr>
<td bgcolor="b8cce4"><b>Kuga</b></td>
<td>401000</td>
<td>420000</td>
<td>1000</td>
<td>10200</td>
<td>9200</td>
<td>$</td>
</tr>
<tr>
<td bgcolor="b8cce4"><b>C-max</b></td>
<td>320000</td>
<td>335000</td>
<td>1000</td>
<td>9400</td>
<td>3600</td>
<td>$</td>
</tr>
<tr>
<td bgcolor="b8cce4"><b>Focus</b></td>
<td>255000</td>
<td>325000</td>
<td>900</td>
<td>12500</td>
<td>9000</td>
<td>$</td>
</tr>
<tr>
<td bgcolor="b8cce4"><b>Mondeo</b></td>
<td>281000</td>
<td>361000</td>
<td>1100</td>
<td>9900</td>
<td>7200</td>
<td>$</td>
</tr>
I'm trying to make it so that I can click on one of the slots, able to select multiple, and at the end it will display the total price for all selected options.
I'd suggest you add/remove a class to your TD's. The "selected" can then have a different background color.
If you're using jQuery, you can use something like this (not tested):
$('td').click(function() {
$(this).toggleClass('selected');
console.log($(this).text());
});
Now you can use the CSS class to indicate it is selected.
I've added a JSFiddle here:
https://jsfiddle.net/vhwLxhsg/
I hope this is what you are looking for :-)
UPDATE:
Added calc. for each row, as requested: https://jsfiddle.net/vhwLxhsg/2/
UPDATE 2:
Vanilla JS version: https://jsfiddle.net/vhwLxhsg/4/

Applying less generated css to all the html table except th elements

I have the following html code
<textarea name="mytextarea" id="mytextarea" rows="10" cols="50">
color:red;
.yellow {
color : yellow;
}
</textarea><br/>
<button id="mybutton">Parse</button><br/>
Content parsed : <br/>
<p id="parsedContent"></p>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>Ya</td>
<td class="yellow">Hey</td>
<td>Ho</td>
</tr>
<tr>
<th>2</th>
<td>11</td>
<td>100</td>
<td>27</td>
</tr>
<tr>
<th>3</th>
<td>sadd</td>
<td>zaa</td>
<td>ddd</td>
</tr>
</tbody>
</table>
This is used to generate some css via a user input and insert dynamically the css generated to the head of the document.
I use the folowing javascript code to generate the css with the lesscss parser:
$('#mybutton').on('click',function(){
content = 'table tbody {'+$('#mytextarea').val()+'}';
var parser = new(less.Parser);
parser.parse(content, function (err, tree) {
if (!err) {
if($('#headCss').length===0){
$('head').append('<style id="headCss"></style>');
}
css = tree.toCSS();
console.log(tree);
$('#headCss').text(css);
$('#parsedContent').text(css);
}else{
$('#parsedContent').text(err);
}
});
});
$('#mybutton').click();
I need to apply the css generated to the table but it should not be applied to the table head (column and rows).
Is there a way to do this with only pure css on the textarea (not less).
Here a jsfiddle with the code : http://jsfiddle.net/Jiwoks/Lkz0mhor/
In this exemple I don't want row headers to be red, only td elements.
Any help much appreciated
You can put this code in the js.
I just noticed that you used <th>s as the header, so the :not(:first-child) is not needed.
content = 'table tbody td {'+$('#mytextarea').val()+'}';
In the JS.
Now this code selects the tds, which prevents the .yellow class from having any effect, since it looks for an element inside the td with the .yellow class, rather than the td itself.
You can get around this by modifying the input:
color:red;
&.yellow {
color : yellow;
}
However, since you want only pure css in the textarea input, you can modify it inside the code instead. For example with this line:
content = content.replace(/^\./mg, '&.');
It replaces all dots at the start of a line with &.
http://jsfiddle.net/Lkz0mhor/3/

Multiple elements with same Id in Javascript

I have a case where a html file contains multiple elements with the same ID name.
The table row contains 5 columns of which I need to consider 2,3,4,5 columns data.
<tr id='total_row'>
<td>Total</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td> </td>
</tr>
I have the above code at several places in the file. I need to add the respective values using javascript.
An ID is unique in an html page. You can call it THE ID as well wrt a page. You cannot have same ID for two different tags in a single page. But you can use class instead of and ID. Know about it here
So your HTML can be like
<tr class='total_row'>
<td>Total</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td> </td>
</tr>
As an example with jquery you can do something like this,
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>
<table>
<tr class="one">
<td></td>
<td></td>
</tr>
<tr class="one">
<td></td>
<td></td>
</tr>
<tr class="one">
<td></td>
<td></td>
</tr>
</table>
<script src="jquery-1.11.0.min.js"></script>
<script>
$(document).ready(function() {
$(".one").eq(0).find('td').eq(0).html("I'm tracked");
// get 1st tr and get first td
$(".one").eq(1).find('td').eq(1).html("I'm tracked");
// get 2nd tr and get second td
$(".one").eq(2).find('td').eq(0).html("I'm tracked");
// get 3rd tr and get first td
});
</script>
</body>
</html>
But I guess this approach can be tedious.
Id should be unique and if you use the same id, javascript code refers only the first element. but if you still want to use same id than you may try the below code:
$(function(){
$('[id="total_row"]').each(function(){//run for every element having 'total_row' id
var $this = $(this);
$this.find('td').eq(1).text() //to get second column data
$this.find('td').eq(1).text('dummy text') //to set second column data
});
});
You can use XHTML:
<p id="foo" xml:id="bar">
Through XHTML you can apply similar ID to multiple Controls.
Similar questions can be found here:
http://www.c-sharpcorner.com/Forums/
While duplicate IDs are invalid, they are tolerated and can be worked around. They are really only an issue when using document.getElementById.
I'll guess that the table looks like:
<table id="t0">
<tr>
<td>-<th>count<th>Pass<td>Fail<td>Error<td>
<tr>
<td>-<td>1<td>1<td>0<td>0<td>
<tr>
<td>-<td>1<td>1<td>0<td>0<td>
<tr id='total_row'>
<td>Total<td><td><td><td><td>
<tr>
<td>-<td>1<td>1<td>0<td>0<td>
<tr>
<td>-<td>1<td><td>1<td>0<td>
<tr>
<td>-<td>1<td><td>0<td>1<td>
<tr id='total_row'>
<td>Total<td><td><td><td><td>
</table>
<button onclick="calcTotals();">Calc totals</button>
If that's correct, then a function to add each sub–section can be like:
function calcTotals(){
var table = document.getElementById('t0');
var rows = table.rows;
var row, totals = [0,0,0,0];
// For every row in the table (skipping the header row)
for (var i=1, iLen=rows.length; i<iLen; i++) {
row = rows[i];
// If it's a total row, write the totals and
// reset the totals array
if (row.id == 'total_row') {
for (var j=0, jLen=totals.length; j<jLen; j++) {
row.cells[j+1].innerHTML = totals[j];
totals[j] = 0;
}
// Otherwise, add values to the totals
} else {
for (var k=0, kLen=totals.length; k<kLen; k++) {
totals[k] += parseInt(row.cells[k + 1].innerHTML) || 0;
}
}
}
}
In addition to using classes, which works but feels kind of icky to me, one can also use data-* attributes.
<tr class='total_row' data-val-row-type="totals-row">
<td>Total</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td> </td>
</tr>
Then, in your script (jQuery syntax -- querySelectorAll has a similar syntax)
var $totalsRows = $("[data-val-row-type='totals-row']);
When you are in a team with a separate UI designer, this keeps the UI guy from ripping out and changing your class names to fix the new design layout and it makes it quite clear that you are using this value to identify the row, not just style it.

Categories