Dynamic DataTable to chart one row across the row - javascript

I have a datatable that is drawing data from a database dynamically, and correctly displaying the data on a piechart. However, after having searched abundantly, I am still having problems doing the following, please keep in mind I am new to javascript and it could be something minor that I am missing.
The piechart is working fine, but I would like the chart to display data only from the first row, and not all rows as it is currently doing. I have tried:
"startRow: 2, endRow: 3" - This works with other charts but with the code I have below, it doesn't work no matter where I put it.
I have also tried ""pageLength": 1," which applies to the datatable but the chart still displays all rows.
On a separate chart from the same datatable, I would like to chart data across the row and not down the column. I have tried "switchRowsAndColumns: true".
Again this solution works with other tables but not with the code I'm using, which draws the chart according to the info in the table, which will be generated through the search function or filters. If I can have both charts displayed as a series each rendered to a separate container that would be great.
Any help would be greatly appreciated. Here is the jsfiddle (pls ignore slice labels)
Attached is the code (I am using a static table but my table is dynamic):
$(document).ready(function() {
// Initialize table
var c20BhvDt = $("#c20Bhv").DataTable({
});
var kc20BhvPieChart = Highcharts.chart("container", {
chart: {
type: "pie",
backgroundColor: "transparent",
},
plotOptions: {
pie: {
colors: ['#64c987', '#d16035', '#e58b38', '#fafa6e', '#b53535', '#099FFF'],
allowPointSelect: true,
slicedOffset: 30,
cursor: 'pointer',
innerSize: '10%',
borderWidth: 3,
borderColor: '#2d3035',
dataLabels: {
enabled: true,
color: '#EF8C99',
connectorColor: '#EF8C99'
}
}
},
series: [{
data: chartData(c20BhvDt, 7),
name: 'Students',
dataLabels: {
style: {
fontSize: 16,
textOutline: '#2d3035'
},
formatter: function() {
const point = this.point;
return '<span style="color: ' + point.color + '">' +
point.name + ' - ' + point.y + ' Students</span>';
},
},
},
],
});
c20BhvDt.on("draw", function() {
kc20BhvPieChart.series[0].setData(chartData(c20BhvDt));
});
});
function chartData(c20BhvDt, column = 7) {
var counts = {};
c20BhvDt
.column(column, {
search: "applied"
})
.data()
.each(function(val) {
if (counts[val]) {
counts[val] += 1;
} else {
counts[val] = 1;
}
});
return $.map(counts, function(val, key) {
return {
name: key,
y: val,
};
});
};
#container {
height: 400px;
}
.highcharts-figure,
.highcharts-data-table table {
min-width: 310px;
max-width: 800px;
margin: 1em auto;
}
#c20Bhv {
font-family: Verdana, sans-serif;
border-collapse: collapse;
border: 1px solid #ebebeb;
margin: 10px auto;
text-align: center;
width: 100%;
max-width: 500px;
}
#c20Bhv caption {
padding: 1em 0;
font-size: 1.2em;
color: #555;
}
#c20Bhv th {
font-weight: 600;
padding: 0.5em;
}
#c20Bhv td,
#c20Bhv th,
#c20Bhv caption {
padding: 0.5em;
}
#c20Bhv thead tr,
#c20Bhv tr:nth-child(even) {
background: #f8f8f8;
}
#c20Bhv tr:hover {
background: #f1f7ff;
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs5/dt-1.12.1/sb-1.3.3/sp-2.0.1/datatables.min.js"></script>
<script src="https://nightly.datatables.net/searchpanes/js/dataTables.searchPanes.js?13"></script>
<script src="https://nightly.datatables.net/select/js/dataTables.select.js?_=9a6592f8d74f8f520ff7b22342fa1183"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<figure class="highcharts-figure">
<div id="container">
</div>
<table id="c20Bhv" class="Stabel" style="width:100%">
<thead>
<tr class="bg-secondary text-light text-large">
<td colspan="8" class="text-center">Student Info</td>
</tr>
<tr>
<th class="text-center">ID</th>
<th class="text-center">EX</th>
<th class="text-center">NP</th>
<th class="text-center">Sl</th>
<th class="text-center">LT</th>
<th class="text-center">WR</th>
<th class="text-center">BTH</th>
<th class="text-center">SCR</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">21204</td>
<td class="text-center">4</td>
<td class="text-center">7</td>
<td class="text-center">3</td>
<td class="text-center">7</td>
<td class="text-center">2</td>
<td class="text-center">1</td>
<td class="text-center">87</td>
</tr>
<tr>
<td class="text-center">21205</td>
<td class="text-center">5</td>
<td class="text-center">3</td>
<td class="text-center">5</td>
<td class="text-center">9</td>
<td class="text-center">5</td>
<td class="text-center">2</td>
<td class="text-center">83</td>
</tr>
<tr>
<td class="text-center">21206</td>
<td class="text-center">8</td>
<td class="text-center">3</td>
<td class="text-center">5</td>
<td class="text-center">6</td>
<td class="text-center">1</td>
<td class="text-center">6</td>
<td class="text-center">93</td>
</tr>
<tr>
<td class="text-center">21207</td>
<td class="text-center">6</td>
<td class="text-center">3</td>
<td class="text-center">8</td>
<td class="text-center">4</td>
<td class="text-center">7</td>
<td class="text-center">4</td>
<td class="text-center">83</td>
</tr>
<tr>
<td class="text-center">21208</td>
<td class="text-center">3</td>
<td class="text-center">7</td>
<td class="text-center">6</td>
<td class="text-center">3</td>
<td class="text-center">2</td>
<td class="text-center">8</td>
<td class="text-center">74</td>
</tr>
<tr>
<td class="text-center">21209</td>
<td class="text-center">3</td>
<td class="text-center">4</td>
<td class="text-center">3</td>
<td class="text-center">8</td>
<td class="text-center">9</td>
<td class="text-center">6</td>
<td class="text-center">69</td>
</tr>
</tbody>
</table>
</figure>

