I'm trying to make a collapsable table for a project, and so far I'm succeeding pretty well. I'm only encountering one problem that I can't figure how to manage : Actually my collapsable rows (the ones which have children) are collapsing, but if I collapse a child, then the parent, and then I expand the parent, the children is expanded as well. How can I save the state of the children so that they don't expand when we expand the parent?
$(document).ready(function() {
// Define color depending on the M1 cell value //
var rows = document.getElementsByTagName("tbody")
[0].getElementsByTagName("tr");
// loops through each row
for (i = 0; i < rows.length; i ) {
cells = rows[i].getElementsByTagName('td');
if (cells[2].innerHTML == '1')
$(cells).parent().addClass('Titre_1');
if (cells[2].innerHTML == '2')
$(cells).parent().addClass('Titre_2');
if (cells[2].innerHTML == '3')
$(cells).parent().addClass('Titre_3');
if (cells[2].innerHTML == '4')
$(cells).parent().addClass('Titre_4');
if (cells[2].innerHTML == '5')
$(cells).parent().addClass('Titre_5');
if (cells[2].innerHTML == '6')
$(cells).parent().addClass('Titre_6');
if (cells[2].innerHTML == '7')
$(cells).parent().addClass('Titre_7');
if (cells[2].innerHTML == '8')
$(cells).parent().addClass('Titre_8');
if (cells[2].innerHTML == '9')
$(cells).parent().addClass('Titre_9');
}
// Expand/collapse when clicking on first column //
function getChildren($row) {
var children = [], level = $row.attr('data-level');
while($row.next().attr('data-level') > 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 children = getChildren($(this).parent('.parent'));
$.each(children, function() {
if(action == "show") {
$(this).removeClass('collapsed').show();
} else {
$(this).addClass('collapsed').hide();
if($(this).children('.colex').text() == ' ') { // Replace possible ' ' by a '-' when parent's collapsed //
$(this).children('.colex').text('-');
}
}
});
})
})
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;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Devis</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<intro>
<p >description</p>
</intro>
<main>
<table id="mytable" align=center rules=groups frame=box hborder=0 cellspacing=1 cellpadding=4 vborder=1>
<thead >
<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 data-level="0">
<td headers="colex" >-</td>
<td headers="h_M8"><input 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 data-level="1">
<td headers="colex" >-</td>
<td headers="h_M8"><input 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 data-level="2">
<td headers="colex" ></td>
<td headers="h_M8"><input 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 2, N°A.1 ci-dessus</td>
<td headers="h_M7">km</td>
<td headers="h_M9">6</td>
</tr>
<tr data-level="2">
<td headers="colex" ></td>
<td headers="h_M8"><input 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 2, N°A.1 ci-dessus</td>
<td headers="h_M7">m</td>
<td headers="h_M9">10,5</td>
</tr>
<tr data-level="0">
<td headers="colex" >-</td>
<td headers="h_M8"><input type="checkbox"></td>
<td headers="h_M1">1</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 data-level="1">
<td headers="colex" >-</td>
<td headers="h_M8"><input type="checkbox"></td>
<td headers="h_M1">2</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 data-level="2">
<td headers="colex" >-</td>
<td headers="h_M8"><input type="checkbox"></td>
<td headers="h_M1">3</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 data-level="3">
<td headers="colex" ></td>
<td headers="h_M8"><input 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 data-level="3">
<td headers="colex" ></td>
<td headers="h_M8"><input 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 data-level="2">
<td headers="colex" ></td>
<td headers="h_M8"><input type="checkbox"></td>
<td headers="h_M1">3</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>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="voctor.js"></script>
</body>
</html>
CodePudding user response:
If I correctly understood your issue, you want to be able to open a "parent" without opening its children.
But then, why did you write your code to do so ?
See the culprit in the code bellow:
var children = getChildren($(this).parent('.parent'));
$.each(children, function() {
if(action == "show") {
/* HERE : This line only purpose is to display the children when a parent is displayed */
$(this).removeClass('collapsed').show(); // <-- DELETE THIS
} else {
$(this).addClass('collapsed').hide();
if($(this).children('.colex').text() == ' ') { // Replace possible ' ' by a '-' when parent's collapsed //
$(this).children('.colex').text('-');
}
}
});
EDIT: Since your requirements have changed you need to review your logic.
What we know:
- only parents can be collapsable
- opening parents should only reveal their direct children AND the sub-children that were not previously hidden
To achieve this behavior, we'll need to make a difference between a collapsed parent AND its hidden children.
See the changes in the code :
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();
}
});
I edited your Fiddle with the new code if you want to test it.
I also replaced your multiple if
statements with a single line :
$(cells).parent().addClass('Titre_' cells[2].innerHTML);