patternjavascriptMinor
Hide and show columns in an HTML table
Viewed 0 times
showcolumnstableandhidehtml
Problem
Codepen Link
I've tried to Google, but there's no library that has an API to toggle table columns when clicked elsewhere on the page, so I've decided to do this:
Is this an awful solution? If yes, how do I refactor it?
I've tried to Google, but there's no library that has an API to toggle table columns when clicked elsewhere on the page, so I've decided to do this:
function deleteColumnOnClick() {
$('.hide div').click(function() {
var index = $(this).index();
$('table thead th').eq(index).toggleClass('hidden');
var hidden = $('table thead th.hidden')
$.each(hidden, function() {
var idx = $(this).index();
$.each($('table tbody tr'), function() {
$(this).find('td').eq(idx).hide();
});
});
var visible = $('table thead th:not(.hidden)');
$.each(visible, function() {
var idx = $(this).index();
$.each($('table tbody tr'), function() {
$(this).find('td').eq(idx).show();
});
});
});
}
deleteColumnOnClick();Is this an awful solution? If yes, how do I refactor it?
Solution
Right now, the relationship between the hide/show "buttons" and the columns is pretty fragile. You're dependent on the buttons being in the same exact order as the columns. If you add or remove a button, the indices stop making sense; you can't rely on the 3rd button always being linked to the 3rd column and vice versa.
I'd suggest giving the buttons (or whatever element you use to hide/show columns) a
For instance:
Now it's explicit that the button will hide column
Secondly, you're (in a sense) trying to both hide and show the column, and just seeing what works. It'd be simpler to just do a
Something like this, for instance:
Here's a demo
I'd suggest giving the buttons (or whatever element you use to hide/show columns) a
data-column attribute or something similar to make it explicit that this button controls that column. Similarly, the th cells can carry a data-column attribute or simply an ID to identify them.For instance:
Hide/show
A column
Another column
Yet another column
...Now it's explicit that the button will hide column
#column-abc. And it'll simplify the code too, since relationships between things are no longer just assumed or implied.Secondly, you're (in a sense) trying to both hide and show the column, and just seeing what works. It'd be simpler to just do a
hasClass("hidden") check. There are also some jQuery selector magic you can use.Something like this, for instance:
// global click handler for any element with a "data-column" attribute
$("[data-column]").on("click", function () {
var button = $(this), // the element that was clicked
header = $(button.data("column")), // the cell referenced by the button
table = header.closest("table"), // the table in which the cell resides
index = header.index() + 1, // convert to CSS's 1-based indexing
selector = "tbody tr td:nth-child(" + index + ")", // selector for all body cells in the column
column = table.find(selector).add(header); // all cells in the column
// toggle the "hidden" class on all the column cells
column.toggleClass("hidden");
});Here's a demo
Code Snippets
<button type="button" data-column="#column-abc">Hide/show</button>
<table>
<thead>
<tr>
<th id="column-foo">A column</th>
<th id="column-xzy">Another column</th>
<th id="column-abc">Yet another column</th>
</tr>
</thead>
...// global click handler for any element with a "data-column" attribute
$("[data-column]").on("click", function () {
var button = $(this), // the element that was clicked
header = $(button.data("column")), // the cell referenced by the button
table = header.closest("table"), // the table in which the cell resides
index = header.index() + 1, // convert to CSS's 1-based indexing
selector = "tbody tr td:nth-child(" + index + ")", // selector for all body cells in the column
column = table.find(selector).add(header); // all cells in the column
// toggle the "hidden" class on all the column cells
column.toggleClass("hidden");
});Context
StackExchange Code Review Q#83839, answer score: 9
Revisions (0)
No revisions yet.