Related

Search different columns of table

I'm trying to work a way where you can click a button and search by different columns in a table. I can figure out the buttons and to change the [0] to [1] to search different columns, but how would i make it more dynamic, using javascript. I only want to search by 1 column at a time, so only search by first name or only search by nationality etc...
it is a basic code, I did web programming 20 years ago and im trying to get back up to speed.
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
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];
if (td) {
txtValue = td.textContent || td.innerText;
if (filter) {
if (txtValue.toUpperCase() == filter) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
} else {
tr[i].style.display = "";
}
}
}
}
<div class="w3-container">
<h2>All Information</h2>
<div class="w3-bar">
<button class="w3-button w3-black" style="width: 10%">#</button>
<button class="w3-button w3-teal" style="width: 10%">First Name</button>
<button class="w3-button w3-red" style="width: 10%">Last Name</button>
<button class="w3-button w3-yellow" style="width: 10%">Address</button>
<button class="w3-button w3-green" style="width: 10%">Age</button>
<button class="w3-button w3-blue" style="width: 10%">Date of Birth</button>
<button class="w3-button w3-purple" style="width: 10%">Nationality</button>
</div>
<input id="myInput" onkeyup="myFunction()" placeholder="Search by ID Number..." title="Type in a number" type="text">
<table id="myTable">
<tr class="header">
<th class="w3-center" style="width: 2%;">#</th>
<th style="text-align: left; width: 17%;">First Name</th>
<th style="text-align: left; width: 17%;">Last Name</th>
<th style="text-align: left; width: 16%;">Address</th>
<th style="text-align: left; width: 16%;">Age</th>
<th style="text-align: left; width: 16%;">Date of Birth</th>
<th style="text-align: left; width: 16%;">Nationality</th>
</tr>
<tr>
<td class="w3-center">1</td>
<td>John</td>
<td>Smith</td>
<td>Pearse Street</td>
<td>45</td>
<td>01/10/1977</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">11</td>
<td>Tim</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>17/04/1999</td>
<td>American</td>
</tr>
<tr>
<td class="w3-center">114</td>
<td>Tom</td>
<td>Deane</td>
<td>Greenwood Road</td>
<td>42</td>
<td>27/11/1980</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">208</td>
<td>Anna</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>11/06/1999</td>
<td>Scottish</td>
</tr>
<tr>
<td class="w3-center">259</td>
<td>Rachel</td>
<td>Waters</td>
<td>Station Road</td>
<td>87</td>
<td>11/02/1936</td>
<td>Irish</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>George</td>
<td>Taylor</td>
<td>Beach Avenue</td>
<td>52</td>
<td>30/07/1971</td>
<td>South African</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Neil</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>6</td>
<td>15/12/2016</td>
<td>Australian</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Sarah</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>30</td>
<td>06/01/1993</td>
<td>Australian</td>
</tr>
</table>
</div>
const column = 3
const searchFor = 'GRE'
for (const cell of document.querySelectorAll(`#myTable tr td:nth-child(${column})`))
if (cell.textContent.toUpperCase().includes(searchFor))
cell.style.background = 'lightgreen'
<table id="myTable">
<tr class="header">
<th class="w3-center" style="width: 2%;">#</th>
<th style="text-align: left; width: 17%;">First Name</th>
<th style="text-align: left; width: 17%;">Last Name</th>
<th style="text-align: left; width: 16%;">Address</th>
<th style="text-align: left; width: 16%;">Age</th>
<th style="text-align: left; width: 16%;">Date of Birth</th>
<th style="text-align: left; width: 16%;">Nationality</th>
</tr>
<tr>
<td class="w3-center">1</td>
<td>John</td>
<td>Smith</td>
<td>Pearse Street</td>
<td>45</td>
<td>01/10/1977</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">11</td>
<td>Tim</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>17/04/1999</td>
<td>American</td>
</tr>
<tr>
<td class="w3-center">114</td>
<td>Tom</td>
<td>Deane</td>
<td>Greenwood Road</td>
<td>42</td>
<td>27/11/1980</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">208</td>
<td>Anna</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>11/06/1999</td>
<td>Scottish</td>
</tr>
<tr>
<td class="w3-center">259</td>
<td>Rachel</td>
<td>Waters</td>
<td>Station Road</td>
<td>87</td>
<td>11/02/1936</td>
<td>Irish</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>George</td>
<td>Taylor</td>
<td>Beach Avenue</td>
<td>52</td>
<td>30/07/1971</td>
<td>South African</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Neil</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>6</td>
<td>15/12/2016</td>
<td>Australian</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Sarah</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>30</td>
<td>06/01/1993</td>
<td>Australian</td>
</tr>
</table>
Looking for something like that ? (first version)
const
btSearch = document.querySelector('#bt-search')
, txt2search = document.querySelector('#txt-2-search')
, searchResult = document.querySelector('#search-result')
, myTable = document.querySelector('#my-table')
;
btSearch.disabled = true
;
myTable.onclick = ({target:TH}) =>
{
if (!TH.matches('th')) return;
clearFounds();
btSearch.disabled = true;
if (TH.classList.toggle('selec'))
{
btSearch.disabled = false;
myTable.querySelectorAll('th.selec')
.forEach(th => th.classList.toggle('selec',th===TH))
}
}
btSearch.onclick=()=>
{
clearFounds();
let txt = txt2search.value.trim()
, Rtxt = new RegExp(txt, 'i')
, nCol = 1 + myTable.querySelector('th.selec').cellIndex
, counter = 0
;
if (txt==='')
{
searchResult.textContent = 'nothing to search...';
return;
}
myTable.querySelectorAll(`tr td:nth-child(${nCol})`).forEach(td =>
{
if(Rtxt.test(td.textContent))
{
counter++;
td.classList.add('found');
}
})
searchResult.textContent = (counter===0) ? 'no result' : `${counter} element(s) found`;
}
function clearFounds()
{
searchResult.textContent = '.';
myTable.querySelectorAll('td.found')
.forEach(td => td.classList.remove('found'));
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
margin : 1rem;
}
table {
border-collapse : separate;
border-spacing : 1px;
background-color : lightslategrey;
}
th { background: cadetblue; padding: .3em .6em; cursor: pointer; }
td { background: whitesmoke; padding: .2em .5em; }
tr *:first-child { text-align: center; font-style: oblique; }
tr * { white-space: nowrap; }
th:not(.selec):hover { background: orange; }
th.selec { background: orangered }
td.found { background: aquamarine; }
caption {
text-align : left;
padding : .4rem;
font-size : 1.2rem;
background-color: #a0dbdd;
}
#search-result {
float : right;
font-size : .9rem;
}
<table id="my-table">
<caption>
Find :
<input type="text" id="txt-2-search" placeholder="select a column first...">
<button id="bt-search"> do search </button>
<span id="search-result">0</span>
</caption>
<thead>
<tr>
<th>#</th><th>First Name</th><th>Last Name</th><th>Address</th><th>Age</th><th>Date of Birth</th><th>Nationality</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td><td>John</td><td>Smith</td><td>Pearse Street</td><td>45</td><td>01/10/1977</td><td>English</td>
</tr>
<tr>
<td>11</td><td>Tim</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>17/04/1999</td><td>American</td>
</tr>
<tr>
<td>114</td><td>Tom</td><td>Deane</td><td>Greenwood Road</td><td>42</td><td>27/11/1980</td><td>English</td>
</tr>
<tr>
<td>208</td><td>Anna</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>11/06/1999</td><td>Scottish</td>
</tr>
<tr>
<td>259</td><td>Rachel</td><td>Waters</td><td>Station Road</td><td>87</td><td>11/02/1936</td><td>Irish</td>
</tr>
<tr>
<td>1</td><td>George</td><td>Taylor</td><td>Beach Avenue</td><td>52</td><td>30/07/1971</td><td>South African</td>
</tr>
<tr>
<td>1</td><td>Neil</td><td>Smyth</td><td>Beach Road</td><td>6</td><td>15/12/2016</td><td>Australian</td>
</tr>
<tr>
<td>1</td><td>Sarah</td><td>Smyth</td><td>Beach Road</td><td>30</td><td>06/01/1993</td><td>Australian</td>
</tr>
</tbody>
</table>
As the subject interested me...
And sorry, there may be a bit too many technical things here, but I've already spent a bit too many hours there, I'll come back to explain and comment. If any questions come up here in the meantime, I'll do my best to answer them.
const
txt2search = document.querySelector('#txt-2-search')
, searchResult = document.querySelector('#search-result')
, myTable = document.querySelector('#my-table')
, tableHeads = myTable.querySelectorAll('thead th')
, styleColHover = document.querySelector('#style-col-hover')
, mouseHoverTD = ({target: TD}) =>
{
let ref = (!!TD && TD.matches('td')) ? TD.cellIndex +1 : -1;
styleColHover.textContent = `td:nth-child(${ref}) { background: var(--col-hover);}`;
};
myTable.tBodies[0].onmouseenter = mouseHoverTD;
myTable.tBodies[0].onmousemove = mouseHoverTD;
myTable.tBodies[0].onmouseout =_=> mouseHoverTD({target:null});
txt2search.onkeyup = ({key}) =>
{
if (key==='Enter') searchProcess();
}
myTable.onclick = ({target:colElm}) =>
{
if (!colElm.matches('th, td')) return;
if (colElm.matches('td'))
{
tableHeads.forEach(th=>th.classList.remove('selec'));
tableHeads[colElm.cellIndex].classList.add('selec');
}
else if (colElm.classList.toggle('selec'))
{
tableHeads.forEach(th=>th.classList.toggle('selec', th===colElm));
}
searchProcess();
}
function clearSearch()
{
searchResult.textContent = '.';
myTable.querySelectorAll('td.found').forEach(td => td.classList.remove('found'));
}
function searchProcess()
{
let indxElm = myTable.querySelector('thead th.selec')?.cellIndex ?? 'x';
clearSearch();
if(isNaN(indxElm)) return;
let txt = txt2search.value.trim()
, Regtxt = new RegExp(txt, 'i')
, counter = 0
, query = 'tr td:nth-child('+ ++indxElm +')'
;
if (txt==='')
{
searchResult.textContent = 'nothing to search...';
return;
}
myTable.querySelectorAll(query).forEach(td =>
{
if(Regtxt.test(td.textContent))
{
counter++;
td.classList.add('found');
}
})
searchResult.textContent =
(counter===0) ? 'no result' : `${counter} element(s) found`;
}
:root {
--col-hover : #eeafdb;
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
margin : 1rem;
}
table {
border-collapse : separate;
border-spacing : 1px;
background-color : lightslategrey;
}
th { background: cadetblue; padding: .3em .6em; }
td { background: whitesmoke; padding: .2em .5em; }
tr *:first-child { text-align: center; font-style: oblique; }
tr * { white-space: nowrap; cursor: pointer; }
th:not(.selec):hover { background: orange; }
th.selec { background: orangered; }
td.found { background: aquamarine !important; }
caption {
text-align : left;
padding : .4rem;
font-size : 1.2rem;
background : #a0dbdd;
}
#search-result {
float : right;
font-size : .9rem;
}
<style id="style-col-hover"> td:nth-child(-1) { background : var(--col-hover);}</style>
<table id="my-table">
<caption>
Find :
<input type="text" id="txt-2-search" placeholder="select a column first...">
<span id="search-result">0</span>
</caption>
<thead>
<tr>
<th>#</th><th>First Name</th><th>Last Name</th><th>Address</th><th>Age</th><th>Date of Birth</th><th>Nationality</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td><td>John</td><td>Smith</td><td>Pearse Street</td><td>45</td><td>01/10/1977</td><td>English</td>
</tr>
<tr>
<td>11</td><td>Tim</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>17/04/1999</td><td>American</td>
</tr>
<tr>
<td>114</td><td>Tom</td><td>Deane</td><td>Greenwood Road</td><td>42</td><td>27/11/1980</td><td>English</td>
</tr>
<tr>
<td>208</td><td>Anna</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>11/06/1999</td><td>Scottish</td>
</tr>
<tr>
<td>259</td><td>Rachel</td><td>Waters</td><td>Station Road</td><td>87</td><td>11/02/1936</td><td>Irish</td>
</tr>
<tr>
<td>1</td><td>George</td><td>Taylor</td><td>Beach Avenue</td><td>52</td><td>30/07/1971</td><td>South African</td>
</tr>
<tr>
<td>1</td><td>Neil</td><td>Smyth</td><td>Beach Road</td><td>6</td><td>15/12/2016</td><td>Australian</td>
</tr>
<tr>
<td>1</td><td>Sarah</td><td>Smyth</td><td>Beach Road</td><td>30</td><td>06/01/1993</td><td>Australian</td>
</tr>
</tbody>
</table>
Here's my take Dar.
//Define a column to look in
// const column = 4
//Get the value from the input
// const searchFor = document.getElementById('myInput').value
//Grab all the cells for the column
columnCells = Array.from(document.querySelectorAll(`#myTable tr td:nth-child(${column})`))
//Clear out previous matches
columnCells.forEach(cell=>cell.style.background = 'white')
//Filter the cells by the searchFor term
matchingCells = columnCells.filter(cell=>{
return cell.textContent.toLowerCase().includes(searchFor.toLowerCase()) && searchFor != ""
})
//Color them
matchingCells.forEach(cell=>cell.style.background = 'yellow')

