Categories

Request Script

Donate

Sortable Table… Updated!

After using my original Sortable Table for some time now, I’ve noticed something that could be better. Namely, type-awareness! I added the ability to declare each column as containing common type of data like numbers and dates as well as giving the functionality to enable writing custom sort functions.

Source: sortableTable.js
Example: Example

To declare a column as containing numbers, give the associated thclass="number". As you may guess, it basically just parses the string as a float (using parseFloat) before comparing, so “11″ will come after “2″. To sort dates, add class="date" to the th. This simply uses the Date.parse function before comparing.

Now that the “easy” ones were out of the way, I thought about how to give the developer a way to define their own sorting function, since strings, numbers, and dates won’t be the only things that should exist in a sortable table, for example, move ratings.

To do this, add class="custom_sortFunc" to your th where sortFunc is the JavaScript function you want to use to sort. This function should take two arguments and return an integer. The return value should be less than 0 if the first argument should be before the second, 0 if they’re equal sort-wise, and greater than 0 if the first should go after the second.

In the example, you see the following:

var movieRatings = new Array('G', 'PG', 'PG-13', 'R', 'NR');
function movieRatingSort(str1, str2)
{
	return movieRatings.indexOf(str1) - movieRatings.indexOf(str2);
}

My movie ratings th has class="custom_movieRatingSort". That’s all!

Note that there is no error checking in the way of checking to see that the custom sort function takes two arguments nor that the return type is an int, so funky things may happen if you give it an invalid function.

Sortable Table

This article will describe a javascript which will make any <table> sortable on all columns.

Update: Thanks to a comment to this post, I corrected a problem with Firefox. I am now using textContext for non-IE browsers as it’s more widely supported.

Update 2: I’ve written a follow up to this article adding additional functionality not mentioned in this article.

Source: sortableTable.js

Example: Example

Here is an example (the above link will be better for looking at the HTML source):

Name Age Email Phone
Jon Doe 21 jon@doe.com 111-111-1111
Joe Bob 20 joe@bob.com 222-222-2222
Fake Guy 25 fake@guy.com 555-555-5555

With the javascript included, the table needs to have class sortableTable, exactly one <thead> with exactly one row, and exactly one <tbody>.

To make a particular column the default sorted column (it’s be sorted upon the initial page load), add the class defaultSort to the particular <th> in the one row in <thead>.

The javascript also automatically adds the classes even and odd to the even and odd numbered rows for ease of styling.

The sorting is done based off of the innerText textContent of each cell, so if the cell contains HTML and you are expecting it to sort in that way, it may be sorted differently. For example, if one cell had <a href="federmanscripts.com">Z</a> and another had <b>A</b>, the cell containing “Z” would be before the one containing “A” if innerText textContent was used, but with innerText textContent the “A” would come first, as expected by the user. In short, the displayed text in the cell is what the column is sorted by.

Form and Table Row Nesting Workaround

Have you ever tried to nest elements in a way that is valid as far as XML is concerned, but isn’t “valid”? For example, have a table containing a different form per table row? This article describes a workaround for that.

So no matter how much you may hate tables in HTML, sometimes it just makes life much easier. Now I don’t want to get into a Div vs Table discussion, but I think we can at least agree that tables have a place and most of us use them at some point.

To set the stage, basically I was making a content management system for a client, and so I had several items with several editable properties. The most straightforward way I thought to implement this is to have a table, with one item per row, one property per column. For example:

Name Email

The only real problem is that structurally we’d have <table><form><tr>…</tr></form></table>, which is not valid, and actually doesn’t work in Google Chrome.

Now, before anyone suggests just surrounding the table with one huge form, the table was dynamic (using php in my case) and could have arbitrarily many rows. Thus the entire form, including fields that weren’t even being used, would be sent every time a row was to be updated by the user. This greatly increases the amount POSTed. Not only that, but fields would need to be named something akin to name1, email1, name2, email2, etc. and that’s just a huge mess on the back-end.

My solution uses an invisible form outside of the table and javascript. The gist is once the submit button is pressed, move all input, select, and textarea elements from the desired “virtual form” to the invisible form and submit that invisible form.

Example: Here

In my example, which is basically identical to the above table, I’ve added the invisible form, the necessary javascript function, the class “form” to the table rows, and onclick="submitForm(this);" to the submit buttons.

You can add the “form” class to whichever container you want which defines your “form” as the javascript just takes the submit button and keeps going up the node tree until it hits a node with class="form".

Do note that because the submit button isn’t actually being clicked as far as the invisible form is concerned, the javascript converts the button into a hidden field so that the button name-value pair still appear in the POST.

Also note that since elements are being shuffled around, there is a slight “flicker” after the submit button is pressed, but before the page reloads. There are workarounds to this if absolutely necessary, but most users won’t care or even notice.

While all the code is very straightforward and easy to understand, it can be pretty powerful and hopefully prevent a lot of headaches and/or code rearrangement/hacks.