Saturday, June 18, 2011

jQuery Tablesorter, The Missing Docs

If you need support for my fork of tablesorter, please contact me here:

The Missing Docs for jQuery Tablesorter 2.0

These docs have been incorporated into my

All Defaults


Appearance
cssHeader: "header"The CSS style used to style the header in its unsorted state.
cssAsc: "headerSortUp"The CSS style used to style the header when sorting ascending.
cssDesc: "headerSortDown"The CSS style used to style the header when sorting descending.
cssChildRow: "expand-child"This allows you to add a child row that is always attached to the parent. See the children rows section below.
widgetZebra: { css: ["even", "odd"] }Set the CSS classes used for zebra striping the table. See the updating zebra striping section below.
widthFixed: falseIndicates if tablesorter should apply fixed widths to the table columns. This is useful for the Pager companion. Requires the jQuery dimension plugin to work. See the main demo page
onRenderHeader: nullThis function is called when classes are added to the th tags. You can use this to append HTML to each header tag. See the Render Header section below.
Sort Options
sortInitialOrder: "asc"A string of the inital sorting order can be "asc" or "desc". This is overridden bt the sortList settings.
sortForce: nullUse to add an additional forced sort that is prepended to sortList. For example, sortForce: [[0,0]] will sort the first column in ascending order. See the main demo page
sortList: []Add an array of the order the table should be initially sorted; e.g. sortList: [[0,1], [1,0]]. The first part "[0,1]" will sort the first column (zero based index) in decending order and the second part "[1,0]" is to sort the second column in ascending order. See the main demo page.
sortAppend: nullUse to add an additional default sorting rule, that is appended to the sortList.
Parsers & Widgets
headers: {}See the Change how you sort a column section below or see the main demo page
textExtraction: "simple"See the Text Extraction section below or see the main demo page
sortLocaleCompare: trueBoolean flag indicating whenever to use String.localeCampare method or not. This is only used when comparing text strings.
parsers: {}Internal list of all of the parsers. See a complete list of parsers below.
widgets: []Initialize widgets using this option (e.g. widgets : ['zebra'], or custom widgets widgets: ['zebra', 'myCustomWidget']; see this demo on how to add a custom widget.)
selectorHeaders: 'thead th'jQuery selectors used to find the header cells. You can change this, but the table will still need the required thead and tbody before this plugin will work properly.
headerList: []Internal list of each header element as selected using jQuery selectors in the selectorHeaders option.
dateFormat: "us"Set the date format. See the dataFormat section below.
Interaction
sortMultiSortKey: "shiftKey"The key used to select more than one column for multi-column sorting. Defaults to the shift key. Other options might be ctrlKey, altKey. See the main demo page
cancelSelection: trueIndicates if tablesorter should disable selection of text in the table header (TH). Makes header behave more like a button.
Unknown
decimal: '/\.|\,/g'Regex to find the decimal "." for U.S. format and "," for European format... but I can't find it being used anywhere in the plugin.
Debugging
debug: falseBoolean flag indicating if tablesorter should display debuging information usefull for development. This displays information in the console, if available, or in alerts. See the main demo page

Update Default Settings

Update any of the default settings above using this format:
$(selector).data("tablesorter").{default name} = newValue;
Here are a few examples:
// Change sortForce
$("table").data("tablesorter").sortForce = [[1,0]];
// it appears that the only way to update the table is to resort it
$("table").trigger("sorton", [[0,1]]);
// Add zebra sorting after the table has initialized
$("table").data("tablesorter").widgets = ["zebra"];
// there is a method to apply widgets!
$("table").trigger("applyWidgets");

Child Rows

To add a row that remains attached to a parent row, add the "expand-child" class to the row.

You can add some scripting to hide these child rows and have them expand when you click on a link; this is the original reason for the css name.

Here is the original mod page, the code was added into the TableSorter core but remains undocumented.

This makes the tablesorter plugin keep these rows together. This css class can be changed using the "cssChildRow" option.

Here is some example markup:
<table width="100%" border="1">
  <thead>
    <tr>
      <th>Item #</th>
      <th>Name</th>
      <th>Available</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>12345</td>
      <td>Toy Car</td>
      <td>5</td>
    </tr>
    <tr class="expand-child"> <!-- this row will remain attached to the above row, and not sort separately -->
      <td colspan="3">
        It's a toy car!
      </td>
    </tr>
    <tr>
      <td>23456</td>
      <td>Toy Plane</td>
      <td>2</td>
    </tr>
    <tr class="expand-child"> <!-- this row will remain attached to the above row, and not sort separately -->
      <td colspan="3">
        It's a toy plane!
      </td>
    </tr>
    <tr class="expand-child"> <!-- this row will remain attached to the above two rows, and not sort separately -->
      <td colspan="3">
        and it flies!
      </td>
    </tr>
  </tbody>
</table>


Update Zebra Striping After Sorting

Actually the zebra striping widget does this for you automatically.

By default the odd and even rows are styled using "odd" and "even" class names ({ css: [ "even", "odd" ] }).

Change these css class names using the widgetZebra option as follows:
$(function(){
  $("table").tablesorter({
    widgets: ["zebra"], // initialize zebra striping of the table
    widgetZebra: { css: [ "normal-row", "alt-row" ] }
  });

Modify the Header Markup

The onRenderHeader option allows you to add a function that which can modify the HTML of each header tag. In the example below, the header cell (th) content is wrapped with a span tag to allow for better styling (source).
$(function(){
  $("table").tablesorter({
    onRenderHeader: function (){
      this.wrapInner('<span class="roundedCorners"></span>');
    }
  });
});
and you'll end up with this (only the thead is shown):
<thead>
  <tr>
    <th class="header"><span class="roundedCorners">Column 1</span></th>
    <th class="header"><span class="roundedCorners">Column 2</span></th>
  </tr>
</thead>


Change how you sort a column

The plugin attempts to detect the type of data that is contained in a column, but if it can't figure it out then it defaults to alphabetical.

You can easily override this by setting the header argument (or column parser).
$(function(){
  $("table").tablesorter({
    headers: {
      0: { sorter: false },      // disable first column
      1: { sorter: "digit" },    // sort second column numerically
      4: { sorter: "shortDate" } // sort the fifth column by date (e.g. mm/dd/yyyy if the date format is "us")
    }
  });
});
*Note* the header number starts with zero (zero based index).

Here is a list of available sorter values/parsers:

sorter: falsedisable sort for this column.
sorter: "text"Sort alphabetically.
sorter: "digit"Sort numerically.
sorter: "currency"Sort by currency value (supports "£$€").
sorter: "ipAddress"Sort by IP Address.
sorter: "url"Sort by url.
sorter: "isoDate"Sort by ISO date (YYYY-MM-DD or YYYY/MM/DD).
sorter: "percent"Sort by percent.
sorter: "usLongDate"Sort by date (U.S. Standard, e.g. Jan 18, 2001 9:12 AM).
sorter: "shortDate"Sort by a shorten date (see "dateFormat").
sorter: "time"Sort by time (23:59 or 12:59 pm).
sorter: "metadata"Sort by the sorter value in the metadata - requires the metadata plugin.

Change the Date Format (dateFormat)

"us""mm-dd-yyyy" or "mm/dd/yyyy"
"uk""dd-mm-yyyy" or "dd/mm/yyyy"
"dd/mm/yy" or
"dd-mm-yy"
Sort by short year (it appears to sort by day first, not the year)




Change the Sorted Columns

There are three options to determine the sort order and this is the order of priority:
  1. sortForce forces the user to have this/these column(s) sorted first (null by default).
  2. SortList is the initial sort order of the columns.
  3. SortAppend is the default sort that is added to the end of the users sort selection (null by default).
The value of these sort options is an array of arrays and can include one or more columns. The format is an array of instructions for per-column sorting and direction in the format: [[columnIndex, sortDirection], ... ] where columnIndex is a zero-based index for your columns left-to-right and sortDirection is 0 for Ascending and 1 for Descending. A valid argument that sorts ascending first by column 1 and then column 2 looks like: [[0,0],[1,0]]
$(function(){
  $("table").tablesorter({
    sortForce  : [[0,0]],        // always sort first column first
    sortList   : [[1,0], [2,0]], // initial sort columns (2nd and 3rd)
    sortAppend : [[3,0]]         // always add this sort on the end (4th column)
  });
});
*NOTE* When writing this post, I didn't realize that the sortAppend option was listed as an option, but the code for it did not exist. This problem is fixed in my fork of tablesorter (example).

Text Extraction

This is demonstrated in the Dealing with markup inside cells demo page, but the example uses vanilla javascript to find the desired text, like this:
$(function(){
  $("table").tablesorter({
    textExtraction: function(node) {
      return node.childNodes[0].childNodes[0].innerHTML;
    }
  });
});
But you could make your life easier and just make the node into a jQuery object and then "find" what you need:
$(function(){
  $("table").tablesorter({
    textExtraction: function(node) {
      return $(node).find("span:last").text();
    }
  });
});
Now if the text you are finding in the script above is say a number, then just include the headers sorter option to specify how to sort it. Also in this example, we will specify that the special textExtraction code is only needed for the second column ("1" because we are using a zero-based index). All other columns will ignore this textExtraction function.


*NOTE* When writing this post, I didn't realize that the textExtraction option did not allow defining it per column, as shown below, but this has been fixed in the forked github version - example.
$(function(){
  $("table").tablesorter({
    textExtraction: {
      1: function(node) {
           return $(node).find("span:last").text();
      }
    },
    headers: {
      1: { sorter : "digit" }
    }
  });
});


Methods

See examples of each further down
sortonResort the table using new sort parameters.
updateUpdate the stored tablesorter data and the table.
appendCacheUpdate a table that has had its data dynamically updated; used in conjunction with "update"
updateCellUpdate a table cell in the tablesorter data.
applyWidgetIdApply a widget (wrapped in square brackets) to the table one time only.
applyWidgetsApply previously selected widgets to the table - will update the widget with new sort.

Resort the table - "sorton" method

See the full example in the tablesorter docs: Sort table using a link outside the table
// Choose a new sort order
var sort = [[0,0],[2,0]];
// Note that the sort value below is inside of another array (inside another set of square brackets)
$("table").trigger("sorton", [sort]);

Update the Table

See the full example in the tablesorter docs: Appending table data with ajax
// Add new content
$("table tbody").append(html);
// let the plugin know that we made a update
$("table").trigger("update");
// set sorting column and direction, this will sort on the first and third column
var sorting = [[2,1],[0,0]];
// sort on the first column
$("table").trigger("sorton", [sorting]);

Append Cache

If you dynamically change the table content, more than just one cell like in the "updateCell" example above, you may possibly have to trigger two events: "update" and "appendCache".

This answer is from a StackOverflow answer
// Table data was just dynamically updated
$(table)
  .trigger("update")
  .trigger("appendCache");

Update a Table Cell

Example from these alternate tablesorter docs: Updating the table cache - the demo doesn't work, but I've tested the example code below and it works properly.
$(function() {
  $("table").tablesorter();
  $("td.discount").click(function(){
      // randomize a number
      var discount = '$' + Math.round(Math.random() * Math.random() * 100) + '.' + ('0' + Math.round(Math.random() * Math.random() * 100)).slice(-2);
      $(this).text(discount);
      // update the table, so the tablesorter plugin knows its value
      $("table").trigger("updateCell",[this]);
      // set sorting column and direction, this will sort on the first and third column
      var sorting = [[3,1]];
      // sort on the first column
      $("table").trigger("sorton",[sorting]);
      return false;
  });
});
<table class="tablesorter" cellspacing="1">
  <thead>>
    <tr>
      <th>first name</th>
      <th>last name</th>
      <th>age</th>
      <th>total</th>
      <th>discount</th>
      <th>date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>peter</td>
      <td>parker</td>
      <td>28</td>
      <td class="discount">$9.99</td>
      <td>20%</td>
      <td>jul 6, 2006 8:14 am</td>
    </tr>
    <tr>
      <td>john</td>
      <td>hood</td>
      <td>33</td>
      <td class="discount">$19.99</td>
      <td>25%</td>
      <td>dec 10, 2002 5:14 am</td>
    </tr>
    <tr>
      <td>clark</td>
      <td>kent</td>
      <td>18</td>
      <td class="discount">$15.89</td>
      <td>44%</td>
      <td>jan 12, 2003 11:14 am</td>
    </tr>
    <tr>
      <td>bruce</td>
      <td>almighty</td>
      <td>45</td>
      <td class="discount">$153.19</td>
      <td>44%</td>
      <td>jan 18, 2001 9:12 am</td>
    </tr>
    <tr>
      <td>bruce</td>
      <td>evans</td>
      <td>22</td>
      <td class="discount">$13.19</td>
      <td>11%</td>
      <td>jan 18, 2007 9:12 am</td>
    </tr>
  </tbody>
</table>

Apply a New Widget "applyWidgetId"

Apply a widget to the table. In this example, we apply the zebra striping to the table after it has been initialized.
$(function(){
  // initialize tablesorter without the widget
  $("table").tablesorter();
  
  // click a button to apply the zebra striping
  $("button").click(function(){
    $('table').trigger('applyWidgetId', ['zebra']);
});

Apply Chosen Widgets "applyWidgets"

Reapply a widget to the table. In this example, we apply the zebra striping to the table after it has been initialized.

This is basically an alternate method to the "applyWidgetId", but in the example below you can add or remove widgets from the chosen list.
// Update the list of widgets to apply to the table (add or remove)
$("table").data("tablesorter").widgets = ["zebra"];
$("table").trigger('applyWidgets');




Triggered Events

sortStartThis event fires when the tablesorter plugin is about to start resorting the table.
sortEndThis event fires when the tablesorter plugin has completed resorting the table.


Bind to the "sortStart" and/or the "sortEnd" events as shown on the example page
$(function(){
  // initialize the tablesorter plugin
  $("table").tablesorter();
  // bind to sort events
  $("table")
    .bind("sortStart",function() {
      $("#overlay").show();
    })
    .bind("sortEnd",function() {
      $("#overlay").hide();
    });
});
Or here is another example from StackOverflow
$(function(){
  $("table")
    .tablesorter()  
    .bind("sortEnd", function(){  
      $("table tr").removeClass("block");
      // adds the "block" class to every 8th row
      $("table tr:nth-child(8)").addClass("block");
    });
});

Monday, June 6, 2011

Equalizer

This script was first written by Stephen Akins to equalize column heights in multiple rows. Chris Coyier of CSS Tricks then posted an update which allowed the heights to adjust while resizing a page. I simply debugged, added a few improvements (like minimum and maximum height, an idea from Mike Avello's plugin) and turned it into a plugin.


In the screen shot above, there are three blocks containing three columns. The three blocks have identical HTML. The left block is unmodified. The center block has Equalizer applied with a max height setting; and each block that exceeds the max height has a css class applied which sets the overflow to auto and adds the different background color for the demo, but you can do whatever you want via the css. And the right block has Equalizer applied with a minimum height setting; you should be able to see in the screen shot that the middle row of the right block has a minimum height set.

Try out the demo, resize your browser window and see how everything changes.