Save state of collapsed rows

I'm having troubles with saving the state of collapsed rows :
I have child and parent rows in a table. Parents have a +/- buttons allowing users to collapse/expand the child rows (which have a bigger data-level). The expand collapse itself works fine but if I collapse a row and then collapse the above row again, when I expand the higher row it expands everything after but I'd like to keep the collapsed rows collapsed.
In this example it works the way I'd like : Fiddle which works.
If you for example collapse the second row, then the first one, and expand the first, the second and all its children are kept collapsed and hidden.
In this example (which I'm struggling with) it doesn't work anymore : Fiddle which doesn't work
Does anyone have an idea of what's the problem ? I can't see why it works in the first case but not the second.
Thanks in advance for your help !
Sincerely,
EDIT :
The data-level needs to be equal to the headers="h_M1" td and each tr which have a lower data-level than its follower needs to be a parent that can be collapsed. For example in your edit there is tr3 as a child, but it needs to be a parent which can collapse all the tr after it (since there's no other 3 or lower after it). And it needs to stay collapsed if we collapse/expand tr2
// Expand/collapse when clicking on first column //
function getChildren($row) {
var children = [], level = $row.attr('data-level');
while($row.next().attr('data-level') > parseInt(level)) {
children.push($row.next());
$row = $row.next();
}
return children;
}
$('.colex').on('click', function() {
var action;
if($(this).parent('.parent').hasClass('collapsed')) {
$(this).parent('.parent').removeClass('collapsed');
$(this).text('-');
action = 'show';
} else {
$(this).parent('.parent').addClass('collapsed');
$(this).text('+');
action = 'hide';
}
var level = $(this).parent('.parent').attr('data-level');
var children = getChildren($(this).parent('.parent'));
$.each(children, function() {
if(action == "show") {
if ($(this).attr('data-level')==parseInt(level)+1
|| $(this).hasClass('hidden')===false) {
/* un-hide direct children, and not hidden sub-children */
$(this).removeClass('hidden').show();
}
} else {
if ($(this).attr('data-level')==parseInt(level)+1) {
/* apply hidden to direct children */
$(this).addClass('hidden');
}
/* hide all children */
$(this).hide();
}
});
})
body {
font-family: sans-serif;
}
body * {
box-sizing: border-box;
/*color: #59547c;*/
margin: 0;
}
main {
/* max-width: 60rem;*/
margin: 1px auto;
padding: 1rem;
}
h1 {
margin-bottom: 1rem;
}
p {
margin-bottom: 1rem;
}
input.variante[type=checkbox] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
input.variante[type=checkbox] {
height: 15px;
width: 15px;
background: #fff;
border: 1px solid #ccc;
}
input.variante[type="checkbox"]:checked
{
background: orange;
&:before {
font-family: FontAwesome;
content: '\f00c';
display: block;
color: grey;
font-size: 15px;
position: absolute;
}
}
table {
empty-cells: show;
}
th {
text-align:center;
border: 1px solid antiquewhite;
}
.parent > .colex {
color: black;
cursor: pointer;
}
.table_header {
background-color:#484e82;
color:#fdfdff;
font-weight: bold;
}
.intro {
font-size: 1.125rem;
}
.Titre_1 {
color: red;
}
.Titre_2 {
color: purple;
}
.Titre_3 {
color: fuchsia;
}
.Titre_4 {
color: green;
}
.Titre_5 {
color: lime;
}
.Titre_6 {
color: navy;
}
.Titre_7 {
color: blue;
}
.Titre_8 {
color: aqua;
}
.Titre_9 {
color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<body>
<intro>
<p class="intro">description</p>
</intro>
<main>
<table id="mytable" align=center rules=groups frame=box hborder=0 cellspacing=1 cellpadding=4 vborder=1>
<thead class="table_header">
<th id="colex" width=2%>Co<br/>Ex</th>
<th id="h_M8" width=2%>V<br/>M8</th>
<th id="h_M1" width=2%>cd<br/>M1</th>
<th id="h_M2" width=5%>N°<br/>M2</th>
<th id="h_M4" width=23%>Désignation<br/>M4</th>
<th id="h_M7" width=3%>Uté<br/>M7</th>
<th id="h_M9" width=3%>Qté <br/>M9</th>
<th id="h_M18" width=5%>PR Fourniture unitaire<br/>M18</th>
<th id="h_M20" width=3%>Type FO<br/>M20</th>
<th id="h_M14" width=3%>K Acc<br/>M14</th>
<th id="h_M19" width=6%>PR Total fourniture<br/>M19</th>
<th id="h_M23" width=5%>Tps pose unitaire<br/>M23</th>
<th id="h_M26" width=3%>Type MO<br/>M26</th>
<th id="h_M22" width=3%>K Pose<br/>M22</th>
<th id="h_M42" width=5%>Tps pose total<br/>M42</th>
<th id="h_M40" width=5%>PR unitaire<br/>M40</th>
<th id="h_M41" width=5%>PR Total<br/>M41</th>
<th id="h_M27" width=3%>qte vendue<br/>M27</th>
<th id="h_M32" width=5%>PV unitaire<br/>M32</th>
<th id="h_M44" width=6%>PV Total<br/>M44</th>
</thead>
<tbody>
<tr class="parent" data-level="1">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">1</td>
<td headers="h_M2">A</td>
<td headers="h_M4">Titre 1, n'appartient à personne</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
<td headers="h_M18"></td>
<td headers="h_M20"></td>
<td headers="h_M14"></td>
<td headers="h_M19"></td>
<td headers="h_M23"></td>
<td headers="h_M26"></td>
<td headers="h_M22"></td>
<td headers="h_M42"></td>
<td headers="h_M40"></td>
<td headers="h_M41"></td>
<td headers="h_M27"></td>
<td headers="h_M32"></td>
<td headers="h_M44"></td>
</tr>
<tr class="parent" data-level="2">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">2</td>
<td headers="h_M2">A.1</td>
<td headers="h_M4">Titre 2 - la ligne doit appartenir au titre niveau 1, N°A ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="parent" data-level="3">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">3</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne "terminale" doit appartenir au titre niveau 2, N°A.1 ci-dessus</td>
<td headers="h_M7">km</td>
<td headers="h_M9">6</td>
</tr>
<tr class="parent" data-level="4">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">4</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne doit aussi appartenir au titre niveau 2, N°A.1 ci-dessus</td>
<td headers="h_M7">m</td>
<td headers="h_M9">10,5</td>
</tr>
<tr class="child" data-level="5">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">5</td>
<td headers="h_M2">B</td>
<td headers="h_M4">un autre Titre 1, n'appartient à personne</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="parent" data-level="5">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">5</td>
<td headers="h_M2">B.1</td>
<td headers="h_M4">Titre 2 - la ligne doit appartenir au titre niveau 1, N°B ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="parent" data-level="6">
<td headers="colex" class="colex">-</td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">6</td>
<td headers="h_M2">B.1.1</td>
<td headers="h_M4">Titre 3 - la ligne doit appartenir au titre niveau 2, N°B.1 ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
<tr class="child" data-level="9">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">9</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne "terminale" doit appartenir au titre niveau 3, N°B.1.1 ci-dessus</td>
<td headers="h_M7">kg</td>
<td headers="h_M9">2</td>
</tr>
<tr class="child" data-level="9">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">9</td>
<td headers="h_M2"></td>
<td headers="h_M4">cette ligne doit aussi appartenir au titre niveau 3, N°B.1.1 ci-dessus</td>
<td headers="h_M7">m</td>
<td headers="h_M9">10,5</td>
</tr>
<tr class="child" data-level="9">
<td headers="colex" class="colex"></td>
<td headers="h_M8"><input class="variante" type="checkbox"></td>
<td headers="h_M1">9</td>
<td headers="h_M2">B.1.2</td>
<td headers="h_M4">Titre 3 - la ligne doit appartenir au titre niveau 2, N°B.1 ci-dessus</td>
<td headers="h_M7">ens</td>
<td headers="h_M9">1</td>
</tr>
</tbody>
</table>
</main>
</body>
updating the JS code as per your changes in question.
this should do what you are trying to do.
// recursive method to get the child of the element
const gc = (a) => {
var children = [];
// loop till the data-level is lower than the parent node or it's a child at the same level.
while (
parseInt(a.next().attr("data-level")) > parseInt(a.attr("data-level")) ||
(parseInt(a.next().attr("data-level")) == parseInt(a.attr("data-level")) &&
a.hasClass("child"))
) {
// if next node is parent call the recursive method
if (a.next().hasClass("parent")) {
var temp = gc(a.next()); // store children in temp var.
children.push({
p: true,
c: temp.c,
n: a.next().get(0),
h: a.next().hasClass("collapsed"),
});
// push the children in array 'p' : to identify if node is parent, 'c' : all child to the element, 'n' : current node, 'h' : to identify if its colapsed.
a = temp.r; // move to the next row (jumping all child rows)
} else {
children.push({ p: false, n: a.next().get(0) }); // if the node is child push without anything
a = a.next(); // move to next row.
}
}
return { r: a.next(), c: children }; // return object 'r' : next row for iteration, 'c' : children of the node a
};
// method to hide/unhide row
const up = (item, show) => {
if (item.p && !item.h) for (var child of item.c) up(child, show); // if the node is parent and not collapsed update all children recursively on all children of the node.
show ? $(item.n).show() : $(item.n).hide(); // show/hide node
};
// on click method for colex tr
$(".colex").on("click", function () {
if ($(this).text() == "") return; // if child do nothing
var show = $(this).text() == "+"; // set if to show or hide on basis of icon value '+' : show, '-' : hide
$(this).text(show ? "-" : "+"); // switch the icon and add/remove the collapsed class
$(this).parent(".parent").toggleClass("collapsed"); // toggle class collapsed
for (var child of gc($(this).parent(".parent")).c) up(child, show); // iterate on all children and show/hide them
});
Let me know if you don't understand anything about it.

How to change classes like schedule in html calendar tables

I have calendar like html tables.like
<td id="1">1</td> <td id="2">2</td> <td id="3">3</td> <td id="4">4</td> <td id="5">5</td>
<td id="6">6</td> <td id="7">7</td> <td id="8">8</td> <td id="9">9</td>
I would like to change its classes like calendar schedule, if I clicked cell2,forward 3day's classes are changed.(I attached images)
①Are there any good way to realize it?
②Are there any other ways to realize schedule like expression(result image is illustrated below),
except for like applying border-bottom options ?
My current attempt is like below.....
.outpatient {
border-bottom: 3px solid yellow;
}
$(function() {
$("td").click(function() {
$(this).addClass('outpatient');
});
});
image is like below.
Thanks
You can try using .nextAll()
Get all following siblings of each element in the set of matched elements, optionally filtered by a selector.
and :lt() selector:
Select all elements at an index less than index within the matched set.
Demo:
$(function() {
$("td").click(function() {
$('td').removeClass('outpatient'); //If you want to reset in each click
$(this).nextAll(':lt(3)').addClass('outpatient');
});
});
table td {
width: 20px;
overflow: hidden;
display: inline-block;
white-space: nowrap;
border: 1px solid gray;
text-align: center;
padding: 5px;
cursor: pointer;
}
.outpatient {
border-bottom: 3px solid yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td id="1">1</td> <td id="2">2</td> <td id="3">3</td> <td id="4">4</td> <td id="5">5</td>
<td id="6">6</td> <td id="7">7</td> <td id="8">8</td> <td id="9">9</td>
</tr>
</table>

How to loop through array with objects inside

Actually its working with simple array
let box1 =[01, 02, 03];
function hitMiss(box) {
$("td").on("click", function(){
let y = $(this).attr("id");
if (box.find(boxId => boxId == y)) {
$(this).addClass("yes");
console.log("full");
} else {
$(this).addClass("no");
console.log("empty");
}
});
};
codepen
But i need to use objects in array
let boxes = [
{ locations: [01, 02, 03]},
{ locations: [23, 24, 25]},
{ locations: [41, 42, 43]}
];
ES6
You can also use reduce() and the spread operator. you can achieve your required result.
CODE SNIPPET
boxes = boxes.reduce((r, {locations}) => [...r, ...locations], []);
DEMO
let boxes = [{
locations: [01, 02, 03]
}, {
locations: [23, 24, 25]
}, {
locations: [41, 42, 43]
}];
hitMiss(boxes);
function hitMiss(box) {
box = box.reduce((r, {
locations
}) => [...r, ...locations], []);
$("td").on("click", function() {
let y = $(this).attr("id");
if (box.some(boxId => boxId == y)) {
$(this).addClass("yes");
console.log("full");
} else {
$(this).addClass("no");
console.log("empty");
}
});
};
html {
background-color: #859cac;
}
table {
margin-right: auto;
margin-left: auto;
}
td {
height: 40px;
width: 40px;
background-color: darkcyan;
border: solid 2px;
border-color: black;
}
.yes {
background-color: red;
}
.no {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td id="00">00</td>
<td id="01">01</td>
<td id="02">02</td>
<td id="03"></td>
<td id="04"></td>
<td id="05"></td>
<td id="06"></td>
</tr>
<tr>
<td id="10"></td>
<td id="11"></td>
<td id="12"></td>
<td id="13"></td>
<td id="14"></td>
<td id="15"></td>
<td id="16"></td>
</tr>
<tr>
<td id="20"></td>
<td id="21"></td>
<td id="22"></td>
<td id="23"></td>
<td id="24"></td>
<td id="25"></td>
<td id="26"></td>
</tr>
<tr>
<td id="30"></td>
<td id="31"></td>
<td id="32"></td>
<td id="33"></td>
<td id="34"></td>
<td id="35"></td>
<td id="36"></td>
</tr>
<tr>
<td id="40"></td>
<td id="41"></td>
<td id="42"></td>
<td id="43"></td>
<td id="44"></td>
<td id="45"></td>
<td id="46"></td>
</tr>
<tr>
<td id="50"></td>
<td id="51"></td>
<td id="52"></td>
<td id="53"></td>
<td id="54"></td>
<td id="55"></td>
<td id="56"></td>
</tr>
<tr>
<td id="60"></td>
<td id="61"></td>
<td id="62"></td>
<td id="63"></td>
<td id="64"></td>
<td id="65"></td>
<td id="66"></td>
</tr>
</table>
Concatenate all the locations using reduce as
var allLocs = boxes.reduce( (a,c) => a.concat(c.locations), [])
Change your internal if-condition to
if (allLocs.find(boxId => boxId == y))
{
$(this).addClass("yes");
console.log("full");
}
else
{
$(this).addClass("no");
console.log("empty");
}
Please find updated pen

css - highlight td elements after finding row

I am trying to highlight some td elements after find the row.
I managed to find the row and td elements in two different steps (commented 'Works OK'). I would like to combine the two steps in a inside a for loop but It is not working.
$(document).ready(function() {
var dt = ['2017-11-02', '2017-11-03'];
cell = $('td:contains("value1")');
// works OK
$(cell).css({
color: "red",
border: "2px solid red"
});
for (var i = 0; i < dt.length; i++) {
// works OK
$('[data-date="' + dt[i] + '"]').css({
background: "blue",
color: "white"
});
// Not Working
//$('td:contains("value1")').find('[data-date="' + dt[i] + '"]').css({background:"blue", color:"white"});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div>
<table>
<tr>
<td>text1</td>
<td>value1</td>
<td data-date="2017-11-01">1</td>
<td data-date="2017-11-02">2</td>
<td data-date="2017-11-03">3</td>
<td data-date="2017-11-04">4</td>
</tr>
<tr>
<td>text2</td>
<td>value2</td>
<td data-date="2017-11-01">1</td>
<td data-date="2017-11-02">2</td>
<td data-date="2017-11-03">3</td>
<td data-date="2017-11-04">4</td>
</tr>
</div>
Regards,
Elio Fernandes
you can replace
$('[data-date="' + dt[i] + '"]').css({
with
$(cell).parent().children('[data-date="' + dt[i] + '"]').css({
you can replace children with find, and replace $(cell).parent() by a different way to focus on the tr.
$(document).ready(function() {
var dt = ['2017-11-02', '2017-11-03'];
cell = $('td:contains("value1")');
// works OK
$(cell).css({
color: "red",
border: "2px solid red"
});
for (var i = 0; i < dt.length; i++) {
// works OK
$(cell).parent().children('[data-date="' + dt[i] + '"]').css({
background: "blue",
color: "white"
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div>
<table>
<tr>
<td>text1</td>
<td>value1</td>
<td data-date="2017-11-01">1</td>
<td data-date="2017-11-02">2</td>
<td data-date="2017-11-03">3</td>
<td data-date="2017-11-04">4</td>
</tr>
<tr>
<td>text2</td>
<td>value2</td>
<td data-date="2017-11-01">1</td>
<td data-date="2017-11-02">2</td>
<td data-date="2017-11-03">3</td>
<td data-date="2017-11-04">4</td>
</tr>
</div>

Categories