/* ---- < MAIN FUNCTION > ---- */
function tableToTree(table_Selector, tr_OpenedClass, tr_VisibleClass, tr_ToggleButton) {
// Table elements variables
var table = document.querySelector(table_Selector);
var trs = document.querySelectorAll(table_Selector + " tr");
// Add the buttons above the table
var buttons = document.createElement('div');
buttons.innerHTML = '<button>[‒] All</button><button>[+] All</button>';
table.insertBefore(buttons, table.childNodes[0]);
buttons = buttons.querySelectorAll('button');
// Add the actions of these buttons
buttons[0].addEventListener("click", function() {
trs.forEach(function(elm) {
elm.classList.remove(tr_OpenedClass);
elm.classList.remove(tr_VisibleClass);
});
});
buttons[1].addEventListener("click", function() {
trs.forEach(function(elm) {
if (elm.innerHTML.includes(tr_ToggleButton))
elm.classList.add(tr_OpenedClass);
elm.classList.add(tr_VisibleClass);
});
});
// Next tr function
function nextTr(row) {
while ((row = row.nextSibling) && row.nodeType != 1);
return row;
}
// On creation, automatically add toggle buttons if the tr has childs elements
trs.forEach(function(tr, index) {
if (index < trs.length - 1) {
if (+tr.getAttribute("level") < +trs[index + 1].getAttribute("level")) {
var elm1 = tr.firstElementChild;
elm1.innerHTML = tr_ToggleButton + elm1.innerHTML;
}
}
});
// Use the buttons added by the function above
table.addEventListener("click", function(e) {
// Event management
if (!e) return;
if (e.target.outerHTML !== tr_ToggleButton) return;
e.preventDefault();
// Get the parent tr and its level
var row = e.target.closest("tr");
row.classList.toggle(tr_OpenedClass);
var lvl = +(row.getAttribute("level"));
// Loop to make childs visible/hidden
while ((row = nextTr(row)) && ((+(row.getAttribute("level")) == (lvl + 1)) || row.className.includes(tr_VisibleClass))) {
row.classList.remove(tr_OpenedClass);
row.classList.toggle(tr_VisibleClass);
}
});
}
/* ---- </ MAIN FUNCTION > ---- */
// Call the above main function to make the table tree-like
tableToTree('#myTable', 'opened', 'visible', '<span class="toggle"></span>');
tbody tr {
display: none;
}
tr[level="0"],
tr.visible {
display: table-row;
}
td {
background: #ccc;
padding: 4px 8px 4px 32px;
text-align: left;
}
tr[level="1"] td {
background: #ddd;
padding-left: 40px;
}
tr[level="2"] td {
background: #eee;
padding-left: 48px;
}
tr .toggle {
position: absolute;
left: 16px;
cursor: pointer;
}
.toggle::after {
content: "[+]";
}
.opened .toggle::after {
content: "[‒]";
}
<table id="myTable">
<tbody>
<tr level="0">
<td>Parent 1</td>
</tr>
<tr level="1">
<td>Match 1</td>
</tr>
<tr level="1">
<td>Match 2</td>
</tr>
<tr level="0">
<td>Parent 2</td>
</tr>
<tr level="1">
<td>Mismatch 1</td>
</tr>
<tr level="1">
<td>Mismatch 2</td>
</tr>
<tr level="2">
<td>Mismatch 2.1</td>
</tr>
</tbody>
</table>
<br>