E-Scribe News : a programmer’s blog

About Me

PBX I'm Paul Bissex, and e-scribe.com is my consulting business. I build web applications using open source software, especially Django. In the '90s I did graphic design for newspapers and magazines. Then I wrote technology commentary and reviews for Wired, Salon.com, Chicago Tribune, and lots of little places you've never heard of. Feel free to email me.

Book

Python Web Development with Django I'm co-author of "Python Web Development with Django", an excellent guide to my favorite web framework. Published by Addison-Wesley, it is available from Amazon and your favorite technical bookstore as well.

Colophon

Built using Django, served by Apache and mod_wsgi. The database is SQLite. The operating system is FreeBSD, on a VPS hosted at Johncompanies.com. Comment-spam protection by Akismet. Vintage topo imagery from the Maptech archive. The markup engine is Markdown.

Pile o'Tags

Stuff I Use

Akismet, del.icio.us, Django, dpaste.com, Emacs, FreeBSD, Freenode, jQuery, LaunchBar, MacPorts, Markdown, Mercurial, OS X, Postfix, Python, SQLite, Subversion, TextMate, Trac, Ubuntu Linux, wmii

Spam Report

At least 70644 pieces of comment spam killed since January 2008, mostly via Akismet.

Sort tables with sorttable.js

I've been enjoying listening to the "Audible Ajax" podcasts from Ajaxian lately. One of the older shows was a talk by Lugradio's Stuart Langridge in which, in an aside, he mentioned a table sorting widget he had written. It sounded cool. When I got home I fired up the browser and found it: sorttable.js.

Even though it's over two years old and doubtless there are a bazillion Ajax (tm) toolkits that include supersets of this functionality, I find it to be a very elegant thing. Largely that's because of its utterly configuration-free operation. As long has you've put <th> headers on your table, you just include the script in your page, and set class="sortable" and a unique id on each of your table(s); clicking on a table header re-sorts the table by that column, without any action on the server side at all.

It took me about two minutes to use sorttable.js to add instant sorting to my (possibly-never-to-be-released) "CRUDLite" content management system. Thanks, Stuart!

Monday, February 20th, 2006
+ +
17 comments

Comment from Stuart Langridge , later that day

No problem. Glad you like it :)

Comment from Rodrigo Perez , 1 week later

Having a hardtime trying to sort dates in the following format: 3/2/2006 11:42:59 AM , 3/2/2006 04:20:05 PM , 3/2/2006 03:21:31 PM. Some are not ordered right, will investigate

Comment from Paul , 1 week later

The docs have this to say:

> (Note that the date function is keyed towards UK format dates (dd/mm/[cc]yy) and will need poking for dates in other formats.)

Comment from Shay , 3 weeks later

Just found sortable.js, so easy to setup and use. Thanks Stuart!!

Comment from Cherise ~^..^~ , 12 months later

I'm trying to get sorttable set up on my website, but it's not working. I'm not sure if I'm installing everything correctly. Can someone help me?

I've put the .js file in the same folder where I have my html pages.

This is my code:

<html>
<head>
<title>
~^..^~ ebontigress.com
</title>
<meta name="GENERATOR" content="Arachnophilia 5.2">
<meta name="FORMATTER" content="Arachnophilia 5.2">
<link rel="stylesheet" type="text/css" href="./ebonstyles.css"/>
<script type="text/javascript" src="sorttable.js"></script>

<style type="text/css">
/* Sortable tables */
table.sortable a.sortheader {
background-color:#eee;
color:#666666;
font-weight: bold;
text-decoration: none;
display: block;
}
table.sortable span.sortarrow {
color: black;
text-decoration: none;
}
</style>
</head>

<body>

<table class="sorttable" id="pgrmbkSpecial" width="100%" border="2" cellspacing="1" cellpadding="2">
<tr>
<th>Rcvd</th>
<th>Guest</th>
<th>Handle</th>
<th>Co./Firm</th>
<th>Award</th>
<th>Bio</th>
<th>Pic (300 dpi res)</th>
</tr>

<tr>
<td>12 Feb</td>
<td>Robin D. Laws</td>
<td>nil</td>
<td>Freelance</td>
<td>Innovation in the Gaming Industry</td>
<td>rcvd</td>
<td>rcvd</td>
</tr>

<tr>
<td>15 Feb</td>
<td>Jamie Chambers</td>
<td>nil</td>
<td>Margaret Weiss Productions</td>
<td>Media Adaptation in Gaming</td>
<td>rcvd</td>
<td>rcvd</td>
</tr>

<tr>
<td>remit ASAP. Lft vm w/ Jamie 15 Feb.</td>
<td>Renae Chambers</td>
<td>HANDLE</td>
<td>Margaret Weiss Productions</td>
<td>nil</td>
<td>remit ASAP</td>
<td>remit ASAP</td>
</tr>

<tr>
<td>15 Feb</td>
<td>Randall N. Bills</td>
<td>HANDLE</td>
<td>FanPro/BattleTech</td>
<td>nil</td>
<td>rcvd</td>
<td>rcvd</td>
</tr>

<tr>
<td>15 Feb</td>
<td>Tara S. Bills</td>
<td>HANDLE</td>
<td>FanPro/BattleTech</td>
<td>nil</td>
<td>rcvd</td>
<td>rcvd</td>
</tr>

<tr>
<td>remit ASAP. email read 14 Feb.</td>
<td>Mike Pondsmith</td>
<td>maxmike!!</td>
<td>R. Talsorian</td>
<td>nil</td>
<td>use last year's or update?</td>
<td>use last year's or update?</td>
</tr>

