Apply CSS "stripe" effect to dynamically-inserted table rows in JavaScript - javascript

I have made a table. In that, when I click on button, a row is added. I want to assign alternate color to the row inserted.
$("#new-row").click(function() {
$('#first').clone(true).insertAfter('#demo tbody>tr:last');
if ($('#demo tr:last').hasClass("lgrey")) {
$('#demo tr:last').removeClass("lgrey");
$('#demo tr:last').addClass("dgrey");
} else if ($('#demo tr:last').hasClass("dgrey")) {
$('#demo tr:last').removeClass("dgrey");
$('#demo tr:last').addClass("lgrey");
};
});
.lgrey {
background-color: #eee;
}
.dgrey {
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="demo">
<tr>
<th>H1</th>
<th>H2</th>
<th>H3</th>
</tr>
<tr class="lgrey" id="first">
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
<button id="new-row">ADD ROW</button>
But running this code does not give desired result.
Please help in assigning an alternate color to inserted rows.

You don't need JavaScript for this . . . use the :nth-child(an+b) selector instead. This approach is much clearer than messing around with unnecessary classes and jQuery code.
Replace the .lgrey and .dgrey selectors with #demo tr:nth-child(2n+2), and #demo tr:nth-child(2n+3), respectively.
(Note that using even and odd, as some others have suggested, will not allow you to leave the header row unstyled.)
$('#new-row').click(function () {
$('#first').clone(true).insertAfter('#demo tr:last')
})
#demo tr:nth-child(2n+2) {
background-color: #eee;
}
#demo tr:nth-child(2n+3) {
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="demo">
<tr>
<th>H1</th>
<th>H2</th>
<th>H3</th>
</tr>
<tr id="first">
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
<button id="new-row">ADD ROW</button>

Use tr:nth-child css property like:
tr:nth-child(even) {
background-color: #004400;
}
tr:nth-child(odd) {
background-color: #000000;
}
It will handle the alternate color for each tr either generated static or dynamic.

