Using JQuery to create a table with folding details rows

I improved an implementation of a table in which each row is clickable to toggle the visibility of a detail row below it. The previous implementation gave each row a numbered id, and applied a separate onClick function to each row. I realised a more efficient approach would be to apply appropriate classes to the table, and use a function that runs across the table and applies the appropriate event handlers.

The table is structured approximately like this (I’ve left out a header row and other complications).

Each summary row of the table has the class summary. The class hide is used to hide the details row – all the details rows start with this class set. When a summary row is clicked the first time, the class selected is applied to that row, and the class hide removed from its detail row (the row below it). When the row is clicked again, the class selected is removed from that row, and the class hide applied to the detail row.

I’ve seen people saying things like “why use jQuery, when you can just use javascript”, and as javascript support gets more mature, this is a fair point. For me, the simplicity and ease of jQuery style coding appeals – I especially enjoy the way function calls are chained.

The next challenge was a change request to add an Expand All button to the header above the table. The markup is approximately like

In the selector to find the Expand All control, $(tableSelector).prevAll(headingSelector).find(expandAllSelector), I use prevAll because the header is not always the element immediately before the table. It’s pretty easy to see what’s going on. If an Expand All element is found, its click event is wired up.

On a click, the event handler works out if the Expand All control is currently open, updates its CSS class and text accordingly, and then selects or unselects all the summary rows as appropriate. The only bit of this code I don’t really like is having the text “Collapse all” and “Expand all” hardwired into the javascript. If I did this now, I’d consider attaching the text using HTML 5 data attributes, or find some similar scheme to include the text in the HTML of the table and header.

So the next time you’re looking at adding some javascript to a certain type of element on a page, rather than individually wiring up the elements, consider if you can apply an approach like this, where you add behaviour to elements that match a certain CSS selector. It’s much easier to understand, and makes for a better experience for your website users. Rather than lots of javascript being generated everytime your page is loaded, you can include the javascript in your common javascript file. The common javascript file will be cached, and only a small piece of javascript to run your function will be needed for each page. And rather than having javascript scattered throughout the pages of your site, it lives in a centralised location.