<tr>
<td>remit ASAP. Lft vm + txt 15 Feb. Pending</td>
<td>Eric Lang</td>
<td>HANDLE</td>
<td>Fantasy Flight Games</td>
<td>nil</td>
<td>remit ASAP</td>
<td>remit ASAP</td>
</tr>

<tr>
<td>remit ASAP</td>
<td>NAME</td>
<td>HANDLE</td>
<td>FIRM</td>
<td>nil</td>
<td>remit ASAP</td>
<td>remit ASAP</td>
</tr>

</table>

</body>
</html>

Thank you,

~^..^~
Cherise

Comment from Paul , 12 months later

Hi Cherise, I've found that the single biggest aid to troubleshooting stuff like this is to use diagnostic tools like [Firebug](http://getfirebug.com/). Even just opening a JS console window can sometimes do the trick. You may find, for example, that the JS isn't loading at all, or that there's some other silent error happening.

Comment from Jennifer , 14 months later

I've been using sortable.js for years. I've found it very useful!

Comment from raja , 14 months later

sorttable.js is working fine if I put columns in "th" and values in "td" tags. But its not working if i keep values in `<td><input name "value to sort"tag</td>` so can anyone suggest how to handle this situation.I have few columns with "td"and only one column with "td" input tag "/td"tag.So sorttable.js is not handling this situation.

Regards Raja

Comment from Erin , 23 months later

I had the same issue as Raja. After some debugging I determined I was never getting to this section of getInnerText:

switch (node.nodeType) {

case 3:

if (node.nodeName.toLowerCase() == 'input') {

return node.value.replace(/^\s+|\s+$/g, '');

}

So I modified the function to have this:

if (node.nodeName.toLowerCase() == 'input') {
return node.value.replace(/^\s+|\s+$/g, '');
} else if (node.getAttribute("sorttable_customkey") != null) {

Comment from Mari , 2 years later

The error is class="sorttable" the correct is class="sortable". Only one "t"

Comment from Hugo Pineda , 3 years later

Hi, I'm trying to sort a table generated by Ajax using prototype, it seems the class="sortable" has the initial document scope, so the loaded "sortable" table is ignored by the script.

Any ideas how to make the ajax generated table "sortable"

Thanks.

PS. I bought your django book, it's great, good job!

Comment from Hugo Pineda , 3 years later

SOLVED: in the code returned by ajax if I put this script then the table becomes sortable:

<script type="text/javascript">
sorttable.makeSortable($('ajax_table'));
</script>

Where 'ajax_table' is the id of the ajax returned table.

Cheers!

Comment from Hugo Pineda , 3 years later

the code dissapears from the prev. post: here is again without the scrip tag:

sorttable.makeSortable($('ajax_table'));

Comment from DAn , 3 years later

jquery has a similar script. the docs are very clean, while configuration is a bit more versatile and easy to globalize/scale with one-off meta-data when needed.

http://tablesorter.com/docs/index.html

Comment from sagar , 3 years later

hi can we use the same in display table as well

Comment from SK , 4 years later

Hi,

I am generating the table from AJAX script and trying to sort it. But I am not able to do so. Can you please help me?

Find enclosed my code that is called by AJAX.

<?php

//mysql db connection defined

$from = $_GET['from'];
$to = $_GET['to'];

$from = mysql_real_escape_string($from);
$to = mysql_real_escape_string($to);

$query1 = "SELECT MMM_DD FROM mdnumbers WHERE BINARY MMM_DD='$from';";
$res1 = mysql_query($query1);

$query2 = "SELECT MMM_DD FROM mdnumbers WHERE BINARY MMM_DD='$to';";
$res2 = mysql_query($query2);

if (mysql_num_rows($res1)>0 && mysql_num_rows($res2)>0)
{
$fvalue = mysql_query("SELECT MDvalue FROM mdnumbers WHERE MMM_DD = '$from'");
$fromvalue1= mysql_result($fvalue, 0);

$tvalue = mysql_query("SELECT MDvalue FROM mdnumbers WHERE MMM_DD = '$to'");
$tovalue1= mysql_result($tvalue, 0);

$result = mysql_query("SELECT * FROM annotations WHERE DayOfYear BETWEEN $fromvalue1 AND $tovalue1 ORDER BY DayOfYear");

if (mysql_num_rows($result)>0)
{
echo '<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">' . "\n";
echo '<head>';

echo '<script type="text/javascript" src="sorttable.js"></script>';
echo '<script type="text/javascript">
sorttable.makeSortable($atable);
</script>';

echo'</head>';

echo '<body>' . "\n";
echo '<table id="atable" class="sortable">';

echo '<tr>';
echo '<th>Day</th>';
echo '<th>Year</th>';
echo '<th>Category</th>';
echo '<th>Annotation</th>';
echo '<th>Link</th>';
echo '</tr>';

while($row = mysql_fetch_array($result))
{
echo "<tr>";
echo "<td>".$row['MMM_DD']."</td>";
echo "<td>".$row['Year']."</td>";
echo "<td>".$row['Category']."</td>";
echo "<td>".$row['Annotation'] ."</td>";
echo "<td><a href=" .$row['Link']. ">" .$row['Link']. "</a> </td>";
echo "</tr>";
}

echo "</table>";

echo "</body>\n";
echo "</html>\n";
}
else
{
echo "No Annotations to display for the selected period";

}
}
else
{
echo "Please enter FROM and TO values in proper format. Examples: Jan-23, Nov-14, Sep-15.";
}
mysql_close($db);
?>

Comment from aman , 4 years later

it do not work even by including
<script type="text/javascript">
sorttable.makeSortable($('ajax_table'));
</script>

Post a comment

Thanks for reading! Please note: Your comment will not appear until approved, which may take a few hours or more. Spammers will be torpedoed.


(Will not be shared)

(Optional)