You should really use CSS's nth-child(even) and nth-child(even)for this.
$("#new-row").click(function() {
$('#first').clone(true).insertAfter('#demo tbody>tr:last');
});
tr:nth-child(even) {
background-color: #eee;
}
tr:nth-child(odd) {
background-color: #ccc;;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="demo">
<tr>
<th>H1</th>
<th>H2</th>
<th>H3</th>
</tr>
<tr class="lgrey" id="first">
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
<button id="new-row">ADD ROW</button>

Use css to handle alternate row colors
tr:nth-child(even) {
background-color: #eee;
}
tr:nth-child(even) {
background-color: #ccc;
}
DEMO

I select row color before add new row as following:
$("#new-row").click(function() {
if ($('#demo tr:last').hasClass("lgrey")) {
var add = "dgrey";
var remove = "lgrey";
} else if ($('#demo tr:last').hasClass("dgrey")) {
var add = "lgrey";
var remove = "dgrey";
};
$('#first').clone(true).insertAfter('#demo tbody>tr:last');
$('#demo tr:last').removeClass(remove);
$('#demo tr:last').addClass(add);
});
.lgrey {
background-color: #eee;
}
.dgrey {
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="demo">
<tr>
<th>H1</th>
<th>H2</th>
<th>H3</th>
</tr>
<tr class="lgrey" id="first">
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</table>
<button id="new-row">ADD ROW</button>

Related

Call Function on Tabel Row Hover

I want to call a function that prints the contents of a row every time I hover over it in a table. So far I have this:
function tablemouseover(event) {
console.log(event.target);
}
<table>
<tr onmouseover='tablemouseover(event)'>
<td>times[row]</td>
<td>locations[row][0]</td>
<td>locations[row][1]</td>
<td>AllDistances[row]m</td>
</tr>
</table>
However this just gets me <td> I am hovered over.
You can get the text of the cell by calling textContent. If you want the col/row indices, you can get them by grabbing the positional index of the element within it's row or table (body).
const getChildIndex = node =>
Array.prototype.indexOf.call(node.parentNode.children, node);
function tablemouseover(event) {
const
row = event.currentTarget,
col = event.target,
rowIndex = getChildIndex(row),
colIndex = getChildIndex(col),
allText = [...row.children].map(td => td.textContent);
console.log(`Cell (${colIndex}, ${rowIndex}): ${event.target.textContent}`);
console.log(`Row [${rowIndex}]: ${JSON.stringify(allText)}`);
}
table, th, td { border: thin solid grey; }
table { border-collapse: collapse; }
th, td { padding: 0.5em; }
.as-console-wrapper { max-height: 5.25em !important; }
<table>
<tr onmouseover='tablemouseover(event)'>
<td>times[row]</td>
<td>locations[row][0]</td>
<td>locations[row][1]</td>
<td>AllDistances[row]m</td>
</tr>
<tr onmouseover='tablemouseover(event)'>
<td>times[row]</td>
<td>locations[row][0]</td>
<td>locations[row][1]</td>
<td>AllDistances[row]m</td>
</tr>
</table>
Use closest('tr') to search up the DOM tree for the closest tr parent and then log its innerHTML like so:
function tablemouseover(event){
console.log(event.target.closest('tr').innerHTML);
}
<table>
<tr onmouseover='tablemouseover(event)'>
<td>times[row]</td>
<td>locations[row][0]</td>
<td>locations[row][1]</td>
<td>AllDistances[row]m</td>
</tr>
</table>
Use onmouseenter not onmouseover
Read what different between
function tablemouseover(event){
console.log(event.target.innerHTML);
}
<table>
<tr onmouseenter ='tablemouseover(event)'>
<td>times[row]</td>
<td>locations[row][0]</td>
<td>locations[row][1]</td>
<td>AllDistances[row]m</td>
</tr>
</table>

How to hide/show element via JS?

I want to show the the table "trackdata" and hide "notrackdata" table whenever I click the button. As of now the table "notrackdata" hides but "trackdata" doesn't show.
HTML
<button class="far fa-file-audio fa-3x" id = "audiotrack" onclick = "searchtrack()"></button>
<table style = "width:90%" class = "notrackdata" id = "notrackdata"> //NOTRACKDATA
<tr>
<th>NO TRACK DATA TO SHOW<br><img class = "fas fa-sad-tear fa-2x" id ="tear"></th>
</tr>
</table>
<table style = "width:90%" class = "trackdata" id ="trackdata"> //TRACKDATA
<th >
<tr class = "trackrow">
<td>Album Cover</td>
<td>Album Title</td>
<td>Artist</td>
<td>Track Preview</td>
</tr>
</th>
<tbody>
<tr>
<td><img src ="https:\/\/e-cdns-images.dzcdn.net\/images\/artist\/72f073a5829b368025b49c460b4b1918\/250x250-000000-80-0-0.jpg" id = "imageBox"></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
JS
function searchtrack(){
var input = document.getElementById("userinput").value;
document.getElementById("trackdata").style.display = "display"; //Display trackdata
document.getElementById("notrackdata").style.display = "none"; //Hide notrackdata
}
CSS
.trackdata{
background-color: #DCDCDC;
margin:auto;
margin-top:1%;
text-align: center;
}
If I use display ="block"; and display = "inline-block I lose the CSS stylings. How can I make sure to keep the stylings while displaying the table as block or inline-block?
The value display is not supported for the property display. When you want to show the element, you should use the value block instead.
You can read more about the accepted values here.
function searchtrack(){
var input = document.getElementById("userinput").value;
document.getElementById("trackdata").style.display = "block"; //Display trackdata
document.getElementById("notrackdata").style.display = "none"; //Hide notrackdata
}
Create a class and add it to trackdata. On click add this class to notrackdata and remove from trackdata
function searchtrack() {
//var input = document.getElementById("userinput").value;
document.getElementById("trackdata").classList.remove('hide')
document.getElementById("notrackdata").classList.add('hide')
}
.hide {
display: none;
}
table {
border: 1px solid green;
}
<button class="far fa-file-audio fa-3x" id="audiotrack" onclick="searchtrack()">Hide</button>
<table style="width:90%" class="notrackdata" id="notrackdata"> //NOTRACKDATA
<tr>
<th>NO TRACK DATA TO SHOW<br><img class="fas fa-sad-tear fa-2x" id="tear"></th>
</tr>
</table>
<table style="width:90%" class="trackdata" id="trackdata"> //TRACKDATA
<th>
<tr class="trackrow hide">
<td>Album Cover</td>
<td>Album Title</td>
<td>Artist</td>
<td>Track Preview</td>
</tr>
</th>
<tbody>
<tr>
<td><img src="https:\/\/e-cdns-images.dzcdn.net\/images\/artist\/72f073a5829b368025b49c460b4b1918\/250x250-000000-80-0-0.jpg" id="imageBox"></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
JS
display = “block” not “display” for including the element in the DOM.
The display attribute takes 'block', 'inline', 'inline-block', or 'none' as values. If you change display="display" to display="block" you will see your element.
Display property should be set to "block" and not "display".
Try using this to show and hide the table: (click the button to toggle)
<button class="far fa-file-audio fa-3x" id = "audiotrack" onclick="myFunction()">Show/hide</button>
<div id="myDIV">
<table style = "width:90%" class = "notrackdata" id = "notrackdata"> //NOTRACKDATA
<tr>
<th>NO TRACK DATA TO SHOW<br><img class = "fas fa-sad-tear fa-2x" id ="tear"></th>
</tr>
</table><br>
<table style = "width:90%" class = "trackdata" id ="trackdata"> //TRACKDATA
<th >
<tr class = "trackrow">
<td>Album Cover</td>
<td>Album Title</td>
<td>Artist</td>
<td>Track Preview</td>
</tr>
</th>
<tbody>
<tr>
<td><img src ="https:\/\/e-cdns-images.dzcdn.net\/images\/artist\/72f073a5829b368025b49c460b4b1918\/250x250-000000-80-0-0.jpg" id = "imageBox"></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<style>
#myDIV {
width: 100%;
text-align: center;
margin-top: 20px;
}
</style>
<script>
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
<style>
.hide {
display: none;
}
table {
border: 1px solid green;
}
</style>
Display property is used to hide/show elements.You have used "display" as a property value.Use "block" instead of "display"
Change it to this
document.getElementById("trackdata").style.display = "block";
So final Js code will be like this:-
function searchtrack()
{
var input = document.getElementById("userinput").value;
document.getElementById("trackdata").style.display = "block"; //Display trackdata
document.getElementById("notrackdata").style.display = "none"; //Hide notrackdata
}
For more info - Hide/show element

Formatting HTML print

I'm trying to have a report, that has a table, whcih could be occupying multiple pages.
In the table footer I need to have the some of all, i.e. I need single table footer to appear once, only at end of the report, not at end of each page.
[If any one can help how to get subtotals at end of each page will be deeply appreciated].
I wrote the below code, which also is loaded here.
The output is as below, whic is buggy.
HTML body:
<body>
<h1>My page</h1>
<button onclick="printContent('t')">Print Content</button>
<div id="t">
<div class="divHeader">Header</div>
<br><br>
<table>
<thead>
<tr>
<th>First Heading</th>
<th>Second Heading</th>
<th>Third Heading</th>
</tr>
</thead>
<tbody>
!-- so many rows of: --!
<tr>
<td>Green</td>
<td>Yellow</td>
<td>Orange</td>
</tr>
</tbody>
<tfoot id="table_footer">
<TR> <TH ALIGN=LEFT COLSPAN=2>Total</TH> <TH>4923</TH> </TR>
</tfoot>
</table>
<br><br>
<div class="divFooter">Footer</div>
</div>
</body>
javascript for printing the required element:
<script language="javascript">
function printContent(el){
var restorepage = document.body.innerHTML;
var printcontent = document.getElementById(el).innerHTML;
document.body.innerHTML = printcontent;
window.print();
document.body.innerHTML = restorepage;
}
</script>
The styling:
<style type="text/css" media="print">
#page
{
size: auto; /* auto is the current printer page size */
margin: 20mm; /* this affects the margin in the printer settings */
size: A4;
}
body
{
background-color:#FFFFFF;
border: solid 1px black ;
}
.divFooter {
position: fixed;
bottom: 0;
}
.divHeader {
position: fixed;
top: 0;
}
table { page-break-after:auto }
tr { page-break-inside:avoid; page-break-after:auto }
td { page-break-inside:avoid; page-break-after:auto }
thead { display:table-header-group }
tfoot { display:table-footer-group; page-break-after:auto }
</style>

jQuery array sort works on only first table element in the DOM

I have one table which is being sorted by clicking on a header field and another which isn't. The table which is working comes before the one that doesn't sort, if the order is a factor.
The first table sorts and the second doesn't.
jsfiddle
$('th').each(function(col) {
$(this).click(function() {
if ($(this).is('.asc')) {
$(this).removeClass('asc');
$(this).addClass('desc selected');
sortOrder = -1;
} else {
$(this).addClass('asc selected');
$(this).removeClass('desc');
sortOrder = 1;
}
$(this).siblings().removeClass('asc selected');
$(this).siblings().removeClass('desc selected');
var arrData = $(this).closest('table').find('tbody > tr:has(td)').get();
arrData.sort(function(a, b) {
//console.log(a, b);
var val1 = $(a).find('td').eq(col).text().toUpperCase();
var val2 = $(b).find('td').eq(col).text().toUpperCase();
if ($.isNumeric(val1) && $.isNumeric(val2))
return sortOrder == 1 ? val1 - val2 : val2 - val1;
else
return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
});
//$(this).closest('tbody tr').remove()
$.each(arrData, function(index, row) {
//console.log(row);
$(this).closest('tbody').append(row);
});
});
});
table {
border: none !important;
}
table th {
border: none !important;
}
table td {
border: none;
}
table thead th {
font-weight: bold;
}
table thead tr td {
padding-right: 2em;
}
table tbody {
font-variant-numeric: tabular-nums;
font-weight: normal;
}
table th,
table td {
padding: 10px;
}
table tr:nth-child(even) td {
background-color: rgba(255, 255, 255, 0.1);
}
table thead tr th:hover {
color: rgba(0, 0, 0, 0.6);
cursor: pointer;
font-weight: bold;
}
.selected {
background-color: rgba(255, 255, 255, 0.1);
font-weight: 500;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table id="leaderboard">
<thead>
<tr>
<th>Position</th>
<th>Name</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Test</td>
<td>00:15:00</td>
</tr>
<tr>
<td>2</td>
<td>Joe Bloggs</td>
<td>01:00:13</td>
</tr>
<tr>
<td>3</td>
<td>Joe Bloggs</td>
<td>03:00:00</td>
</tr>
<tr>
<td>4</td>
<td>Joe Bloggs</td>
<td>08:00:00</td>
</tr>
</tbody>
</table>
<table id="leaderboard2">
<thead>
<tr>
<th>Position</th>
<th>Name</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Bob</td>
<td>00:17:52</td>
</tr>
<tr>
<td>2</td>
<td>Joe Bloggs</td>
<td>00:20:35</td>
</tr>
<tr>
<td>3</td>
<td>Alice</td>
<td>23:19:18</td>
</tr>
</tbody>
</table>
The col index returned by .each is wrong for the second table...
Since that index is based on the th collection for the whole page, regardless of the table in which it is in.
So wrap your function with:
$("table").each(function(){
And then use $(this).find('th').each(function(col) {.
The rest is unchanged.
Updated Fiddle
The problem is in the th indexing when you do $('th').each(function(col)
col is index of all th in page which doesn't work well when indexing in the cell sorting
Following approach works
$('table').each(function(col) {
var sortOrder
$(this).find('th').click(function() {
var col = $(this).index()
// all same after this
Suggest you get rid of repetitive calls to $(this) by caching variables for $th, $table,$siblings etc
Note you can also append whole array without each also
DEMO
No need for extra library or plugin for this.
The problem you have is that you have two tables and you r walking all 'th's and save their number in col, so the variable col is 0, 1, 2, 3, 4, 5
in the second table you are searching for td under th which is equal to col in your case 3,4 or 5. But these doesn't exists.
You only have to normlaize your col variable. For example adding this:
arrData.sort(function(a, b) {
col = col >= 3 ? col-3 : col; // add this line
var val1 = $(a).find('td').eq(col).text().toUpperCase();
var val2 = $(b).find('td').eq(col).text().toUpperCase();
....
Fiddle updated here: https://jsfiddle.net/gyfoousf/15/

Displaying JavaScript

I am still stuck on what should seem to be a simple concept. I have a very very simple javascript that just does some addition and I want to display the result on a web page. I have tried using a tag but that did not seem to do anything, an now I am trying to use the from the html but that is not working either. This seems like it should be such a simple thing to do but I am obviously missing something. Any help would be greatly appreciated. I have attached the html code, the script, and the css.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>The Lighthouse</title>
<link href="lhouse.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="title">
<p><img src="logo.jpg" alt="The Lighthouse" />
</p>
<p>The Lighthouse<br />
543 Oak Street<br />
Owensboro, KY 42302<br/>
(270) 555-7511
</p>
</div>
<div id="data_list">
<table rules="rows" cellspacing='0'>
<thead>
<tr>
<th>Date</th>
<th>Amount</th>
<th>First Name</th>
<th>Last Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>2011-09-18</td>
<td id="amount1">125</td>
<td>Nina</td>
<td>Largent</td>
<td>88 Regal Lane<br />Willaimsburg, KY 40789</td>
</tr>
<tr class="yellowrow">
<td>2011-09-18</td>
<td id="amount2">75</td>
<td>Mike</td>
<td>Hunt</td>
<td>404 Barrow Street<br />London, KY 40742</td>
</tr>
<tr>
<td>2011-09-16</td>
<td id="amount3">50</td>
<td>Monica</td>
<td>Lang</td>
<td>743 Stawlings Drive<br />Danville, KY 40423</td>
</tr>
<tr class="yellowrow">
<td>2011-09-15</td>
<td id="amount4">150</td>
<td>William</td>
<td>McKnight</td>
<td>404 Barrow Street<br />Danville, KY 40423</td>
</tr>
<tr>
<td>2011-09-14</td>
<td id="amount5">250</td>
<td>Latrina</td>
<td>Hults</td>
<td>750 Whitehall Road<br />London, KY 40742</td>
</tr>
<tr class="yellowrow">
<td>2011-09-13</td>
<td id="amount6">50</td>
<td>Danny</td>
<td>Shamblin</td>
<td>123 Smith Street<br />Owensboro, KY 42303</td>
</tr>
</tbody>
</table>
</div>
<div id="totals">
<table rules="groups" cellspacing="1">
<thead>
<tr>
<th id="sumTitle" colspan="2">Summary</th>
</tr>
</thead>
<tbody>
<tr>
<th>Contributors</th>
<td id="contributions"> </td>
</tr>
<tr>
<th>Amount</th>
<td id="amount"> </td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
__
// JavaScript Document
window.onload = function ()
{
//find the div tags called amount1, amount2, ...amount6
var amount1 = 125;
var amount2 = 75;
var amount3 = 50;
var amount4 = 150;
var amount5 = 250;
var amount6 = 50;
var totalAmount = amount1 + amount2 + amount3 + amount4 + amount5 + amount6;
var totalContributors = 6;
$("contributions").value = totalAmount.toFixed(2);
}
__
#title {
width: 600px;
text-align:right;
color: rgb(192,142,90);
border-bottom: 1px solid rgb(232,182,130);
margin-bottom:9px;
font-size:10pt;
height: 100px;
}
#title img {
float: left;
}
#data_list {
float: left;
}
table {
font-size: 8pt;
font-family: Arial, Helvetica, sans-serif;
border: 1px solid brown;
margin-right: 20px;
}
.yellowrow {
background-color: yellow;
}
th {
color: white;
background-color: brown;
padding: 2px 5px;
}
td {
vertical-align: top;
padding: 2px 5px;
}
.amt {
text-align: right;
}
#totals table {
font-size: 12pt;
border: solid black 1px;
}
#totals table th {
text-align: left;
}
#totals table td {
text-align: right;
width: 75px;
}
#totals table #sumTitle {
text-align: center;
background-color: yellow;
color: black;
}
In the below line:
$("contributions").value = totalAmount.toFixed(2);
You have forgot # as contributions is id of td so use this:
$("#contributions").html(totalAmount.toFixed(2));
And .value is the javascript and you are using jQuery so use .html function instead of .value .
And you have not added jquery library in your HTML page, add jquery library also.
And If your JS is in different file then add the file also in the code.
Use this:
<script type="text/javascript" src="your/file/path/*.js"></script>
$("contributions").value = totalAmount.toFixed(2);
this should probably be:
$("#contributions").html(totalAmount.toFixed(2));
So instead it does target the contributions td (based on id because of # just like in css).
And the html sets the innerHTML, you could just use text() instead if it's just plaintext.
2 issues I see:
1) you should be looking for $("#contributions") since you are querying by id.
2) since contributions is a td you should use its innerHTML property to set content, rather than value.

Categories

Resources