Skip to content
Mottie edited this page Jan 20, 2015 · 15 revisions

Wiki: Home | FAQ | Snippets | Search | Language | Changes | Change summary #List of FAQ

##Why does my column only sort once?

There are various reasons why this could happen, but the most often it is due to an incorrect parser being set.

When a table has tablesorter applied to it, it must determine what type of data each column contains. The code that does this isn't really that smart, because all it does is looks at the first cell in that column - it is smart enough to skip empty cells and go to the next row - and then runs through each parser until something matches.

So say you have text included after a date, something like "Aug 21, 2009 12:21 PM blah", the date parser won't think this is a date because of the extra text. So it will set the parser as just plain text. See this demo. To fix this, wrap the date text in a span

<td><span>Aug 21, 2009 12:21 PM</span> blah</td>

then target the date using the textExtraction option, like this (working demo)

textExtraction: {
    1: function (node) {
        return $(node).find('span').text();
    }
}

Alternatively you can wrap the extra text in a span

<td>Aug 21, 2009 12:21 PM <span>blah</span></td>

Then modify the text extraction function like this (demo):

textExtraction: {
    1: function (node) {
        return node.childNodes[0].nodeType === 3 ? node.childNodes[0].nodeValue : $(node).text();
    }
}

Or, write your own custom parser (demo):

$.tablesorter.addParser({
    id: 'dates',
    is: function (s) { return false; }, // don't auto detect this parser
    format: function (s, table) {
        // match dates in this format: 'Mmm dd, yyyy hh:mm:ss AM'
        var date = s.match(/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(?:\d{4})(?:\s+\d{1,2}:\d{2}(?::\d{2})?(?:\s+[AP]M)?)?/i)[0];
        return date ? $.tablesorter.formatFloat((new Date(date).getTime() || ''), table) || s : s;
    },
    type: 'numeric'
});

$('table').tablesorter({
    headers : {
        1 : { sorter : 'dates' }
    }
});

If your issue doesn't seem related to this, then please check the development console (Press F12 in the browser, while on the problematic page), then

##Why doesn't the zebra widget work in tabs, popups or dialog boxes?

The zebra widget only alternates class names on every visible row. So when tablesorter is inside of a tab, popup or dialog that isn't visible when the zebra widget is applied (tablesorter initialization), the table and all of its rows are hidden. So that means the zebra widget find any visible rows and ends up not adding any class names.

The easiest solution would be to use the tab, popup or dialog callback which is executed when it becomes visible. Since there are so many, I'm only going to show an example using jQuery UI widgets. For tabs, do the following:

$('#tabs').on('tabsactivate', function(event, ui){
	// make sure zebra widget is applied
	// after the tab becomes active
	ui.newPanel.find('table').trigger('applyWidgets');
});

and for the jQuery UI Dialog, do this:

$('#dialog')
	// initialize dialog widget
	.dialog()
	// use open callback to update the zebra widget
	.on('dialogopen', function(event, ui){
		// make sure zebra widget is applied after
		// the dialog is visible
		$(this).find('table').trigger('applyWidgets');
	});

##Why is this fork slower than the original on very large tables?

Well, to be fair, this fork does do a lot more stuff during initialization.

Here is a tested example:

Say you have a page with 90 tables each 19 columns by around 20 rows; that ends up being around 32,000 table cells to process!

  • When tested in IE11, the original tablesorter (v2.0.5) takes about 400ms. Not too shabby.
  • When tested in IE11, this fork takes up to 6800ms! Chrome takes about 1100ms.

Yeah, huge difference!

So, to break it down. Some of the little things that add to the initialization time of this fork include:

  • Aria support (the original does nothing)

  • Text Extraction:

    • The original checks for a node's textContent (if supported) then falls back to innerHTML - quick & simple.

    • This fork first checks for a data-attribute (to allow alternate text to be stored in "data-text"), then textContent, then innerText, then jQuery .text()

    • The data-attribute check adds some pretty significant time to the overall initialization time, especially in IE.

    • Adding the following two optimizations cuts the overall time to about 3600ms:

      // when true, the table cache is not built initially. The cache is built if the table has an initial sort, initial
      // filter settings, or once the user clicks on a header cell to sort the table
      delayInit: true,
      // Simplified text extraction method
      textExtraction: function(node){
        return node.textContent || $(node).text() || '';
      },
  • Header cell processing:

    • The original TS does nothing to the table header cell.
    • This fork wraps the header cell content within a div:
      • The main reason for this is due to Firefox because "position:relative" can not be set on a table cell in Firefox, but all other browsers allow it.

      • With this inner div, icon elements (<i> used by Bootstrap and jQuery UI themes) can be absolutely positioned within the header cell. This also includes the resizable widget handle.

      • If you only want to use very basic widgets, then turning off this option cuts the example's total initialization time to around 2500ms - 3200ms.

        headerTemplate: '',

So the resulting optimized code woud look like this:

$('table').tablesorter({
  headerTemplate: '',
  delayInit: true,
  textExtraction: function(node){
    return node.textContent || $(node).text() || '';
  }
});

I tried to get the time better than this, but the rest of the code is all stuff that isn't easy to trim down, such as the ability to set options using data-attributes, jQuery .data() and header class names - they all need to be checked.

With more optimization and using native javascript instead of jQuery in critical places might speed up the code even more... I'll see what I can do when I have the time.

But really the bottom line is huge tables, or many many tables on one page is just too much. That tested HTML file with around 32,000 table cells was over 400kb in size, which is too much for a mobile device/network to handle.

Clone this wiki locally