'Collapsing columns in a table without jquery by click and by url
for our intranet i've to do a large table with lots of columns. As there are many columns, i want to be able to hide some "blocks" of columns for better overview.
The columns have two headings, one as kind of grouping for the "Progress step" and one under it with details for each step.
I found several solutions but the problem is that it is required to hide each group/step by click, but it should be also possible to have predefined views like a short overview, detailed view, maybe reachable by a url?
Currently the table heading looks like:
<table>
<thead>
<colgroup>
<col>
<col>
<col>
<col span='11' class='step0'>
<col span='2' class='step1'>
<col span='3' class='step2'>
<col span='3' class='step3'>
<col span='3' class='step4'>
</colgroup>
<tr>
<th rowspan='2'>ID</th>
<th rowspan='2'>Name</th>
<th rowspan='2'>State</th>
<th colspan='11'>Step 0</th>
<th colspan='2'>Step 1</th>
<th colspan='3'>Step 2</th>
<th colspan='3'>Step 3</th>
<th colspan='3'>Step 4</th>
</tr>
<tr>
<th>Step 0 - Info 1</th>
<th>Step 0 - Info 2</th>
<th>Step 0 - Info 3</th>
<th>Step 0 - Info 4</th>
<th>Step 0 - Info 5</th>
<th>Step 0 - Info 6</th>
<th>Step 0 - Info 7</th>
<th>Step 0 - Info 8</th>
<th>Step 0 - Info 9</th>
<th>Step 0 - User+Date</th>
<th>Step 0 - Notes</th>
<th>Step 1 - User+Date</th>
<th>Step 1 - Notes</th>
<th>Step 2 - Info</th>
<th>Step 2 - User+Date</th>
<th>Step 2 - Notes</th>
<th>Step 3 - Info</th>
<th>Step 3 - User+Date</a></th>
<th>Step 3 - Notes</th>
<th>Step 4 - Info</th>
<th>Step 4 - User+Date</th>
<th>Step 4 - Notes</th>
</tr>
</thead>
</table>
As i never used jquery (and can't even code JS besides a bit modification of existing scripts, i'd prefer a solution without jquery. If it is much easier with jquery, i'd have a look.
Maybe one column of each group should stay visible, but that could be achieved by modifying the colgroup :)
Thanks in advance!
Solution 1:[1]
jQuery is kind of obsolete, if you don’t need to support quite old platforms. So you’re right in searching for a non-jQuery solution.
It’s not necessary to code JS yourself, as there are plenty of libraries out there that you can use for such purposes. Usually they come in so called packages, which can be installed by means of the node package manager (npm).
Learning how to integrate npm can be quite long, so you can also download libraries (aka scripts) that you might find on the web. It’s important that the download includes all dependencies.
You will need to ask yourself some questions, though, to be able to choose the right library/script:
- What is the UI pattern that you want to use? This will determine your search keyword
- Collapse column-groups into one column? This is called a collapse pattern, I would recommend it due to it’s intuitiveness.
- Have a checklist on your site to hide the step completely from the table?
- Should the solution be accessible to users with situational, temporary or permanent disabilities? Include the keyword accessible or a11y in your search
- The minimum should be keyboard support
- What platforms need to be supported (browser version and operating system)?
- Is there already another JavaScript framework used in the intranet, like jQuery or other?
- You would either like to look for a library that integrates well,
- or one that uses “vanilla” JavaScript, so no framework at all
- Are you using a build system, into which the library should integrate? Ask the architects, if you don’t know
- How much of your solution would you be willing to replace by a library?
- There are Data Grid libraries out there that offer your functionality, but will build the whole table based on JavaScript, instead of simply adding functionality
- or would you like to apply progressive enhancement, meaning you’re simply adding functionality on top of a already fully usable table? (I’d recommend that)
- Which licenses do you accept? There are different open source licenses, that allow you manipulating code or not, and might oblige you to publish any changes you make
Finally, the library will need a mapping between the toggle and the columns to hide somewhere. It can be done in JavaScript only, but I would recommend to use a library that makes use of HTML attributes instead, so that you don’t need to write JavaScript.
If the library is specialised in tables, it might use the already present colspan
attributes to do the mapping.
Otherwise, you might have to provide the mapping with data-
attributes.
So, your search might be like “Accessible collapsible column groups javascript”.
Example with Bootstrap
Here is an example based on Bootstrap’s Collapse Component. Bootstrap is a framework and supports accessibility. Some particularities concerning accessibility in tables might be missing.
Note that you cannot hide cells directly, if you keep the grouping header visible, since the table’s structure would fall apart.
If you go for the checklist solution instead of a collapse pattern, you could use the same component, and reference all cells (including those with colspan) in the data-bs-target
attribute.
…
<thead>
<tr>
<th>
Step 0 - Info 1
<button class="btn btn-light" data-bs-toggle="collapse" data-bs-target=".cell-col-0" aria-expanded="false">Toggle</button>
</th>
…
<th>
Step 1 - User+Date
<button class="btn btn-light" data-bs-toggle="collapse" data-bs-target=".cell-col-1" aria-expanded="false">Toggle</button>
</th>
…
</tr>
…
<tr>
<th><div class="cell-col-0">Step 0 - Info 1</div></th>
…
<th><div class="cell-col-1">Step 1 - User+Date</div></th>
…
</tr>
</thead>
<tbody>
<tr>
<td><div class="cell-col-0">Step 0 - Info 1 - Row 1</div></td>
…
<td><div class="cell-col-1">Step 1 - User+Date - Row 1</div></td>
…
Solution 2:[2]
There is no need to use an unwieldy library. Plain "Vanilla" JavaScript will do. The following lines of code will make a col
within a colgroup
disappear, when you deselect its corresponding checkbox on top of the table:
/* // ===========================================================
// un-comment this section when you run this from your PHP server:
<?PHP $hidden = array(0,2); // hide steps 0 and 2 ?>
const hidden=<?PHP echo json_encode($hidden); ?>;
// ============================================================*/
// stackoverflow mockup of PHP input:
const hidden=[0,2];
const cols = document.querySelectorAll("table col:nth-child(n+4)"),
ttls= [...document.querySelectorAll("table tr.ttl th:nth-child(n+4)")].map(t=>t.textContent),
div = document.querySelector("div");
div.innerHTML=ttls.map(t=>`<label><input type="checkbox" checked>${t}</label>`).join(" ");
const cbs = div.querySelectorAll("input[type=checkbox]");
hidden.forEach(h=>{cols[h].classList.add("hidden");cbs[h].checked=false});
cbs.forEach((cb,i)=>{
cb.addEventListener("change",ev=>cols[i].classList.toggle("hidden",!cb.checked))
});
// enter a few lines of data into the table ... (to make it look more impressive)
document.getElementById("tbd").innerHTML = [...Array(5)].map((_, i) =>
`<tr>${[...Array(25)].map((_,j)=>
`<td>${(i+1)*100+j}</td>`).join("")}</tr>`).join("\n");
td,
th {
border: 1px solid grey
}
.hidden {
visibility: collapse
}
<div></div>
<table>
<thead>
<colgroup>
<col>
<col>
<col>
<col span='11' class='step0'>
<col span='2' class='step1'>
<col span='3' class='step2'>
<col span='3' class='step3'>
<col span='3' class='step4'>
</colgroup>
<tr class="ttl">
<th rowspan='2'>ID</th>
<th rowspan='2'>Name</th>
<th rowspan='2'>State</th>
<th colspan='11'>Step 0</th>
<th colspan='2'>Step 1</th>
<th colspan='3'>Step 2</th>
<th colspan='3'>Step 3</th>
<th colspan='3'>Step 4</th>
</tr>
<tr>
<th>Step 0 - Info 1</th>
<th>Step 0 - Info 2</th>
<th>Step 0 - Info 3</th>
<th>Step 0 - Info 4</th>
<th>Step 0 - Info 5</th>
<th>Step 0 - Info 6</th>
<th>Step 0 - Info 7</th>
<th>Step 0 - Info 8</th>
<th>Step 0 - Info 9</th>
<th>Step 0 - User+Date</th>
<th>Step 0 - Notes</th>
<th>Step 1 - User+Date</th>
<th>Step 1 - Notes</th>
<th>Step 2 - Info</th>
<th>Step 2 - User+Date</th>
<th>Step 2 - Notes</th>
<th>Step 3 - Info</th>
<th>Step 3 - User+Date</th>
<th>Step 3 - Notes</th>
<th>Step 4 - Info</th>
<th>Step 4 - User+Date</th>
<th>Step 4 - Notes</th>
</tr>
</thead>
<tbody id="tbd"></tbody>
</table>
I am not sure whether this will work on all browsers, but I tested it successfully on Chrome, Edge and Firefox.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |