After hitting ADD button I get yet another row. I need it's row class should be changed accordingly by identifying previous row's class. If previous row class name is odd then newly created class name should be even and so on. How do we do this by using javascript? How can we modify existing code to do this or any other suggestion?
Proper CSS file is ready for alternate class names. When I fetch data from database then alternate odd/even row will be created. But when I hit ADD button it always take first rows class name because there is a clone of first row always. I have no worries for cloned row except class name.
<script>
function addRow(tableID) {
var table = document.getElementById(tableID);
if (!table) return;
var newRow = table.rows[1].cloneNode(true);
// Now get the inputs and modify their names
var inputs = newRow.getElementsByTagName('input');
for (var i=0, iLen=inputs.length; i<iLen; i++) {
// Update inputs[i]
}
// Add the new row to the tBody (required for IE)
var tBody = table.tBodies[0];
tBody.insertBefore(newRow, tBody.lastChild);
}
</script>
<table id="table1" border=1 class="display">
<tr class="odd">
<th>Operator ID</th>
<th>Status</th>
</tr>
<tr class="odd">
<td>TestA</td>
<td>ActiveA</td>
</tr>
<tr class="even">
<td>TestB</td>
<td>ActiveB</td>
</tr>
</table>
<input type="button" value="ADDROW" onclick=addRow("table1"); />
Why not just use the proper CSS:
#table1 tr {
/* odd row styles */
/* also acts as fallback for really old browsers */
}
#table1 tr:nth-child(even) {
/* even row styles */
}
You can simply do something like this:
tr:nth-child(even) td {
background-color: #ccc;
}
tr:nth-child(odd) td {
background-color: #fff;
}
DEMO HERE
Related
I have following HTML code for an table:
<div id="table">
<table>
<thead>
<tr>
<th>Product</th>
<th>net</th>
<th class="green">VAT</th>
</tr>
</thead>
<tbody>
<tr>
<td class="red">Lipstick</td>
<td>€6.58</td>
<td>19</td>
</tr>
<tr>
<td class="red">Shoelaces</td>
<td>€7.34</td>
<td>19</td>
</tr>
<tr>
<td class="apple">Apple</td>
<td>0.43</td>
<td>7</td>
</tr>
</tbody>
</table>
</div>
The table is created with tableify.
Now i want to select a row with this function:
function selectedRow(){
var index,
table = document.getElementById("table");
for(var i = 1; i < table.rows.length; i++)
{
table.rows[i].onclick = function()
{
// remove the background from the previous selected row
if(typeof index !== "undefined"){
table.rows[index].classList.toggle("selected");
}
console.log(typeof index);
// get the selected row index
index = this.rowIndex;
// add class selected to the row
this.classList.toggle("selected");
console.log(typeof index);
};
}
}
selectedRow();
Here is the following CSS code so that the the background geht a color:
.selected{
background-color: brown;
color: #fff;
}
Normally should the row, that i selected turn brown, but i get a error, that length can't be read. If i have a normal table without and >tbody>, the code works.
How can i get the body so that can i read the length and the row?
Now that you updated the question you added a parent div to fetch the child table. So the selector in that case should be: #table > table
Here's a code that achieves that same result in a better way and using addEventListener instead of the onclick property.
Two strategies are shown to listen for the click event:
Having a click event handler for each row
Having a click event handler for the whole table
The first one just listen for the click event for any single row in the table and will check if the table has any selected row before attempting to toggle the class or if the clicked row is the one having the selected class.
The second has one listener for the click event on the table only. Since the event bubble starting from the exact child element clicked (a td for example) it will trigger anyway but it needs to make further checks to better target the context.
In the end...
I left the first strategy cabled with the logics and made it more narrow so that you can select any row at any moment and it will become the only selected row in the table
addClickEventToTableRows();
//adds a click event handler to the table
function addClickEventToTable(){
const table = document.querySelector("#table table");
table.addEventListener('click', tableOnClick);
}
//the click event handler for the table
function tableOnClick(event){
const clickedElement = event.target;
const hasTbodyAsParent = clickedElement.closest('tbody') !== null;
//if the child element clicked of the table, is a child of tbody
if ( hasTbodyAsParent ){
//the clickedrow taken with .closest (since clickedElement could be a td)
const clickedRow = clickedElement.closest('tr');
clickedRow.classList.toggle("selected");
clickedRow.closest('table').removeEventListener('click', tableOnClick);
}
}
//adds a click event handler to all the rows of the table
function addClickEventToTableRows(){
//the table element
const table = document.querySelector("#table table");
//foreach row element in the tbody of the currently selected table
table.querySelectorAll(':scope > tbody > tr')
.forEach(row => {
//add a click event listener to the current row
row.addEventListener('click', (event)=>{
//retrieves the clicked table row
const clickedRow = event.currentTarget;
console.log(`Row: ${clickedRow.rowIndex} was clicked`);
//if there's not any row in the table with the 'selected' class OR this row has the class selected
//if(!clickedRow.closest('tbody').querySelector('.selected') || clickedRow.classList.contains('selected'))
table.querySelectorAll(':scope > tbody > tr.selected').forEach(trSelected => {
trSelected.classList.remove('selected');
});
//toggle its selected class
clickedRow.classList.toggle("selected");
});
});
}
#table > table > tbody > tr{
cursor: pointer;
}
#table > table{
border-collapse: collapse;
}
#table > table > tbody td{
border: solid 1px lightgray;
padding: 1rem;
}
#table > table > thead th{
background: gray;
color: white;
font-weight: 600;
font-size: 1.5rem;
padding: .5rem;
}
.selected {
background-color: brown;
color: #fff;
}
<div id="table">
<table>
<thead>
<tr>
<th>Product</th>
<th>net</th>
<th class="green">VAT</th>
</tr>
</thead>
<tbody>
<tr>
<td class="red">Lipstick</td>
<td>€6.58</td>
<td>19</td>
</tr>
<tr>
<td class="red">Shoelaces</td>
<td>€7.34</td>
<td>19</td>
</tr>
<tr>
<td class="apple">Apple</td>
<td>0.43</td>
<td>7</td>
</tr>
</tbody>
</table>
</div>
As the title says, I'm looking to add a new column to a table that exists which you can see here: https://onetoso.com/PSOTesting/Shane/HTML/customCookieList.html
My blocker right now is the tr does not have a class name so I can't append to each row. I've created a new column header by doing:
This creates a new th so I need to generate the field underneath it as well for each respective row.
let newHead = document.createElement('th'); newHead.class = 'ot-table-header'; newHead.innerHTML = 'Description'; document.querySelector('tr').appendChild(newHead);
To add the necessary field I require to the table I have this:
let newRow = document.createElement('td'); newRow.class = 'ot-cookie-desc-td'; newRow.innerHTML = 'Example text'; document.querySelector('tbody tr').appendChild(newRow);
This will add 1 td that I require but how would I add to the additional rows that already exist since there is no way to specifically target those? I'm looking to copy the same format as the existing table.
This is a demo showing how to add a column to a table already existing in the dom.
The function addColumn(table, headerText, rowContents) given a table, the text of the header for the new column and column data contained by each row; just adds the new column to the table as specified by the args.
The demo calls such function inside the useCase() that gets triggered when the button gets clicked.
The table used was taken from the link included in your question but to be better focused I stripped off the details that were just adding noise.
It's worthwhile saying that there's no indicators in your tables to select them in a page holding multiple ones. So in absence of ids or a combination of css class that would make a non ambiguos selector, in my demo I just picked it with document.querySelector('table')
function useCase(){
const table = document.querySelector('table');
addColumn(table, 'newColumn', ['NewContentForRow1','NewContentForRow2']);
}
function addColumn(table, headerText, rowContents){
const newHeaderCol = document.createElement('th');
newHeaderCol.innerText = headerText;
table.querySelector('thead > tr:first-child').append(newHeaderCol);
const tableRows = table.querySelectorAll('tbody > tr');
let iRow = 0;
for(const tableRow of tableRows){
const newBodyCol = document.createElement('td');
newBodyCol.innerText = rowContents[iRow++];
tableRow.append(newBodyCol);
}
}
table, tr, th, td {
border: solid 1px black;
}
button{
margin-top: 1rem;
cursor: pointer;
}
<table>
<caption class="ot-scrn-rdr">Strictly Necessary Cookies</caption>
<thead>
<tr>
<th scope="col" class="ot-table-header ot-host">Cookie Subgroup</th>
<th scope="col" class="ot-table-header ot-cookies">Cookies</th>
<th scope="col" class="ot-table-header ot-cookies-type">Cookies used</th>
<th scope="col" class="ot-table-header ot-life-span">Lifespan</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row1[A]</td>
<td>Row1[B]</td>
<td>Row1[C]</td>
<td>Row1[D]</td>
</tr>
<tr>
<td>Row2[A]</td>
<td>Row2[B]</td>
<td>Row2[C]</td>
<td>Row2[D]</td>
</tr>
</tbody>
</table>
<button onclick="useCase();">Add Column</button>
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.
I'm using this answer to include a toggle that switches between two css classes: twotablecell and tablecell which are two different sized table headers cells which are different sizes in css.
When clicking on my button id: sizeTog, it changes the table headers class property to tablecell however does not change it back to twotablecell when clicking on it again.
$('#sizeTog').on('click', function() {
$('table thead tr .twotablecell').toggleClass("twotablecell tablecell");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th class="twotablecell">
Name
</th>
</tr>
</thead>
</table>
<input id="sizeTog" type="button" value="toggle size">
I've tried changing the element that needs to be toggled to: table thead tr th.twotablecell to make it more specific.
It only works accordingly when I change the Jquery toggled element to table thead tr th.
However, this is I have quite a few different table header columns which I want to be different sizes other than twotablecell and tablecell.
The problem is because on the second click the element you're looking for doesn't have the .twotablecell class any more - the first click removed it.
Select it by another means, using a different class which is not removed for example:
$('#sizeTog').on('click', function() {
$('table thead tr .headercell').toggleClass("twotablecell tablecell");
});
.tablecell { color: #C00; }
.twotablecell { color: #0C0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th class="headercell twotablecell">
Name
</th>
</tr>
</thead>
</table>
<input id="sizeTog" type="button" value="toggle size">
I am using PHP and MySQL to build an HTML table. I am trying to use JavaScript to filter/search the table and only display the rows with the results I need. I want the JavaScript input to search multiple <td>s of the table. I was able to get this to work, but it is not going to be an elegant solution to put in place with larger tables.
I am sure there is a better way to choose what is being searched, but have not been able to find anything. Does anybody know a way for me to make this code more flexible for varying column width tables?
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
td1 = tr[i].getElementsByTagName("td")[1];
if (td+td1) {
if ((td.innerHTML.toUpperCase().indexOf(filter)+td1.innerHTML.toUpperCase().indexOf(filter)) > -2) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search" title="Type in anything">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
There's a lot you can improve. Start by remembering to explicitly declare your variables, otherwise they become global.
This solution doesn't rely on any specific number of columns. It will work no matter how many there are.
See comments inline for more:
// Get DOM references just once:
var input = document.getElementById("myInput");
var table = document.getElementById("myTable");
// Do event binding in JavaScript, not HTML
input.addEventListener("keyup", filter);
input.addEventListener("search", filter);
// Get all rows, except the header and convert to array so .forEach() can be used to loop
var rows = Array.prototype.slice.call(table.querySelectorAll("tr:not(.header)"));
function filter() {
// Always trim user input
var filter = input.value.trim().toUpperCase();
// Loop the rows
rows.forEach(function(row) {
// You really don't need to know if the search criteria
// is in the first or second cell. You only need to know
// if it is in the row.
var data = "";
// Loop over all the cells in the current row and concatenate their text
Array.prototype.slice.call(row.getElementsByTagName("td")).forEach(function(r){
// Don't use .innerHTML unless there is HTML. Use textContent when there isn't.
data += r.textContent;
});
// Check the string for a match and show/hide row as needed
// Don't set individual styles. Add/remove classes instead
if(data.toUpperCase().indexOf(filter) > -1){
// show row
row.classList.remove("hidden");
} else {
// hide row
row.classList.add("hidden");
}
});
}
input[type=search]{
border-radius:10px;
outline:0;
padding:3px;
}
input[type=search]:focus{
box-shadow:0 0 4px blue;
}
.hidden { display:none; }
.leftHeader { width:60%; }
.rightHeader { width:40%; }
<!-- Use the actual "search" input type and don't do inline CSS or JavaScript -->
<input type="search" id="myInput" placeholder="Search" title="Type in anything">
<table id="myTable">
<tr class="header">
<th class="leftHeader">Name</th>
<th class="rightHeader">Country</th>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
All what you have to do is to get the td content and then match it with the search input.
function search(value) {
$('table tr').each(function () {
var content = $(this).find('td').text();
if (content.toUpperCase().includes(value.trim().toUpperCase())) {
$(this).show();
} else {
$(this).hide();
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<body>
<input type="search" placeholder="Search..." id="search_account" onkeyup="search(this.value)">
<table>
<tr>
<td>Cell1</td>
<td>Cell2</td>
<td>Cell3</td>
</tr>
<tr>
<td>Cell4</td>
<td>Cell5</td>
<td>Cell6</td>
</tr>
</table>
</body>
</html>