Sorttable v2: making your tables even more sortable
Sorttable, the JavaScript table sorting library, is pretty much the most popular thing I’ve ever written. (Top hit for “javascript sort table” on Google, too.) Over the four years or so since I first released it, there’s been a steady trickle of thanks, feature requests, and bug fixes to it. I’ve finally got around to releasing a new version of the script that hopefully covers everything that people were looking for. You can get it at the same place as it ever was, sorttable: Make all your tables sortable.
What’s changed in version 2
The most important thing that’s changed is that sorttable now has a much much clever automatic column typer. You still can just drop sorttable in place and not have to do any configuration, but it’s quite a bit cleverer about working out whether your columns are numeric or dates or currency or text. It skips blank lines, it can tell the difference between English and American format dates, it understands numbers with commas in and negative numbers. This is the number one feature request.
Secondly, you can now use custom sort keys for those columns that sorttable can’t work out for itself. See the page for details, but this should allow anyone to make anything work with sorttable v2.
It’s also a bit more compliant with HTML standards. To add a “totals” row you should add the row to a <tfoot> section in your table. Sorttable v1 used a class of “sortbottom” on totals rows; for backwards compatibility this is still supported, but you really should be using <tfoot> instead.
In a similar way, sorttable now uses <thead> as your column headers if you have it. If you do not have it then it will create a <thead> and put the first row of your table in it. This is a backwards incompatible change: to apply style to your table headers, you should now style table.sortable thead, not table.sortable a.sortheader as in v1.
Input elements are now supported in table cells! If your table cells contain input elements then sorttable will use the value in the input element.
Sorttable is now quite a lot faster than it used to be, owing to various little tweaks. It’s especially fast at resorting the table by the column you’ve already sorted by (but reversed), because now it just reverses the table rather than doing the sort.
Stable sorting is supported but commented out in the code (because the stable sort is implemented in JavaScript, not using the native list sorter, and so it’s a lot slower). You can change this by editing one line in sorttable.js if stable sorting is important; see the page for details.
Thanks
Lots of people (really, really lots) have contributed code suggestions, feature requests, bug reports, and compliments about sorttable. Here’s my chance to say thankyou. So: thankyou to…
Eric Chang, Mehmet Kut, Dan Synder, Jeff Bradley, Eric Holstege, Victor Kryukov, Nikola Ivanov, Geoff Clevenger, Mikko Suniala, Scott Reynen, Justin Meyer, Leonardo Kenji Shikida, Ben Ostrowsky, Daniel Berlin, Richard Snazell, Mark James, Eric Rizzo, Garve, Andreas Rehm, Scott Kingdon, Marcus Månsson, Bill Barry, Michael Rumpler, Avi Rogers, Kevin Wu, Espen Hovlands, Petronel Laviniu Malutan, John M. Pierre, opus27, Brendan Bowles, Marty O’Brien, Alex Rubin, Chris Gay, Jack Vanhan, Guy Rosen, John Dawson, Ryan Korczykowski, Carl Forde, Pete K, Glenn Haser, Richard Grassy, Olivier Briat, Bob Hanson, Alex Z, Narayana Rao Kankipati, Rey Hernandez, Eric Moriztz, Marco Valk, Marcus Daniel, David Dockhorn, Angela Weise, Aneel Nazareth, Jeremy Hulford, Thomas K. Weinstock, Edward, Matthew Egbers, Anton Berezin, Moustafa Elqabbany, Justin Williams, Daniel Chace, Inigo Surguy, Vladimir Kornea, John Mund, Pablo, David Golden, Brad Kemper, Brian Schott, Christian Robottom Reis, Justin Haygood, C. David Eagle, Simon Willison, and Dean Edwards.
Phew! All those people have contacted me asking for new features or have sent me patches or have provided code that I was able to reuse in v2 of sorttable. Thankyou: for those of you who wanted sorttable to do something new, I hope you like it.
Oh..you’re where I got that code from. Thanks!
104 minutes later
dsas: no problem. :)
2 hours later
if i have more than one row in header, I want to do sort by the last header row, how can I set it?
thx
8 hours later
margiex: you can’t, I’m afraid. Sorttable doesn’t support tables with more than one header row, because it gets a bit confused by them.
13 hours later
It would be nice if a third click on a header would revert the table back to the original sort, rather than just toggling ascending and descending on that column.
Just a thought ;)
20 hours later
mrben: daresay it would, but that would mean caching the table structure, which I’d like to avoid :) If you want that, hit refresh.
20 hours later
Why would it mean caching the table structure? Surely you could define the default sort somewhere, and then re-run that particular sort on every third click of a header? Or have I over-simplified?
28 hours later
mrben: there isn’t a “default sort”; there’s just “what the table looked like when it got served from the server”, which could be in any order at all or even no order.
28 hours later
Ah. Point taken. Shame ;)
38 hours later
mrben: hence “hit refresh” to get that order back.
38 hours later
[...] Follow any comments here with the RSS feed for this post. Post a comment or leave a trackback: Trackback URL. « Discussion List, Crossdomain.xml forFlash [...]
2 days later
Would it be possible to add some extra variables to the makeSortable() function, like:
makeSortable($(’table’), ‘header’, ‘ASC’);
Where the last two can the name of the header and sorting order you’d like to use for sorting immediately instead of just adding the event listeners.
3 days later
tommie: Sorttable doesn’t support sorting the table as soon as the page is loaded. There are some notes as to why not in the old sorttable documentation (see “Sorting a table the first time the page is loaded”).
4 days later
In Netscape 8 this script close the window. There is a solution for this?
6 days later
Stuart: I’ve just had the inevitable “client-side sorting” request on a new project I’m working on. Less than 5 minutes later, we had it working. Thanks a lot for this script, I owe you a drink.
7 days later
Nice job! If I could only get it to work :(
When I include your script file in my Asp.net AJAX site I get the following error.
Error Sys.ArgumentTypeException: Object of type ‘Object’ cannot be converted to type ‘Array’
Parametername:array
This occurs even if I don’t have any sortables defined.
Any Ideas?
The error is occuring in a file calse ResourceScript.axd
Here is the function
Array.forEach = function Array$forEach(array, method, instance) {
///
///
///
var e = Function._validateParams(arguments, [
{name: "array", type: Array, elementMayBeNull: true},
{name: "method", type: Function},
{name: "instance", mayBeNull: true, optional: true}
]);
if (e) throw e;
for (var i = 0, l = array.length; i
8 days later
I’ve narrowed it down further and the code below in the sorttable init function is causing the error.
forEach(document.getElementsByTagName(’table’), function(table) {
if (table.className.search(/\bsortable\b/) != -1) {
sorttable.makeSortable(table);
}
});
I’m not as versed in Javascript as you are so any help would be appreciated.
8 days later
Got it working. It took 2 code changes. Basically it was erroring on function(table) and onsort it error on function(Cell). I’ve include my new code in case it helps someone else.
// forEach(document.getElementsByTagName(’table’), function(table) {
var tables = document.getElementsByTagName(”table”);
for (var i=0; i
8 days later
Change 1
var tables = document.getElementsByTagName(”table”);
for (var i=0; i
8 days later
Sorry guys, this forum keeps cutting off my post when I include the code.
I basically changed each foreach loop into an index loop and accessed each table and cell using the appropriate array index.
I also had the problem that my tables are loaded via AJAX after page initialization. A simple call to sorttable.makeSortable(MyNewTable) worked like a charm.
Thanks again for the code!
Scott
8 days later
GaryF: that’s what it’s for. :)
8 days later
ScottW: glad you got it sorted! I’d like to talk over this in more detail; could you drop me a mail? (See the contact link for my address.)
8 days later
you are very appreciated for you good job at sorttable.js.
And i also have a question.
To have the function ” when the table is loaded, one column is sorted”, how can i do it?
thanks very much!
RobertLee
From Peking of China
11 days later
Hey, I was tryin out the script, great job :) although having a few a problems, I think it is similar to ScottW’s problem, if you could somehow please provide me with the fix, I would be really thankful. I dont know if this is another problem when your table is in a javascript variable, and calling the html contents of the variable through innerHTML, but the script doesnt work on the tables then. (I think it works in IE, but not firefox and mozilla, really being odd like that)
12 days later
To Varun:
I have used sorttable.js. it does indeed work in IE.
12 days later
Fantastic tool, thanks so much!
I’m curious why you chose to use the non-standard
sorttable_customkey="2"rather than a class attribute? I’m loath to use invalid markup. ;)That said, I can see myself using this in many places, particularly at my workplace, a community college in British Columbia, Canada. I’ve been creating complicated workarounds in my custom CMS but this is a far better solution all around. Well done!
12 days later
Jason: two reasons. Firstly, a custom sortkey is emphatically not a class :) I feel a bit guilty about using class atrributes for things like column type overrides, but they are *sort of* appropriate. If you use a class of “2″ as a sortkey, then you’re suggesting that that table cell is like other cells with a class “2″, which it ain’t; it contains (something that maps to) the value 2, which is not the same thing. That’s the academic ivory-tower argument. The other argument is that if you’ve got more than one class applied to the cell then it won’t know which one to use as the sortkey, and setting class=”sorttable_sortkey_2″ seemed very silly :) I didn’t like the invalid markup either, I have to admit it, but it seemed the lesser of the evils.
12 days later
Fair enough. I’m working tangentially with Moodle that does all sorts of your second example to attempt to be fully compliant. I admit it’s a bit crazy to look at
class="course_47 subsection_cheese_danish_12". I think I’d still prefer that, but I definitely see your point.Nevertheless, I sure appreciate the code. :)
12 days later
I was wondering if there is any way to have the table sorted (instead of default) onload
13 days later
Thank you so much for your script! Is there anyway to have the script ignore strings that start with “the”, “a”, and “an” when sorting? I have a list of movie titles, and it would be great if the sort ignored these words. I can use the custom sort keys, but it would be great if the script did this automatically. Thanks!
2 weeks later
Rhonda: it’s not possible to do that easily, I’m afraid. I’d recommend using the custom keys to get this; I won’t make sorttable do it automatically because some people may want A or The to be included.
2 weeks later
FYI, I noticed there were some lines that included a conditional statement to use
font face ="webdings"for IE. There seems to be semicolon missing after the & nbsp. I also had some trouble with some Windows boxes that didn’t have webdings installed, so I replaced them with images (ie only). I’ll try to put the code in below.original code:
sortfwdind.innerHTML = stIsIE ? '& nbsp<font face="webdings">6</font>' : '& nbsp;& #x25BE;';my replacement:
sortfwdind.innerHTML = stIsIE ? '& nbsp;<img src=\'res/i/interface/arrow-down.gif\' alt=\'\' />' : '& nbsp;& #x25BE;';2 weeks later
(please note that I added spaces to the above comment; they shouldn’t be included in the original js, of course.)
2 weeks later
How can i get default sort on particular column on page load?
3 weeks later
Is there a quick way to change the color of the column that you are sorting?
This would be very usefull for big tables.
3 weeks later
My application uses dates in the form ‘Jan 1, 2007′. Be default, sorttable treats this as alpha. I’ve managed to override this in my page with class=”sorttable_mmdd” which seems to sort chronologically instead and I thought this fixed my problem. The problem arrises when there are blank values in the list however. Instead of having all the blank values go to the beginning like I would have expected (and how the alpha and date sorts work), there are various dispersed blank values in the list. Is this a bug? Any suggestions would be welcome.
Thanks.
3 weeks later
Scott: I advise you, in that situation, to use custom sortkeys. Instead of
<td>Mar 1, 2007</td>
<td></td>
use
<td sorttable_customkey=”20070301″>Mar 1,2007</td>
<td></td>
and then sorttable will happily sort them all correctly.
3 weeks later
My dates are being pulled from a database. How do I set up these custom keys when the output is variable? I’d need to translate 356 possible values. Many of these fields have timestamps as well. I’m not sure if what I’m trying to do is possible with this utility.
Thanks.
3 weeks later
Scott: is you data stored in the database as the string “May 02 2007″, or is it stored as a date which you then format in the output? Most languages have something that will let you output ISO date format, which is designed for this sort of thing. Failing that, if sorttable isn’t good enough then don’t let m eprevent you writing your own, of course.
3 weeks later
I really like this. I was using v1 for some time and just happened to come back here (to look up something) and see v2 was put up. Great!
One question; if the table (which is querie’d from a db) has no rows, i get some javascript errors. I tried to fix this myself, but got into hot water quite quickly. Not that javascript errors are terrible perse; but I know people around my company will come telling me about them.
3 weeks later
jimbo: hrm. I may patch sorttable to cope with this, but to be honest the answer to “sorttable doesn’t sort a table with no rows” is “don’t do that, then”, I think ;-)
3 weeks later
heheh, well, i do agree.
of course, my data is coming from a mysql query, so i don’t really know how many rows are getting returned. of course, i guess i could just not display the table at all if there are no rows to display.
hmmm.. not sure why i didn’t think of that before, actually. i guess i’ll do that.
thanks. i really like this…
4 weeks later
I realize that you don’t support any ’sort on load’ function. I get lots of requests to restore a particular sort order when a page is loaded / refreshed though. In an ideal world I would create a cookie whenever a header is clicked and look for that when a page is loaded and sort accordingly. That would make my life much easier than having to pass a special ‘order by’ query value back each time.
Just my $0.02.
Thanks for the excellent script.
4 weeks later
My solution to the “sort dates with blanks” problem: (line 271)
sort_ddmm: function(a,b) {
mtch = a[0].match(sorttable.DATE_RE);
if(mtch==null) {dt1=0};
else { y = mtch[3];
Regards
4 weeks later
Is there a quick way to change the color of the column that you are sorting?
This would be very usefull for big tables.
4 weeks later
jimbo, I use a function to check if there are rows come back from the db, if not I display a row, in the 1st column that says No Results. This will tell the user there is nothing, rather than just leaving it empty, and also solves your problem
Sydney
5 weeks later
I have a table with styles which shows odd rows with one colour and even rows with another. The problem comes up when I sort the table, then styles keep in the same row and the table is shown with unordered colours. Please, let me know if you have a solution for this.
Madrid, Spain
6 weeks later
A good way to deal with alternating rows is to use a modulo in the Append Child area. (There are two locations, the 2nd is for reversing the sort)
Search for tb.appendChild(row_array[j][1]); and tbody.appendChild(newrows[i]); and add the follow above them (make sure to stay inside the for loop)
if(j % 2)
row_array[j][1].className = “tRowA”;
else
row_array[j][1].className = “tRowB”;
– and –
if(i % 2)
newrows[i].className = “tRowB”;
else
newrows[i].className = “tRowA”;
Note: You hafto swap the order in the second function.
6 weeks later
Hi there, Is there a solution for begin the sort in a particular row?, for example I have other kind of information in the first row, and the header begin in the second row, I’ve tried to fix it but I dont found the solution…
8 weeks later
Hi,
Love the script as it’s saved me a whole load of grief! I think I might have found a small bug though :-( When there is more than a single table on the page, say tables A and B, and each has columns, say 1, 2 & 3, when alternate table headers are clicked for sorting, with the third click on the same as the first header to reverse, I get an error on page and the sorting arrow appears in the wrong table. Using the table notation this would be:
click B1/2/3 -> click A1 = Error>>.
Does this relate at all to ScottW’s posts?
Thanks
Rich
8 weeks later
submission seems to have shredded part of the post
order is A1 then B1/2/3 then A1 = Error
8 weeks later
When I attempt to use more than one table I am having the same issue as Rich G . The browser displays an “invalid argument” message. Debugging shows that this is being thrown from on of the following code segments depending upon the sort: this.removeChild(document.getElementById(’sortable_sortrevind)); and this.removeChild(document.getElementById(’sortable_sortfwdind));
8 weeks later
Nice to know I haven’t gone mad ;-)
I’ve come to the conclusion this is because the element found by document.getElementById does not have to be part of the same table as the calling cell and hence cannot be removed from its children in this case.
I’m now working out how to ensure that:
a: the element name is unique and known (or work outable) per table.
b: only the cell’s siblings are searched and have the element removed as I want the sorting indicator to be possible on each table.
Any thoughts?
Cheers!
8 weeks later
Yes, more than one table on a page is broken, because I’m a bit of an idiot. It’s on the list for sorttable 3.
8 weeks later
Hey Rich G - I have to switch to another project for the next couple of days. If you come up with some possible ideas or dead-ends can you post them? If I can find some time, I will do the same. Thanks!
8 weeks later
Hi,
Have a solution to this, the logic behind it is that the search by id is not necessary if the table head element is searched for children of a new sort_span type and any existing ones stripped. This ensures that the spans that have the arrows are removed for that table only.
I’ve taken the liberty of using the same forEach method for the three cases for clarity.
Hope that is all clear ;-)
Changed code is:
dean_addEvent(headrow[i],”click”, function(e) {
if (this.className.search(/\bsorttable_sorted\b/) != -1) {
// if we’re already sorted by this column, just
// reverse the table, which is quicker
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace(’sorttable_sorted’,
’sorttable_sorted_reverse’);
//get the thead for this cell
theadrow = this.parentNode;
forEach(theadrow.childNodes, function(cell) {
if (cell.nodeType == 1) { // an element
//get the spans in each cell
theNodes = cell.getElementsByTagName(’sort_span’);
//and remove them
for(var z = 0; z < theNodes.length; z++)
{
cell.removeChild(theNodes[z]);
}
}
});
sortrevind = document.createElement(’sort_span’);
//sortrevind.id = ”sorttable_sortrevind”;
sortrevind.innerHTML = stIsIE ? ’ <font face=”webdings”>5</font>’ : ’ ▴’;
this.appendChild(sortrevind);
return;
}
if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
// if we’re already sorted by this column in reverse, just
// re-reverse the table, which is quicker
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace(’sorttable_sorted_reverse’,
’sorttable_sorted’);
//get the thead for this cell
theadrow = this.parentNode;
forEach(theadrow.childNodes, function(cell) {
if (cell.nodeType == 1) { // an element
//get the spans in each cell
theNodes = cell.getElementsByTagName(’sort_span’);
//and remove them
for(var z = 0; z < theNodes.length; z++)
{
cell.removeChild(theNodes[z]);
}
}
});
sortfwdind = document.createElement(’sort_span’);
//sortfwdind.id = ”sorttable_sortfwdind”;
sortfwdind.innerHTML = stIsIE ? ’ <font face=”webdings”>6</font>’ : ’ ▾’;
this.appendChild(sortfwdind);
return;
}
// remove sorttable_sorted classes
theadrow = this.parentNode;
forEach(theadrow.childNodes, function(cell) {
if (cell.nodeType == 1) { // an element
cell.className = cell.className.replace(’sorttable_sorted_reverse’,”);
cell.className = cell.className.replace(’sorttable_sorted’,”);
//get the spans in each cell
theNodes = cell.getElementsByTagName(’sort_span’);
//and remove them
for(var z = 0; z < theNodes.length; z++)
{
cell.removeChild(theNodes[z]);
}
}
});
this.className += ’ sorttable_sorted’;
sortfwdind = document.createElement(’sort_span’);
sortfwdind.id = ”sorttable_sortfwdind”;
sortfwdind.innerHTML = stIsIE ? ’ <font face=”webdings”>6</font>’ : ’ ▾’;
this.appendChild(sortfwdind);
8 weeks later
just realised that the last
sortfwdind.id = ”sorttable_sortfwdind”;
should have been commented out
8 weeks later
Also fixed/tweaked the code for alternate table row styling in the reverse function suggected by Johnny Moon, as this didn’t take into account the fact that the mod of the last row number (and hence the first row) for the reversed table was not the same as the mod of the first row in the normal table if there were an even number of rows, which meant that the styling would be swapped on the first reverse sort click for the row and this would persist until another column was chosen for sorting or the page refreshed, a very minor bug but visually distracting. The fix checks whether the table has an odd or even number of lines and then allocates styling accordingly, note that only the reverse function was affected by this:
for (var i=newrows.length-1; i>=0; i–) {
//begin inserted statement
if(i % 2)
{
if(newrows.length % 2) //odd number of rows so start with tRowB
newrows[i].className = (’tRowB’);
else
newrows[i].className = (’tRowA’);
}
else
{
if(newrows.length % 2) //odd number of rows so start with tRowA
newrows[i].className = (’tRowA’);
else
newrows[i].className = (’tRowB’);
}
//end of inserted statement//
tbody.appendChild(newrows[i]);
8 weeks later
Thanks Rich G!
8 weeks later
A bug in IE 6 causes a security warning when loading the script over https
A fix is to replace this line:
document.write(”<script id=__ie_onload defer src=javascript:void(0)><\/script>”);
With:
document.write(”<script id=__ie_onload defer src=’dummy.html’><\/script>”);
The bug is documented all over the place. The html page given doesn’t even need to exist.
—Alex
8 weeks later
Ah thanks Alex I ran into that one last night and was about to look for a solution today and hey presto…
8 weeks later
Any plans to add scrollability to the code? Ideally, headers and footer stay fixed, body is scrollable. We have the first part worked out (IE6), but not the second.
8 weeks later
Jett: I’m not planning on adding that to sorttable; it’s just for sorting tables. http://www.imaputz.com/cssStuff/bulletVersion.html might be useful.
8 weeks later
In V2, how do I change the initial defualt sort direction from ascending to descending?
Thanks!
10 weeks later
Mike: this requires editing sorttable.js. After the line:
row_array.sort(this.sorttable_sortfunction);
add a new line:
row_array.reverse();
Let me know if this works.
10 weeks later
Beautiful! That did work! Thank you very much for all the help, you do excellent work!
Mike
10 weeks later
Hi Stuart,
Just to say thanks for making the code available to everyone, it saved me quite some time from writing my own.
Thanks again,
Dan
11 weeks later
Hi everyone, hi Rich G!
You said you fixed the problem with multiple tables, but I really don’t know where to place the code you posted a few days ago. Could you be as kind as to post your full working code (or a link to it) here? I’d be very thankful!
mark
11 weeks later
Hi mark,
It replaces the dean_addEvent part of the
existing makeSortable: function(table) function and starts from about line 93ish in my editor, the rest of the code is unchanged so I wont bother clogging up the rest of this page with it ;-)
Let me know if you have any further probs
Rich G
11 weeks later
Hi Rich,
Thank you very much for your help! I%27ve finally got it!!
I always just looked at the bottom of the source where the dean_addEvent() function is defined…
Thanks for fixing this multiple table problem. It was quite important for me!
11 weeks later
No worries it solved quite a few probs for me too, and I only really tweaked the stuff that was already there, which made my life a whole lot easier ;-)
BTW just got the spam blocking maths question wrong which is a little worrying :-(
11 weeks later
Here’s a kludge for ’sort on load’:
<body onload=’loader();>
function loader()
{
if (!document.all)
{
var fireOnThis = document.getElementById(’TH id value’);
var evObj = document.createEvent(’MouseEvents’);
evObj.initEvent( ‘click’, true, true );
fireOnThis.dispatchEvent(evObj);
}
else
{
var fireOnThis = document.getElementById(’TH id value’);
fireOnThis.fireEvent(”onclick”);
}
}
now put some unique ‘id=’ value in the <th> element for the column that you want to have sorted when the page loads. This works with FF and IE7.
11 weeks later
Great script! One question though.. Would it be possible to sort rows in pairs? Essentially, i have the following structure:
tr > td.price , td.date, td.blah
tr > td.description
.. repeat
Unfortunately I need two rows to fit all of the information about one product, but this creates a number of problems when trying to sort the table - namely, the second row gets all out of order, any ideas, suggestions?
Best,
Ilya
12 weeks later
Ilya: sorttable won’t do that; it’d need some fairly hefty modifications to the script, I’m afraid.
12 weeks later
Great great code! Many thanks!
12 weeks later
I just added this script to my 3D game comparison table but the script seriously screws the table up. I’d like to be able to sort by game name (top row) and feature (first, middle, and last columns). Any ideas? The table is very complex with nested col/row spans.
12 weeks later
eep2: sorttable can’t handle tables with colspans or rowspans, because working out how to sort a table like that is pretty close to impossible without knowing the details of the table.
12 weeks later
Well, how else to know the details of the table than to analyze the table prior to sorting?
12 weeks later
perhaps the best way would be to rethink the table structure :-(
I’ve had a look at your page and it looks interesting but hard to follow from a first encounter (ie without knowing the background as to why you chose to do it that particular way)
How is your table populated? Manually or via a db?
12 weeks later
Manually. I chose the layout (with the games across the top) because that reduces how much horizontal scrolling is necessary (since vertical scrolling is more common and easier). I tried to get it into a database but it’s just too complicated for me (not being much of a programmer)–check the main page and news/updates for more info. I’d be happy just to use a flat-file system with some kind of character-delimited list that PHP can sort and tabularize (allowing x games and x features/sections to be displayed only, etc), too.
12 weeks later
Sorry, the introduction was unreadable for me due to the colour scheme and font size :-( (and that’s on a 24″ widescreen at 1920 x 1200)
12 weeks later
Er, so increase the text size in your web browser and override the colors if you don’t like them…
12 weeks later
Sorry, inaccessibility of content is one of my pet hates, if i can’t read it I’m already browsing away
12 weeks later
just realised that sounded very critical of your site sorry, it wasn’t personal, I was just trying to explain why I rarely bother resetting my system to cope with a specific designers decision, have a look at sites such as http://www.csszengarden.com to see what clear and accessible design can achieve, its a good principle to design so that everyone can view your site rather than having to change their browser settings,
12 weeks later
So where’s the option on that site to have a dark layout? I don’t like bright white–it hurts my eyes… If I knew how to set cookies and allow people to choose/design their own color scheme, I would, but I don’t.
12 weeks later
in the zen garden each scheme has a different layout but the same content (supplied by the site), its an exercise in separating style from content and allows you to see what layouts you like and what you don’t, you may well have a valid reason for choosing your scheme I was merely commenting that it’s very hard to read ;-)
You could use alternative stylesheets to have a selector for viewing your site as white on black or black on white for example or completely change the layout for people with rotated widescreen monitors, css is both fun and amazingly irritating to play with!
to get slightly back towards the original start of our discussion, you could make your table into xml and then style that using css thus making it easy to add new content (by changing the xml only) or new layouts (by changing the css only) it might conceivably help your sorting table layout issues too!
Hopefully I’m being slightly helpful and you don’t feel too criticised by my random thoughts ;-)
12 weeks later
test
12 weeks later
Dunno why my comments aren’t being posted (aside from short ones–assuming this one will work). This is the third time now…
12 weeks later
Need a way to edit/delete comments…
12 weeks later
Blah…my last comment didn’t show up, for some reason (maybe cuz I had “a href” HTML links in it. Anyway, I had the thought of doing CSS hiding via this script (minus the animation) but I’m not sure if it works with tables (without them having to be separate tables per game, which defeats the purpose of having multiple games in a single table to compare, in the first place).
12 weeks later
But then there’s this sortable table script which has a filter, which might be configurable as a checkbox above each column/game field (and perhaps even each row/feature) to hide/show it. I don’t know XML but maybe HTML+CSS+Javascript will suffice.
12 weeks later
Oh and there’s a stylesheet switcher that I’ll look into adding to my site(s).
Anyway, thanks for the replies.
(OK, one link per comment is stupid…)
12 weeks later
They got moderated, which is why they didn’t show up. The one-link-per-comment thing is Wordpress, not me specifically, but the huge majority of comments I get with more than one link in are spam…
12 weeks later
if you know the column class in a table you can hide the entire column and the same for rows so you could have a separate class for each game and switch them on or off as you like
12 weeks later
But is that only for columns that don’t span multiple rows (and vice versa)? Cuz, ideally, I’d like to consolidate cells that have the same content (developer, “yes”, “no”, etc)…
12 weeks later
I’m taking rubbish of course! there is no concept of a column in a html table definition, just rows and cells (hangs head in shame). Styling rows with a unique css class will allow easy turning on and off but doing this by hand will become a bit more tedious each time you add stuff and for columns like you have with multiple cell spanning, you would have to know something like each cell location in the parent row -> child cells tree and to find this you would have the same problem as what you have already encountered :-(
I think for a table like this it might be easier to have the duplication for the sake of easier coding as you would be able to rely on knowing the same number of cells per row etc.
I would do it in ASPX myself and so would avoid the problem entirely by generating the table on the fly each time things were clicked on but that might be using a sledgehammer to avoid the nut!
Hmm I might have just talked you back to where you were a few days ago :-( sorry!
12 weeks later
Of course there’s a column concept in HTML tables, otherwise there wouldn’t be a col element and colspan attribute, for one. For two, there’s a colgroup element. I don’t know ASPX (whatever that is) either. I’m looking into various content management systems but am not having much luck (trying Drupal right now–I’d post a link but stupid WordPress is too paranoid about “spam links” ). Anyway, I’m more informed than I was a few days ago but still pretty much stuck on what to do and how to implement it.
12 weeks later
I’ve learn’t something new too, never come across col attribute before, will have a play could be very useful!
ASPX is basically dynamic server side generated webpages ie you code how you want to generate the page and when the user browses to it the page is generated for them.
12 weeks later
Right…more coding…blech.
12 weeks later
you know you enjoy it really, join us on the dark side:
“Don’t be so proud of this technological terror you’ve created. The ability to destroy a planet is insignificant next to the power of the force.”
- Darth Vader
12 weeks later
Patch for stable sort :
sort_alpha: function(a,b) {
if (a[0]<b[0]) return -1;
if (a[0]>b[0]) return 1;
// when equals keep previous order (=row index)
if (a[1].rowIndex<b[1].rowIndex) return -1;
else return 1
}
Apply similar rule to sort_numeric, sort_ddmm, …
12 weeks later
Patch to show ’wait’ cursor while sorting :
Insert this :
dean_addEvent(headrow[i],”mouseover”, function(e) {
this.style.cursor=’pointer’;
});
dean_addEvent(headrow[i],”mousedown”, function(e) {
this.style.cursor=’wait’;
});
just before that :
dean_addEvent(headrow[i],”click”, function(e) {
…
});
and add this line :
this.style.cursor=’pointer’;
before each return
and after : delete row_array;
in the same function
12 weeks later
I need a patch to sort single-digit dates (days, months, and even years) correctly, and not always in DD/MM/YY format either but MM/DD/YY, MM/D/YY, MM/D/Y, M/D/Y, M/DD/Y, etc.
20 weeks later
opus, what is “stable sort”?
20 weeks later
Hello? Anyone? Beuler, Beuler?
22 weeks later
That’s “Bueller”. You might get a patch if you asked a touch more nicely about it…
22 weeks later
Uh, how much more nicely can I ask “what is ’stable sort’”? Geez…too many damn overhypersensitive people online–I fucking swear it’s ridiculous!
22 weeks later
The definition is a google search away. The sorttable page itself links to the Wikipedia description of stable sorting.
And I wasn’t talking about stable sorting, anyway, I was talking about you just saying “I need a patch to do X, Y, and Z”.
22 weeks later
Er, it’s not like I wrote “I demand a patch NOW!*($#” or something… I was being quite neutral about it, actually. Besides, why should I need to ask nicely for something that the script should already be able to do inherently? <buh-link> Anyway, stable sorting isn’t what I need…
22 weeks later
Single-digit date handling is on the list for sorttable v3.
22 weeks later
“Besides, why should I need to ask nicely for something that the script should already be able to do inherently?”
Well thats how to win friends!
“Anyway, stable sorting isn’t what I need…”
Nope, quite right, what you need is to look through the code and fix it then share the fix with everyone else.
22 weeks later
Wondering if anybody has used sortable with checkboxes. I have a table with a column of checkboxes and labels set to sorttable_nosort. If I sort the table, check some boxes and submit the form, all the form elements get passed except for the checked boxes. If I submit the form without sorting the table,everything works as expected.
Any ideas?
22 weeks later
Mark G: you’re not the first person to report this problem, but I’ve not been able to replicate it. Do you have a URL that demonstrates the problem? Which browser are you using?
22 weeks later
Mark G, All my table have checkboxes and work fine so I can’t say I’ve found a problem with it sorry :-(
22 weeks later
It’s an internal project so I don’t have a URL for you to look at.
I’ve been able to replicate the problem on Firefox and Opera. It works fine on Safari.
Thanks
22 weeks later
Thanks for the great script ! It help a lots.
I have a minor problem, my table with 3 header rows (i understand it doesn’t work for this version) so I decided to change the script. But afetr some hard works, :o( I am wondering will I be able to achieve it ?
I change like:
headrow = table.tHead.rows[table.tHead.rows.length - 1]
23 weeks later
(oops, sorry, haven’t finish my typing… )
and make changes to row_array (to make it start from table.tbody, not counting the header…)
Can I know am I in right direction ? or I am totally talking nonsense ?
Thanks.
23 weeks later
EngDian: that’s certainly one approach to take. I haven’t yet decided how best to make sorttable support multiple header rows, which is why sorttable doesn’t do it yet. It’s planned for version 3.
23 weeks later
Sortable and AJAX.NET both has an Array.forEach function it’s just that they do not work the same way.
To fix that just put a prefix before all the ForEach-functions in sorttable.js. Don’t forget to also change the
resolve.STforEach(object, block, context); // ST is the prefix
in the base forEach function.
ScottW has another solution above but I think this one might be simpler.
24 weeks later
Jonas: quite right, and added to the bug list.
24 weeks later
i would like to order the table by binding 2 row together
30 weeks later
Is there a way to skip a column from sorting?
I have a first column with ranking (1 to whatever), and I want that to stay the same when sorting the table.
38 weeks later
Ryan: I’m afraid not. This is a known bug, though; see http://kryogenix.org/bugs/sorttable/left-hand-headers.html for details.
38 weeks later
Hi Stuart. Great code, very useful.
I’m running into a problem using your sorttable v2 with BarelyFitz’s Tabber.js (http://www.barelyfitz.com/projects/tabber/), such that when I include a sorttable table, all tabs vanish (standard tabs w/cookies). When I use sorttable v1, it works fine. While I realize that its likely to be much to ask, I was wondering if you had any suggestions? (I’ve tried the prefix fix mentioned above to no avail)
Also, does anyone have any advice for sorting a street address field, already merged into one field of Street # + Street Name? (where not all properties have a #?)
Thanks a lot!
39 weeks later
Sadly, sorttable doesn’t seem to work if your doctype is XHTML 1.0 versus HTML 4.01. If you do upgrade the library, let me know!
39 weeks later
Kathy: that’s not supposed to happen. Do you have an example of a page that it doesn’t work on, so I can test? Feel free to contact me by email if you prefer.
39 weeks later
josh: have you got a page that exhibits the problem, so I can take a look?
For sorting oddly-formatted fields, you’ll want to use sorttable’s custom sort keys.
40 weeks later
I spent some time searching for a solution to this until I came back and reread the whole thread. The bugfix link isn’t by the error message tha caused it.
sys.argumenttypeexception object of type object cannot be converted to type array
http://kryogenix.org/bugs/sorttable/foreach-collide.html
I fixed mine by doing a replace on forEach to STforEach
40 weeks later
Your script doesn’t work on IE7.
Great with FF2.
As an exemple, you tables on this page are not active with IE7 but are on FF2.
Chears,
46 weeks later
Fabrice: oops. Added to my bug list. Thanks.
46 weeks later
Thanks for the script. I use it at work for sorting off of an
Indexing Server with ASP. Is there any way to manipulate the script to allow for date modified? Since this is a search I cant simply alter the cell. I need to sort in the format
mm/dd/yyyy HH:MM:SS AM/PM
Thanks again for sharing this great script!
47 weeks later
Jared: if you can’t use custom keys, then the script will need to be modified, as you mention. It can be done; you’ll need to edit the date-parsing functions and the date regular expression. If you want me to do it, contact me and we can talk about rates and so on.
47 weeks later
Here is a patch to make the sort stable.
The modification is to set id to the original row index and sort by row.id when rows are equal (one drawback is that existing id:s on tr-elements are removed).
The added code starts with ”+”:
forEach(document.getElementsByTagName(’table’), function(table) {
if (table.className.search(/\bsortable\b/) != -1) {
sorttable.makeSortable(table);
+ if (table.className.search(/\bstablesort\b/) != -1)
+ sorttable.setrowids(table);
}
});
},
+ setrowids: function(table) {
+ // Set id=rownumber, makes the sorting stable with the help of sort_by_id
+ sortfn = sorttable.sort_alpha;
+ for (var i=0; i<table.tBodies[0].rows.length; i++)
+ table.tBodies[0].rows[i].id = i+100000;
+ },
+ sort_by_id: function(a,b) {
+ if (a[1].id==b[1].id) return 0;
+ if (a[1].id<b[1].id) return -1;
+ return 1;
+ },
sort_numeric: function(a,b) {
aa = parseFloat(a[0].replace(/[^0-9.-]/g,”));
if (isNaN(aa)) aa = 0;
bb = parseFloat(b[0].replace(/[^0-9.-]/g,”));
if (isNaN(bb)) bb = 0;
+ if (aa==bb)
+ return sorttable.sort_by_id(a,b);
+ else
return aa-bb;
},
sort_alpha: function(a,b) {
if (a[0]==b[0])
+ return sorttable.sort_by_id(a,b);
if (a[0]<b[0]) return -1;
return 1;
},
sort_ddmm and sort_mmdd:
+ if (dt1==dt2) return sorttable.sort_by_id(a,b);
48 weeks later
Niklas: what was wrong with http://www.kryogenix.org/code/browser/sorttable/#stablesort ?
48 weeks later
I sent you an email as requested about sorting mm/dd/yyyy hh:mm:ss AM/PM but I never heard back from you. Just wanted to make sure you got the message?
48 weeks later
Jared: sorry, replied now!
48 weeks later
> Niklas: what was wrong with http://www.kryogenix.org/code/browser/sorttable/#stablesort ?
Differences:
shaker_sort:
* Uses custom sort function
* multi-level sorting of data (when two rows are equal the previous sort order is used)
My patch:
* Uses JavaScript sort (sorting should be faster, but initial setup is slower)
* When two rows are equal the original order is used
* If you sort with sort_by_id, or on a column with all the same values, the result is the original order.
So you could quite easily add a third state when clicking a third time on the column header - unsorted (i.e. remove the arrow and sort with sort_by_id)
Note:
To make my patch behave like shaker_sort (general way of making any sort stable):
1. skip setrowids (not needed)
2. add j as the third element in row_array
for (var j=0; j<rows.length; j++)
row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j], j];
3. Modify the sort_by_id function (or replace all “sort_by_id” with “a[2] - b[2]“):
sort_by_id: function(a,b) {
return a[2] - b[2];
},
4. Use row_array.sort(this.sorttable_sortfunction); as normal
Should give the same result (not tested though).
48 weeks later
hi great script!!
i need to know how to do this:
I have one column that I don’t want to be sorted at all, how do I do that? Thanks in advance!
50 weeks later
lau: see the documentation.
50 weeks later
Hi, just updated to v2. The speed increase is excellent.
is there any documentation on any additional css stuff to interact with sortable.. I was thinking along the lines of a:hover.sortable but cant get anything to work.
in v1 when you would hover over the heading the pointer would change… in v2 it doesn’t & it shows no obvious signs of being a “link” or sortable, or do I have mine incorrectly setup?
many thanks
51 weeks later
gee: to style links in a sortable table, you want
table.sortable a { styles }
and to style your headers, use
table.sortable th { cursor: hand; }
51 weeks later
Hi,
Many thanks for the response.. I think I worded the question badly but it gave me some ideas for future use.
just to check did you mean
table.sortable thead {}
rather than
table.sortable th {}
as I can’t get anything out of th
….
what I have done though is this
table.sortable thead {
padding:3px;
background-color:#52418C;
color:white;
font-weight: bold;
text-decoration: none;
height: 12.75pt;
}
table.sortable thead:hover {
text-decoration: underline;
background:#A5DD29;
cursor: pointer;
}
note pointer rather than hand as I found out hand don’t work in ff
what happens isn’t exactly what I’d expect in that when you hover over one header cell is the whole header row changes colour & underlines… which makes me think I’ve got something wrong & it’s where ’th’ comes in?
off to research css a bit more, but any pointers much appreciated.
51 weeks later
doh… th won’t work unless you use <th></th>
51 weeks later
gee: ah, yeah, you should be using th inside a thead :)
51 weeks later
Awesome script!! It works in IE7 with Tabber.js (which Josh reported) for me.
I have a display problem however. When the column header string is shorter than its values in tbody, adding the unicode triangle when sorting on the header works great. See example below.
Name
Employee A
Employee B
But when the column header string is longer than any of its text in tbody, the added triangle increases the th length and messes up my table format. The right table border is gone, and the tbody formatting (background color) doesn’t apply to the increased thead/th length. For example,
Name
A
B
Can you give me some tips on how to work around this?
Thanks!!!
52 weeks later
Hi, thanks for this script !
I use striped-tables, and I see that is in the wish list.
As I did not want to wait, I have to add this to script :
1/ a new function
striped: function(table){
for (var i=0; i<table.tBodies[0].rows.length; i++) {
table.tBodies[0].rows[i].style.backgroundColor=(i%2==0)?table.getAttribute(’R1BgColor’):table.getAttribute(’R2BgColor’);
}
},
2/ I call it in init just before makeSortable
…
sorttable.striped(table);
sorttable.makeSortable(table);
…
3/Another call before sort function
…
delete row_array;
sorttable.striped(this.sorttable_tbody.parentNode);
…
4/ I add two attributes to the table
Note: Class instead og Bgcolor would be better, I think.
What are you thinking about this ?
55 weeks later
Martial: that’s certainly a good way to solve your specific problem, and I’m glad sorttable could help you!
55 weeks later
[...] have a sortable sub folder structure and sortable images per folder. Searching the web, I found an excellent javascript solution for sorting tables. The script works very well and I have adapted it for use in the Lazyest Gallery Manage page with [...]
56 weeks later
Is there any “onsorted” event that gets fired after a sort is complete? If not, any recommendation on how to add support for that? I need to make an Ajax call after a sort to store the new order on the server. I’m thinking it would be most convenient if I could just add an onsorted=”myjsfunc();” to the table.
Thanks,
Russ
59 weeks later
Thanx,
It is a beautiful script works like charm in my scripts without much changes
60 weeks later
hey…
i am trying to get sortable to work for textbox inputs…the values are entered dynamically each time for some further validations… the text i am entering is of a certain format eg. ‘PP_VER-RE_908′ the innerText code in the sorttable.js considers this as numeric…after that it just inverts the rows in the table…sort doesnt happen..any suggestions???
60 weeks later
Vinnie: what you’re talking about will, I think, require some custom (thus paid-for) enhancements to sorttable. Drop me an email (http;//www.kryogenix.org/contact) and we can talk about it.
60 weeks later
i need to know how to do this:
I have one line not a column that I don’t want to be sorted at all (some ads), how do I do that? Thanks in advance!
62 weeks later
Bastien: if you mean that you’d like that column to stay in the same order even if the rest of the table is sorted, then that’s http://www.kryogenix.org/bugs/sorttable/left-hand-headers.html which is a known request for enhancement. I’m not sure when I’ll have time to get to it, though. (You can get it up my list with money: see http://www.kryogenix.org/code/browser/sorttable/#payforwork for details :))
62 weeks later
Oh my God! I can’t believe it! All that functionality and it took me 5 seconds to drop it in and it just works! AWESOME!!! You just saved me a ton of time in dinking with database query strings.. You are the man! THANK YOU!!!
-Hatch in Costa Rica…
62 weeks later
Hatch: no problem Glad you liked the script. :)
62 weeks later
It seems I ran into a bug with the date format dd.mm.yy. At least the sorting does not work properly and I cannot figure out why. It sorts in a very weird way.
You can see it at http://www.quaddicted.com/spmaps.html
The script seems to loaded right as sorting the other columns works fine.
Unfortunately I am rather “code-blind” so I can’t see why it does work so wrongly. Tried Firefox 2.0.0.14 and Opera.
62 weeks later
I love it, it’s da bomb.
Is there any way to sort an image column? No, I don’t mean sort them by what they contain (!), just if there’s an icon there or not. For instance, if there’s a star for “Featured” something or other, and a camera icon for “Has a Photo”, etc. it would be nice to be able to just bring all these to the top.
I know, I know, give ‘em an inch… ;^)
64 weeks later
ps: I mean besides inserting a number “1″ in front of the icons and giving them a css font size of 1 and a color the same as the background ;^) Because that works! (but it’s a little wacked)…
64 weeks later
Table Sorta Guy: add a custom sort key of 1 or 0 to the cells in question. See http://kryogenix.org/code/browser/sorttable/#customkeys for details.
64 weeks later
Awesome! Thank you !!!
64 weeks later
whatever
64 weeks later
I love this script, however, I have a checkbox that allows one to select certain records for processing via a post of the form information.
I am trying to add an option to select or unselect all but I would like the select or unselect to select or unselect only visible rows, not all rows.
Is there any easy way to do this that anyone knows of?
67 weeks later
Stephanie: I’m not sure what you mean by “visible” rows? Sorttable doesn’t make rows visible or invisible.
68 weeks later
Hi, more stuff:
<pre>
* Sort detect empty as lowest ”value”
</pre>
Great job - rgds. Henrik at Lassen dot dk
Solutions proposed
==================
<pre>
//* Sort detect empty as lowest ”value”
sort_numeric: function(a,b) {
aa = parseFloat(a[0].replace(/[^0-9.-]/g,”"));
bb = parseFloat(b[0].replace(/[^0-9.-]/g,”"));
return sorttable.sort_NaN(aa) - sorttable.sort_NaN(bb);
},
</pre>
70 weeks later
Hi, here is what i am looking for (resend):
* Embed script (One page HTML)
* Sort detect IP addresses
Great job - great speed - rgds. Henrik at Lassen dot dk
PS. Never understod the difference between ”Submit comment” and ”Post comment”
Solutions proposed
==================
//Embed script: Use double qoutes
//Sort detect IP addresses
if (text != ”") {
if (text.match(/^(\d{1,3}\.){3}\d{1,3}$/)) return sorttable.sort_ip;
if (text.match(/^-?[£$¤]?[\d,.]+%?$/ )) return sorttable.sort_numeric;
…
sort_ip: function(a,b) { // Rgds HL
aa = a[0].split(”.”); aaa = 0; for(i in aa) aaa = aaa*256+parseInt(aa[i]);
bb = b[0].split(”.”); bbb = 0; for(i in bb) bbb = bbb*256+parseInt(bb[i]);
return sorttable.sort_NaN(aaa) - sorttable.sort_NaN(bbb);
},
sort_NaN: function (a) {
if (isNaN(a)) return -Number.MAX_VALUE; return a;
},
70 weeks later
I just wanted to submit my tweak to enable the correct sorting of negative numbers that are denoted by enclosing them in parenthesis like (10.39) = -10.39
What I do is have it replace the opening parenth with a negative sign before stripping all other non-number chars. That way it retains the negative and sorts in true numeric rather than as an absolute value when using parenths.
sort_numeric: function(a,b) {
aa = parseFloat(a[0].replace(/\(/g,’-').replace(/[^0-9.-]/g,”));
if (isNaN(aa)) aa = 0;
bb = parseFloat(b[0].replace(/\(/g,’-').replace(/[^0-9.-]/g,”));
if (isNaN(bb)) bb = 0;
return aa-bb;
}
81 weeks later
Is there an equivalent to “sortbottom” that will keep a row at the top? (e.g. “sorttop”)
Thanks.
82 weeks later
Jason: I’m afraid not. You’d need to make a custom enhancement to sorttable to do that (or talk to me abou