how to toggle table rows from 3rd - javascript

I have multiple tables on a page.
Each table has more than 10 rows.
The design is to show first rows on each table with a 'show more' button.
Once a user clicks the show more button.
It will expand the hidden rows on the clicked table only.
Any idea to make it easily?
It seems hard to implement by css, because there are multiple tables on a page.
My idea is to put the toogle button on each table.
Which will intercept the click trigger. And find the closest parent table.
Finally, change all the rows style in the table. from display:none to show.

As you've not given us much to go on, we will assume that your toggle buttons immediately follow your tables.
I've given you three options. No Jquery, Jquery and CSS with a bit of a hack.
No Jquery
var toggleButtons = document.getElementsByClassName("toggleTable");
for (var i = 0; i < toggleButtons.length; i++) {
toggleButtons[i].addEventListener('click', function() {
this.previousElementSibling.classList.toggle('collapsed');
}, false);
}
/*Change nth-child as required*/
table.collapsed>tbody>tr:nth-child(n+2) {
display: none;
}
<table class="collapsed">
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>R1 C1</td>
<td>R1 C2</td>
<td>R1 C3</td>
</tr>
<tr>
<td>R2 C1</td>
<td>R2 C2</td>
<td>R2 C3</td>
</tr>
<tr>
<td>R3 C1</td>
<td>R3 C2</td>
<td>R3 C3</td>
</tr>
</tbody>
</table>
<input type="button" value="Toggle Rows" class="toggleTable">
Support Issues, this will have issues in IE 9 and lower, other major browsers should be fine.:
http://caniuse.com/#feat=getelementsbyclassname
http://caniuse.com/#feat=addeventlistener
https://developer.mozilla.org/en-US/docs/Web/API/NonDocumentTypeChildNode/previousElementSibling
http://caniuse.com/#search=classList
Jquery -- Solves the support issues above.
$(".toggleTable").click(function(){
$(this).prev("table").toggleClass("collapsed");
});
/*Change nth-child as required*/
table.collapsed>tbody>tr:nth-child(n+2)
{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="collapsed">
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>R1 C1</td>
<td>R1 C2</td>
<td>R1 C3</td>
</tr>
<tr>
<td>R2 C1</td>
<td>R2 C2</td>
<td>R2 C3</td>
</tr>
<tr>
<td>R3 C1</td>
<td>R3 C2</td>
<td>R3 C3</td>
</tr>
</tbody>
</table>
<input type="button" value="Toggle Rows" class="toggleTable">
CSS Only - With a bit of a hack. You will need to generate in ID for each check box and associated label. In this instance the button must come before the table.
/*Use CSS to hide the rows of the table that is next to check box that is next to an element with a class of tableToggle*/
.tableToggle + input[type="checkbox"]:checked + table>tbody>tr:nth-child(n+2) {
display: none;
}
/*Hide the checkbox*/
.tableToggle + input[type="checkbox"] {display:none;}
/*Button Styling only -- noting important here*/
.tableToggle{
background-color:#44c767;
-moz-border-radius:28px;
-webkit-border-radius:28px;
border-radius:28px;
border:1px solid #18ab29;
display:inline-block;
cursor:pointer;
color:#ffffff;
font-family:Arial;
padding:5px;
text-decoration:none;
text-shadow:0px 1px 0px #2f6627;
}
<label class="tableToggle" for="cb1">Toggle Rows</label><input id="cb1" type="checkbox" checked="checked">
<table>
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>R1 C1</td>
<td>R1 C2</td>
<td>R1 C3</td>
</tr>
<tr>
<td>R2 C1</td>
<td>R2 C2</td>
<td>R2 C3</td>
</tr>
<tr>
<td>R3 C1</td>
<td>R3 C2</td>
<td>R3 C3</td>
</tr>
</tbody>
</table>

Unless you decide to use a library like jQuery, this is going to require a decent amount of code. Abstracting out certain functionality like showing and hiding elements helps to reduce the bloat:
function hide (e) { e.style.display = 'none' }
function show (e) { e.style.display = '' }
function additionalRows (table) {
return [].slice.call(table.rows, +table.getAttribute('data-initial-rows'))
}
function insertAfter (e, reference) {
reference.parentNode[reference.nextSibling ? 'insertBefore' : 'appendChild'](e, reference.nextSibling)
}
function showAll () {
additionalRows(this.previousSibling).forEach(show)
this.parentNode.removeChild(this)
}
var template = document.createElement('button')
template.textContent = 'Show All'
document.querySelectorAll('.expandable-table').forEach(function (table) {
additionalRows(table).forEach(hide)
var button = template.cloneNode(true)
button.addEventListener('click', showAll)
insertAfter(button, table)
})
<table class="expandable-table" data-initial-rows="10">
<thead>
<tr><th>X</th><th>Y</th></tr>
</thead>
<tr><td>7.34</td><td>9.56</td></tr>
<tr><td>5.64</td><td>4.14</td></tr>
<tr><td>0.99</td><td>8.55</td></tr>
<tr><td>9.18</td><td>8.65</td></tr>
<tr><td>6.60</td><td>3.25</td></tr>
<tr><td>8.88</td><td>5.29</td></tr>
<tr><td>0.40</td><td>5.36</td></tr>
<tr><td>9.74</td><td>7.14</td></tr>
<tr><td>7.61</td><td>6.32</td></tr>
<tr><td>3.87</td><td>2.80</td></tr>
<tr><td>0.77</td><td>0.11</td></tr>
<tr><td>8.78</td><td>5.45</td></tr>
<tr><td>2.40</td><td>7.54</td></tr>
<tr><td>6.53</td><td>1.45</td></tr>
<tr><td>7.92</td><td>1.90</td></tr>
<tr><td>1.81</td><td>4.69</td></tr>
<tr><td>9.40</td><td>7.86</td></tr>
<tr><td>3.33</td><td>5.08</td></tr>
<tr><td>0.18</td><td>3.16</td></tr>
<tr><td>1.54</td><td>0.80</td></tr>
</table>

Try This way :
$('.btnShow').click(function () {
$(this).prev("table").find("tr.expand").toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table1">
<thead>
<tr>
<th>No.</th>
<th>Name</th>
<th>Mobile No</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Taylor</td>
<td>123456789</td>
</tr>
<tr class="expand" style="display:none">
<td>2</td>
<td>Smith</td>
<td>456789</td>
</tr>
<tr class="expand" style="display:none">
<td>3</td>
<td>Mr. Patel</td>
<td>456789</td>
</tr>
<tr class="expand" style="display:none">
<td>4</td>
<td>Nirav</td>
<td>987654321</td>
</tr>
</tbody>
</table>
<input type="button" value="Show / Hide" class="btnShow" />

Related

How can I filter the column type of the table using two buttons?

I want to filter the type column, one button filters the aquatic and in the other all except the aquatic
<button type="button" onclick="Aquatic()">Aquatic</button>
<button type="button" onclick="NotAquatic()" >everything but aquatic</button>
<table class="table" >
<thead>
<tr>
<th scope="col">Animal</th>
<th scope="col">Type </th>
</tr>
</thead>
<tbody id="" >
<tr>
<td>bat</td>
<td>aerial</td>
</tr>
<tr>
<td>Fish</td>
<td>Aquatic</td>
</tr>
<tr>
<td>Horse</td>
<td>Land</td>
</tr>
<tr>
<td>Shark</td>
<td>Aquatic</td>
</tr>
<tr>
<td>Elephant</td>
<td>Land</td>
</tr>
<tr>
<td>Whale</td>
<td>Aquatic</td>
</tr>
<tr>
<td>dove</td>
<td>aerial</td>
</tr>
</tbody>
</table>
Hopefully this helps point you in the right direction! have a filterTable function which grabs all the table rows, and removes any inline style changes previously added to display. Then, I filter all the trs by the innerHTML content not including the term, and I take all those trs and set their display to none
function filterTable(aquaShown) {
const trs = [...document.querySelectorAll("tbody tr")];
trs.forEach(tr => tr.style.display = "");
const hiddenTrs = aquaShown ?
trs.filter(tr => !tr.innerHTML.includes("Aquatic")) :
trs.filter(tr => tr.innerHTML.includes("Aquatic"));
hiddenTrs.forEach(tr => tr.style.display = "none");
}
function aquatic() {
filterTable(true);
}
function nonaquatic() {
filterTable(false);
}
<button type="button" onclick="aquatic()">Aquatic</button>
<button type="button" onclick="nonaquatic()">Non-Aquatic</button>
<table class="table">
<thead>
<tr>
<th scope="col">Animal</th>
<th scope="col">Type </th>
</tr>
</thead>
<tbody id="">
<tr>
<td>Fish</td>
<td>Aquatic</td>
</tr>
<tr>
<td>Horse</td>
<td>Land</td>
</tr>
<tr>
<td>Shark</td>
<td>Aquatic</td>
</tr>
<tr>
<td>Elephant</td>
<td>Land</td>
</tr>
<tr>
<td>Whale</td>
<td>Aquatic</td>
</tr>
</tbody>
</table>
EDIT refactored based on further clarification in comments

Changing Day Date of <td> using JQuery

I am trying to change all the table Due Date values from the 31st to the 25th using jquery. The current code I am using is not working, as it is putting all values instead of the single value.
var dueDate1 = $("td:contains(/31/)").text();
var dueDate = dueDate1.replace(/31/g, "25");
$("td:contains(/31/)").text(dueDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Due Date</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td data-title="Due Date">08/31/21</td>
<td data-title="Amount">$500</td>
</tr>
<tr>
<td data-title="Due Date">07/31/21</td>
<td data-title="Amount">$1500</td>
</tr>
<tr>
<td data-title="Due Date">06/31/21</td>
<td data-title="Amount">$2500</td>
</tr>
</tbody>
</table>
Your attempt is working on the entire set of data all at once.
$("td:contains(/31/)").text(); will return all the text of all the cells.
Instead, loop through the cells and update them individually.
$("td:contains('31')").each(function(idx, element){
$(element).text($(element).text().replace("31", "25"));
});
td { padding:2px; border:1px solid grey; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Due Date</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td data-title="Due Date">08/31/21</td>
<td data-title="Amount">$500</td>
</tr>
<tr>
<td data-title="Due Date">07/31/21</td>
<td data-title="Amount">$1500</td>
</tr>
<tr>
<td data-title="Due Date">06/31/21</td>
<td data-title="Amount">$2500</td>
</tr>
</tbody>
</table>

Styling alternate rows using Javascript [duplicate]

This question already has answers here:
Alternate table row color using CSS?
(11 answers)
Closed 4 years ago.
I am trying to change background color of alternate rows of two tables using Javascript.
I am able to do it using below javascript but I'm sure there is a more efficient or short-cut way to select required child elements using CSS selectors. Can anyone help?
window.onload = function() {
var elem = document.getElementsByTagName('table')
for (let c = 0; c < elem.length; c++) {
var childElem = elem[c].getElementsByTagName('tr');
for (let d = 0; d < childElem.length; d = d + 2) {
childElem[d].classList.add('alt');
}
}
}
tr {
background-color: #fff;
}
.alt {
background-color: #ccc;
}
<html>
<body>
<h2>Online Tx</h2>
<table>
<tr>
<td>As You Like It</td>
<td>Comedy</td>
<td></td>
</tr>
<tr>
<td>All's Well that Ends Well</td>
<td>Comedy</td>
<td>1601</td>
</tr>
<tr>
<td>Hamlet</td>
<td>Tragedy</td>
<td>1604</td>
</tr>
<tr>
<td>Macbeth</td>
<td>Tragedy</td>
<td>1606</td>
</tr>
<tr>
<td>Romeo and Juliet</td>
<td>Tragedy</td>
<td>1595</td>
</tr>
</table>
<h2>Backend tx</h2>
<table>
<tr>
<td>The Fair Youth</td>
<td>1–126</td>
</tr>
<tr>
<td>The Dark Lady</td>
<td>127–152</td>
</tr>
<tr>
<td>The Rival Poet</td>
<td>78–86</td>
</tr>
</table>
</body>
</html>
You can achieve it with pure CSS and :nth-child:
tr:nth-child(2n) {
background-color: #eee;
}
tr:nth-child(2n + 1) {
background-color: #ccc;
}
<h2>Online Tx</h2>
<table>
<tr>
<td>As You Like It</td>
<td>Comedy</td>
<td></td>
</tr>
<tr>
<td>All's Well that Ends Well</td>
<td>Comedy</td>
<td>1601</td>
</tr>
<tr>
<td>Hamlet</td>
<td>Tragedy</td>
<td>1604</td>
</tr>
<tr>
<td>Macbeth</td>
<td>Tragedy</td>
<td>1606</td>
</tr>
<tr>
<td>Romeo and Juliet</td>
<td>Tragedy</td>
<td>1595</td>
</tr>
</table>
<h2>Backend tx</h2>
<table>
<tr>
<td>The Fair Youth</td>
<td>1–126</td>
</tr>
<tr>
<td>The Dark Lady</td>
<td>127–152</td>
</tr>
<tr>
<td>The Rival Poet</td>
<td>78–86</td>
</tr>
</table>
In CSS, simply use:
tr:nth-of-type(odd)
Working Example:
tr:nth-of-type(odd) {
background-color: rgb(191, 191, 191);
}
<table>
<tr>
<td>As You Like It</td>
<td>Comedy</td>
<td></td>
</tr>
<tr>
<td>All's Well that Ends Well</td>
<td>Comedy</td>
<td>1601</td>
</tr>
<tr>
<td>Hamlet</td>
<td>Tragedy</td>
<td>1604</td>
</tr>
<tr>
<td>Macbeth</td>
<td>Tragedy</td>
<td>1606</td>
</tr>
<tr>
<td>Romeo and Juliet</td>
<td>Tragedy</td>
<td>1595</td>
</tr>
</table>

Change background of entire table row

I'm looking to make the entire row of a table change colour (either the background colour or text colour) based on the value of the column labelled "Status". If the value in the "Status" column is "Expired" the background of the entire row should change.
(Edit: The data is going to be pulled dynamically from a database).
Any suggestions?
HTML Code
<table>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</table>
Thanks in advance.
If you can change how the table is rendered than I would just add the text as a class. This will be the best performance option and requires no JavaScript and the content will not flash.
tr.Expired td {
background-color: red;
}
tr.Active td {
background-color: green;
}
<table>
<thead>
<tr>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr class="Active">
<td>Cash</td>
<td>£500</td>
<td>Link
</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr class="Expired">
<td>Sports Car</td>
<td>£5000</td>
<td>Link
</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</tbody>
</table>
Or you will need to run JavaScript code that reads the cell value and adds the class.
$("tr:has(td:last:contains('Expired'))").addClass("Expired");
tr.Expired td {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link
</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link
</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</tbody>
</table>
try using CSS only adding a class to the tr.
tr.active > td {
background-color: green;
}
tr.expired > td {
background-color: red;
}
https://jsfiddle.net/jt717mL8/
In your case the status column is the 5th. So you may do something like:
$('table tr:gt(0)').each(function(idx, ele) {
if ($(ele).find('td:eq(4)').text() == 'Expired') {
$(ele).css('backgroundColor', 'yellow');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</table>
You can first get index of status th and then check each td with same index and check its text.
var i = $('th:contains(Status)').index();
$('tr').each(function() {
var td = $(this).find('td').eq(i);
if (td.text() == 'Expired') td.css('background', 'red')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link
</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link
</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</table>

Master-detail with HTML, CSS and jQuery

I want to create a master-detail. So, I follow this tutorial:
http://mrbool.com/how-to-create-a-master-detail-table-with-html-css-and-jquery/26848
I decided to reproduce it, but there is something wrong in my code(?).
Here's my code:
HTML/jQuery
<!DOCTYPE html>
<html>
<head>
<link href="stile.css" rel="stylesheet" type="text/css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("td:nth-child(1)").html("<img src='images.jpg' class='clk'>");
$(".clk").click(function () {
var index = $(this).parent().parent().index();
var detail = $(this).parent().parent().next();
var status = $(detail).css("display");
if (status === "none")
$(detail).css("display", "table-row");
else
$(detail).css("display", "none");
});
});
</script>
</head>
<body>
<table id="tbSales" rules="rows">
<thead>
<tr>
<th></th>
<th>ID</th>
<th>Date</th>
<th>Items</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr class="saleRow">
<td></td>
<td>01</td>
<td>01/01/2001</td>
<td>2</td>
<td>10,00</td>
</tr>
<tr class="itemsRow">
<td colspan="5"> Itens
<table class="tbItems" rules="rows">
<thead>
<tr>
<th>ID</th>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>A1</td>
<td>Product A 1</td>
<td>1</td> <td>7,00</td>
</tr>
<tr>
<td>A2</td>
<td>Product A 2</td>
<td>1</td>
<td>3,00</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr class="saleRow">
<td></td>
<td>02</td>
<td>02/02/2001</td>
<td>3</td>
<td>20,00</td>
</tr>
<tr class="itemsRow">
<td colspan="5"> Itens
<table class="tbItems" rules="rows">
<thead>
<tr>
<th>ID</th>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>B1</td>
<td>Product B 1</td>
<td>1</td>
<td>10,00</td>
</tr>
<tr>
<td>B2</td>
<td>Product B 2</td>
<td>2</td>
<td>5,00</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tbody>
</table>
</body>
CSS:
#tbSales, .tbItems{
width:100%;
border:solid 1px;
}
#tbSales thead th, .tbItems thead th{
text-align:left;
}
#tbSales tr td, .tbItems tr td{
border:solid 1px;
}
#tbSales tr td:nth-child(1){
width:20px;
}
#tbSales tbody tr{
background:#DCDCDC;
}
.tbItems tr{
background:red;
}
#tbSales thead{
background:#4682B4;
}
.itemsRow{
display: none;
}
.tbItems{
font-size:12px;
}
This is what should happen:
This is what happen to me:
The row is empty! Why?
$("td:nth-child(1)")
Is overriding all first children from table.
You need to specify the line in which you want to replace the cell:
$(".saleRow td:nth-child(1)")
Your first line of javascript replaces the contents of all first children from your table.
Change :
$("td:nth-child(1)").html("<img src='images.jpg' class='clk'>");
with :
$("td:nth-child(1)").css("border","red dashed 2px")
and you'll see what I mean.
See it here : http://codepen.io/jeremythille/pen/qELyWX
td:nth-child(1) means "Every first <td> of each <tr> of the whole table". But you have nested tables...

Categories