Example from the blue theme:
.tablesorter-blue .tablesorter-headerAsc {
@@ -469,7 +492,7 @@
cssDesc |
String |
"tablesorter-headerDesc" |
- The CSS style used to style the header when sorting descending. Default value Changed! v2.5.
+ | The CSS style used to style the header when sorting descending. Default value (changed v2.5).
Example from the blue theme:
.tablesorter-blue .tablesorter-headerDesc {
@@ -827,7 +850,7 @@ From the example function above, you'll end up with something similar to this HT
sorter: "isoDate" | Sort by ISO date (YYYY-MM-DD or YYYY/MM/DD; these formats can be followed by a time). |
sorter: "percent" | Sort by percent. |
sorter: "usLongDate" | Sort by date (U.S. Standard, e.g. Jan 18, 2001 9:12 AM or 18 Jan 2001 9:12 AM (new in v2.7.4)). |
- sorter: "shortDate" | Sort by a shorten date (see dateFormat ). |
+ sorter: "shortDate" | Sort by a shortened date (see dateFormat ; these formats can also be followed by a time). |
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. |
@@ -962,7 +985,7 @@ From the example function above, you'll end up with something similar to this HT
String |
"asc" |
- The direction a column sorts when clicking the header for the first time. Valid arguments are "asc" for Ascending or "desc" for Descending.
+ This sets the direction a column will sort when clicking on the header for the first time. Valid arguments are "asc" for Ascending or "desc" for Descending.
This order can also be set by desired column using the headers option (Added in v2.0.8).
@@ -2156,7 +2179,7 @@ $("table").trigger("sorton", [sort, callback]);
|
sortReset |
- Use this method to reset the table to it's initial unsorted state. New v2.4.7.
+ | Use this method to reset the table to it's initial unsorted state (v2.4.7).
Don't confuse this method with the sortReset option. This method immediately resets the entire table sort, while the option only resets the column sort after a third click.
// Reset the table (make it unsorted)
@@ -2167,7 +2190,7 @@ $("table").trigger("sortReset");
|
update |
- Update the stored tablesorter data and the table.
+ | Update the tbody 's stored data (updateRow does exactly the same thing)
// Add new content
$("table tbody").append(html);
@@ -2192,6 +2215,30 @@ $("table").trigger("sorton", [sorting]);
| Example |
+
+ updateAll |
+ Update a column of cells (thead and tbody ) New! v2.8.
+
+ // Change thead & tbody column of cells
+// remember, "eq()" is zero based & "nth-child()" is 1 based
+$("table thead th:eq(2)").html("Number");
+// add some random numbers to the table cell
+$("table tbody").find('td:nth-child(3)').html(function(i,h){
+ return Math.floor(Math.random()*10) + 1; // random number from 0 to 10
+});
+
+var resort = true, // re-apply the current sort
+ callback = function(){
+ alert('table updated!');
+ };
+
+// let the plugin know that we made a update, then the plugin will
+// automatically sort the table based on the header settings
+$("table").trigger("updateAll", [ resort, callback ]);
+ |
+ Example |
+
+
appendCache |
Update a table that has had its data dynamically changed; used in conjunction with "update".
@@ -2290,14 +2337,15 @@ $('table').trigger('applyWidgets');
$("table").trigger("destroy");
// Remove tablesorter and all classes but the "tablesorter" class on the table
-$("table").trigger("destroy", [false];
+// callback is a function
+$("table").trigger("destroy", [false, callback]);
|
|
refreshWidgets |
- Refresh the currently applied widgets. Depending on the options, it will completely remove all widgets, then re-initialize the current widgets or just remove all non-current widgets. New v2.4.
+ | Refresh the currently applied widgets. Depending on the options, it will completely remove all widgets, then re-initialize the current widgets or just remove all non-current widgets (v2.4).
Trigger this method using either of the following methods (they are equivalent):
// trigger a refresh widget event
@@ -2324,7 +2372,7 @@ $.tablesorter.refreshWidgets(table, doAll, dontapply)
search |
- Trigger the filter widget to update the search from current inputs and/or selections. Updated! v2.4.
+ | Trigger the filter widget to update the search from current inputs and/or selections (v2.4).
This first method sends an array with the search strings to the filter widget. $(function(){
// apply "2?%" filter to the fifth column (zero-based index)
@@ -2509,7 +2557,7 @@ or, directly add the search string to the filter input as follows:updateComplete |
This event fires after tablesorter has completed updating. (v.2.3.9)
- This occurs after an "update", "updateCell" or "addRows" method was called, but before any callback functions are executed.
+ This occurs after an "update", "updateAll", "updateCell" or "addRows" method was called, but before any callback functions are executed.
$(function(){
// initialize the tablesorter plugin
@@ -2588,7 +2636,7 @@ or, directly add the search string to the filter input as follows:
pagerBeforeInitialized |
- This event fires after all pager controls have been bound and set up but before the pager formats the table or loads any ajax data. New v2.4.4.
+ | This event fires after all pager controls have been bound and set up but before the pager formats the table or loads any ajax data (v2.4.4).
$(function(){
@@ -2614,7 +2662,7 @@ or, directly add the search string to the filter input as follows:
pagerInitialized |
- This event fires when the pager plugin has completed initialization. New v2.4.4.
+ | This event fires when the pager plugin has completed initialization (v2.4.4).
$(function(){
@@ -2641,7 +2689,7 @@ or, directly add the search string to the filter input as follows:
pageMoved |
- This event fires when the pager plugin begins to change to the selected page. New v2.4.4.
+ | This event fires when the pager plugin begins to change to the selected page (v2.4.4).
This event may fire before the pagerComplete event when ajax processing is involved, or after the pagerComplete on normal use.
See issue #153.
@@ -2681,7 +2729,7 @@ or, directly add the search string to the filter input as follows:
filterInit |
- Event triggered when the filter widget has finished initializing. New v2.4.
+ | Event triggered when the filter widget has finished initializing (v2.4).
You can use this event to modify the filter elements (row, inputs and/or selects) as desired. Use it as follows: $(function(){
$('table').bind('filterInit', function(){
@@ -2694,7 +2742,7 @@ or, directly add the search string to the filter input as follows:
filterStart |
- Event triggered when the filter widget has started processing the search. New v2.4.
+ | Event triggered when the filter widget has started processing the search (v2.4).
You can use this event to do something like add a class to the filter row. Use it as follows: $(function(){
$('table').bind('filterStart', function(){
@@ -2707,7 +2755,7 @@ or, directly add the search string to the filter input as follows:
filterEnd |
- Event triggered when the filter widget has finished processing the search. New v2.4.
+ | Event triggered when the filter widget has finished processing the search (v2.4).
You can use this event to do something like remove the class added to the filter row when the filtering started. Use it as follows: $(function(){
$('table').bind('filterEnd', function(){
@@ -2766,7 +2814,7 @@ or, directly add the search string to the filter input as follows:fork a copy on github.
- Some basic unit testing has been added. If you would like to add more or report a problem, please use the appropriate link above. New! v2.6.
+ Some basic unit testing has been added. If you would like to add more or report a problem, please use the appropriate link above (v2.6).
Support is also available from stackoverflow.
diff --git a/js/jquery.tablesorter.js b/js/jquery.tablesorter.js
index 704efb28..49dcbff3 100644
--- a/js/jquery.tablesorter.js
+++ b/js/jquery.tablesorter.js
@@ -131,9 +131,9 @@
text = $(node).text();
}
} else {
- if (typeof(t) === "function") {
+ if (typeof t === "function") {
text = t(node, table, cellIndex);
- } else if (typeof(t) === "object" && t.hasOwnProperty(cellIndex)) {
+ } else if (typeof t === "object" && t.hasOwnProperty(cellIndex)) {
text = t[cellIndex](node, table, cellIndex);
} else {
text = c.supportsTextContent ? node.textContent : $(node).text();
@@ -208,7 +208,7 @@
if (c.debug) {
log(parsersDebug);
}
- return list;
+ c.parsers = list;
}
/* utils */
@@ -374,7 +374,8 @@
function buildHeaders(table) {
var header_index = computeThIndexes(table), ch, $t,
h, i, t, lock, time, c = table.config;
- c.headerList = [], c.headerContent = [];
+ c.headerList = [];
+ c.headerContent = [];
if (c.debug) {
time = new Date();
}
@@ -398,7 +399,7 @@
this.count = -1; // set to -1 because clicking on the header automatically adds one
this.lockedOrder = false;
lock = ts.getData($t, ch, 'lockedOrder') || false;
- if (typeof(lock) !== 'undefined' && lock !== false) {
+ if (typeof lock !== 'undefined' && lock !== false) {
this.order = this.lockedOrder = formatSortingOrder(lock) ? [1,1,1] : [0,0,0];
}
$t.addClass(c.cssHeader);
@@ -415,13 +416,23 @@
}
}
- function updateHeader(table) {
- var s, th,
+ function commonUpdate(table, resort, callback) {
+ var $t = $(table),
c = table.config;
+ // remove rows/elements before update
+ $t.find(c.selectorRemove).remove();
+ // rebuild parsers
+ buildParserCache(table);
+ // rebuild the cache map
+ buildCache(table);
+ checkResort($t, resort, callback);
+ }
+
+ function updateHeader(table) {
+ var s, c = table.config;
c.$headers.each(function(index, th){
s = ts.getData( th, c.headers[index], 'sorter' ) === 'false';
th.sortDisabled = s;
- // $t.toggleClass('sorter-false', this.sortDisabled); not supported until jQuery 1.3
$(th)[ s ? 'addClass' : 'removeClass' ]('sorter-false');
});
}
@@ -590,9 +601,9 @@
// sort multiple columns
function multisort(table) { /*jshint loopfunc:true */
- var dynamicExp, sortWrapper, col, mx = 0, dir = 0, tc = table.config,
+ var dir = 0, tc = table.config,
sortList = tc.sortList, l = sortList.length, bl = table.tBodies.length,
- sortTime, i, j, k, c, colMax, cache, lc, s, e, order, orgOrderCol;
+ sortTime, i, k, c, colMax, cache, lc, s, order, orgOrderCol;
if (tc.serverSideSorting || !tc.cache[0]) { // empty table - fixes #206
return;
}
@@ -646,6 +657,149 @@
}
}
+ function bindEvents(table){
+ var c = table.config,
+ $this = $(table),
+ j, downTime;
+ // apply event handling to headers
+ c.$headers
+ // http://stackoverflow.com/questions/5312849/jquery-find-self; andSelf() deprecated in jQuery 1.8
+ .find('*')[ $.fn.addBack ? 'addBack': 'andSelf' ]().filter(c.selectorSort)
+ .unbind('mousedown.tablesorter mouseup.tablesorter')
+ .bind('mousedown.tablesorter mouseup.tablesorter', function(e, external) {
+ // jQuery v1.2.6 doesn't have closest()
+ var $cell = this.tagName.match('TH|TD') ? $(this) : $(this).parents('th, td').filter(':last'), cell = $cell[0];
+ // only recognize left clicks
+ if ((e.which || e.button) !== 1) { return false; }
+ // set timer on mousedown
+ if (e.type === 'mousedown') {
+ downTime = new Date().getTime();
+ return e.target.tagName === "INPUT" ? '' : !c.cancelSelection;
+ }
+ // ignore long clicks (prevents resizable widget from initializing a sort)
+ if (external !== true && (new Date().getTime() - downTime > 250)) { return false; }
+ if (c.delayInit && !c.cache) { buildCache(table); }
+ if (!cell.sortDisabled) {
+ initSort(table, cell, e);
+ }
+ });
+ if (c.cancelSelection) {
+ // cancel selection
+ c.$headers.each(function() {
+ this.onselectstart = function() {
+ return false;
+ };
+ });
+ }
+ // apply easy methods that trigger bound events
+ $this
+ .unbind('sortReset update updateRows updateCell updateAll addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter '))
+ .bind("sortReset.tablesorter", function(e){
+ e.stopPropagation();
+ c.sortList = [];
+ setHeadersCss(table);
+ multisort(table);
+ appendToTable(table);
+ })
+ .bind("updateAll.tablesorter", function(e, resort, callback){
+ e.stopPropagation();
+ ts.restoreHeaders(table);
+ buildHeaders(table);
+ bindEvents(table);
+ commonUpdate(table, resort, callback);
+ })
+ .bind("update.tablesorter updateRows.tablesorter", function(e, resort, callback) {
+ e.stopPropagation();
+ // update sorting (if enabled/disabled)
+ updateHeader(table);
+ commonUpdate(table, resort, callback);
+ })
+ .bind("updateCell.tablesorter", function(e, cell, resort, callback) {
+ e.stopPropagation();
+ $this.find(c.selectorRemove).remove();
+ // get position from the dom
+ var l, row, icell,
+ $tb = $this.find('tbody'),
+ // update cache - format: function(s, table, cell, cellIndex)
+ // no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr');
+ tbdy = $tb.index( $(cell).parents('tbody').filter(':last') ),
+ $row = $(cell).parents('tr').filter(':last');
+ cell = $(cell)[0]; // in case cell is a jQuery object
+ // tbody may not exist if update is initialized while tbody is removed for processing
+ if ($tb.length && tbdy >= 0) {
+ row = $tb.eq(tbdy).find('tr').index( $row );
+ icell = cell.cellIndex;
+ l = c.cache[tbdy].normalized[row].length - 1;
+ c.cache[tbdy].row[table.config.cache[tbdy].normalized[row][l]] = $row;
+ c.cache[tbdy].normalized[row][icell] = c.parsers[icell].format( getElementText(table, cell, icell), table, cell, icell );
+ checkResort($this, resort, callback);
+ }
+ })
+ .bind("addRows.tablesorter", function(e, $row, resort, callback) {
+ e.stopPropagation();
+ var i, rows = $row.filter('tr').length,
+ dat = [], l = $row[0].cells.length,
+ tbdy = $this.find('tbody').index( $row.closest('tbody') );
+ // fixes adding rows to an empty table - see issue #179
+ if (!c.parsers) {
+ buildParserCache(table);
+ }
+ // add each row
+ for (i = 0; i < rows; i++) {
+ // add each cell
+ for (j = 0; j < l; j++) {
+ dat[j] = c.parsers[j].format( getElementText(table, $row[i].cells[j], j), table, $row[i].cells[j], j );
+ }
+ // add the row index to the end
+ dat.push(c.cache[tbdy].row.length);
+ // update cache
+ c.cache[tbdy].row.push([$row[i]]);
+ c.cache[tbdy].normalized.push(dat);
+ dat = [];
+ }
+ // resort using current settings
+ checkResort($this, resort, callback);
+ })
+ .bind("sorton.tablesorter", function(e, list, callback, init) {
+ e.stopPropagation();
+ $this.trigger("sortStart", this);
+ // update header count index
+ updateHeaderSortCount(table, list);
+ // set css for headers
+ setHeadersCss(table);
+ // sort the table and append it to the dom
+ multisort(table);
+ appendToTable(table, init);
+ if (typeof callback === "function") {
+ callback(table);
+ }
+ })
+ .bind("appendCache.tablesorter", function(e, callback, init) {
+ e.stopPropagation();
+ appendToTable(table, init);
+ if (typeof callback === "function") {
+ callback(table);
+ }
+ })
+ .bind("applyWidgetId.tablesorter", function(e, id) {
+ e.stopPropagation();
+ ts.getWidgetById(id).format(table, c, c.widgetOptions);
+ })
+ .bind("applyWidgets.tablesorter", function(e, init) {
+ e.stopPropagation();
+ // apply widgets
+ ts.applyWidget(table, init);
+ })
+ .bind("refreshWidgets.tablesorter", function(e, all, dontapply){
+ e.stopPropagation();
+ ts.refreshWidgets(table, all, dontapply);
+ })
+ .bind("destroy.tablesorter", function(e, c, cb){
+ e.stopPropagation();
+ ts.destroy(table, c, cb);
+ });
+ }
+
/* public methods */
ts.construct = function(settings) {
return this.each(function() {
@@ -654,8 +808,8 @@
return (this.config && this.config.debug) ? log('stopping initialization! No thead, tbody or tablesorter has already been initialized') : '';
}
// declare
- var $cell, $this = $(this), table = this,
- c, i, j, k = '', a, s, o, downTime,
+ var $this = $(this), table = this,
+ c, k = '',
m = $.metadata;
// initialization flag
table.hasInitialized = false;
@@ -685,148 +839,12 @@
// do this after theme has been applied
fixColumnWidth(table);
// try to auto detect column type, and store in tables config
- c.parsers = buildParserCache(table);
+ buildParserCache(table);
// build the cache for the tbody cells
// delayInit will delay building the cache until the user starts a sort
if (!c.delayInit) { buildCache(table); }
- // apply event handling to headers
- // this is to big, perhaps break it out?
- c.$headers
- // http://stackoverflow.com/questions/5312849/jquery-find-self; andSelf() deprecated in jQuery 1.8
- .find('*')[ $.fn.addBack ? 'addBack': 'andSelf' ]().filter(c.selectorSort)
- .unbind('mousedown.tablesorter mouseup.tablesorter')
- .bind('mousedown.tablesorter mouseup.tablesorter', function(e, external) {
- // jQuery v1.2.6 doesn't have closest()
- var $cell = this.tagName.match('TH|TD') ? $(this) : $(this).parents('th, td').filter(':last'), cell = $cell[0];
- // only recognize left clicks
- if ((e.which || e.button) !== 1) { return false; }
- // set timer on mousedown
- if (e.type === 'mousedown') {
- downTime = new Date().getTime();
- return e.target.tagName === "INPUT" ? '' : !c.cancelSelection;
- }
- // ignore long clicks (prevents resizable widget from initializing a sort)
- if (external !== true && (new Date().getTime() - downTime > 250)) { return false; }
- if (c.delayInit && !c.cache) { buildCache(table); }
- if (!cell.sortDisabled) {
- initSort(table, cell, e);
- }
- });
- if (c.cancelSelection) {
- // cancel selection
- c.$headers.each(function() {
- this.onselectstart = function() {
- return false;
- };
- });
- }
- // apply easy methods that trigger bound events
- $this
- .unbind('sortReset update updateRows updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter '))
- .bind("sortReset.tablesorter", function(){
- e.stopPropagation();
- c.sortList = [];
- setHeadersCss(table);
- multisort(table);
- appendToTable(table);
- })
- .bind("update.tablesorter updateRows.tablesorter", function(e, resort, callback) {
- e.stopPropagation();
- // remove rows/elements before update
- $this.find(c.selectorRemove).remove();
- // update sorting
- updateHeader(table);
- // rebuild parsers
- c.parsers = buildParserCache(table);
- // rebuild the cache map
- buildCache(table);
- checkResort($this, resort, callback);
- })
- .bind("updateCell.tablesorter", function(e, cell, resort, callback) {
- e.stopPropagation();
- $this.find(c.selectorRemove).remove();
- // get position from the dom
- var l, row, icell,
- $tb = $this.find('tbody'),
- // update cache - format: function(s, table, cell, cellIndex)
- // no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr');
- tbdy = $tb.index( $(cell).parents('tbody').filter(':last') ),
- $row = $(cell).parents('tr').filter(':last');
- cell = $(cell)[0]; // in case cell is a jQuery object
- // tbody may not exist if update is initialized while tbody is removed for processing
- if ($tb.length && tbdy >= 0) {
- row = $tb.eq(tbdy).find('tr').index( $row );
- icell = cell.cellIndex;
- l = c.cache[tbdy].normalized[row].length - 1;
- c.cache[tbdy].row[table.config.cache[tbdy].normalized[row][l]] = $row;
- c.cache[tbdy].normalized[row][icell] = c.parsers[icell].format( getElementText(table, cell, icell), table, cell, icell );
- checkResort($this, resort, callback);
- }
- })
- .bind("addRows.tablesorter", function(e, $row, resort, callback) {
- e.stopPropagation();
- var i, rows = $row.filter('tr').length,
- dat = [], l = $row[0].cells.length,
- tbdy = $this.find('tbody').index( $row.closest('tbody') );
- // fixes adding rows to an empty table - see issue #179
- if (!c.parsers) {
- c.parsers = buildParserCache(table);
- }
- // add each row
- for (i = 0; i < rows; i++) {
- // add each cell
- for (j = 0; j < l; j++) {
- dat[j] = c.parsers[j].format( getElementText(table, $row[i].cells[j], j), table, $row[i].cells[j], j );
- }
- // add the row index to the end
- dat.push(c.cache[tbdy].row.length);
- // update cache
- c.cache[tbdy].row.push([$row[i]]);
- c.cache[tbdy].normalized.push(dat);
- dat = [];
- }
- // resort using current settings
- checkResort($this, resort, callback);
- })
- .bind("sorton.tablesorter", function(e, list, callback, init) {
- e.stopPropagation();
- $this.trigger("sortStart", this);
- // update header count index
- updateHeaderSortCount(table, list);
- // set css for headers
- setHeadersCss(table);
- // sort the table and append it to the dom
- multisort(table);
- appendToTable(table, init);
- if (typeof callback === "function") {
- callback(table);
- }
- })
- .bind("appendCache.tablesorter", function(e, callback, init) {
- e.stopPropagation();
- appendToTable(table, init);
- if (typeof callback === "function") {
- callback(table);
- }
- })
- .bind("applyWidgetId.tablesorter", function(e, id) {
- e.stopPropagation();
- ts.getWidgetById(id).format(table, c, c.widgetOptions);
- })
- .bind("applyWidgets.tablesorter", function(e, init) {
- e.stopPropagation();
- // apply widgets
- ts.applyWidget(table, init);
- })
- .bind("refreshWidgets.tablesorter", function(e, all, dontapply){
- e.stopPropagation();
- ts.refreshWidgets(table, all, dontapply);
- })
- .bind("destroy.tablesorter", function(e, c, cb){
- e.stopPropagation();
- ts.destroy(table, c, cb);
- });
-
+ // bind all header events and methods
+ bindEvents(table);
// get sort list from jQuery data or metadata
// in jQuery < 1.4, an error occurs when calling $this.data()
if (c.supportsDataObject && typeof $this.data().sortlist !== 'undefined') {
@@ -888,7 +906,7 @@
// detach tbody but save the position
// don't use tbody because there are portions that look for a tbody index (updateCell)
ts.processTbody = function(table, $tb, getIt){
- var t, holdr;
+ var holdr;
if (getIt) {
table.isProcessing = true;
$tb.before('');
@@ -905,6 +923,18 @@
$(table)[0].config.$tbodies.empty();
};
+ // restore headers
+ ts.restoreHeaders = function(table){
+ var c = table.config;
+ c.$headers.each(function(i){
+ // only restore header cells if it is wrapped
+ // because this is also used by the updateAll method
+ if ($(this).find('.tablesorter-header-inner').length){
+ $(this).html( c.headerContent[i] );
+ }
+ });
+ };
+
ts.destroy = function(table, removeClasses, callback){
table = $(table)[0];
if (!table.hasInitialized) { return; }
@@ -919,15 +949,12 @@
// disable tablesorter
$t
.removeData('tablesorter')
- .unbind('sortReset update updateRows updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave sortBegin sortEnd '.split(' ').join('.tablesorter '));
+ .unbind('sortReset update updateAll updateRows updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave sortBegin sortEnd '.split(' ').join('.tablesorter '));
c.$headers.add($f)
.removeClass(c.cssHeader + ' ' + c.cssAsc + ' ' + c.cssDesc)
.removeAttr('data-column');
$r.find(c.selectorSort).unbind('mousedown.tablesorter mouseup.tablesorter');
- // restore headers
- $r.children().each(function(i){
- $(this).html( c.headerContent[i] );
- });
+ ts.restoreHeaders(table);
if (removeClasses !== false) {
$t.removeClass(c.tableClass + ' tablesorter-' + c.theme);
}
@@ -951,8 +978,8 @@
if (a === b) { return 0; }
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ],
r = ts.regex, xN, xD, yN, yD, xF, yF, i, mx;
- if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : -e || -1; }
- if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : e || 1; }
+ if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; }
+ if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; }
if (typeof c.textSorter === 'function') { return c.textSorter(a, b, table, col); }
// chunk/tokenize
xN = a.replace(r[0], '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0');
@@ -987,8 +1014,8 @@
ts.sortTextDesc = function(table, a, b, col) {
if (a === b) { return 0; }
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ];
- if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : e || 1; }
- if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : -e || -1; }
+ if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; }
+ if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; }
if (typeof c.textSorter === 'function') { return c.textSorter(b, a, table, col); }
return ts.sortText(table, b, a);
};
@@ -1011,8 +1038,8 @@
ts.sortNumeric = function(table, a, b, col, mx, d) {
if (a === b) { return 0; }
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ];
- if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : -e || -1; }
- if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : e || 1; }
+ if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; }
+ if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; }
if (isNaN(a)) { a = ts.getTextValue(a, mx, d); }
if (isNaN(b)) { b = ts.getTextValue(b, mx, d); }
return a - b;
@@ -1021,8 +1048,8 @@
ts.sortNumericDesc = function(table, a, b, col, mx, d) {
if (a === b) { return 0; }
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ];
- if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : e || 1; }
- if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : -e || -1; }
+ if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; }
+ if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; }
if (isNaN(a)) { a = ts.getTextValue(a, mx, d); }
if (isNaN(b)) { b = ts.getTextValue(b, mx, d); }
return b - a;
@@ -1187,7 +1214,7 @@
};
ts.formatFloat = function(s, table) {
- if (typeof(s) !== 'string' || s === '') { return s; }
+ if (typeof s !== 'string' || s === '') { return s; }
// allow using formatFloat without a table; defaults to US number format
var i,
t = table && table.config ? table.config.usNumberFormat !== false :
@@ -1228,10 +1255,10 @@
// add default parsers
ts.addParser({
id: "text",
- is: function(s, table, node) {
+ is: function() {
return true;
},
- format: function(s, table, cell, cellIndex) {
+ format: function(s, table) {
var c = table.config;
if (s) {
s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s );
@@ -1331,7 +1358,7 @@
id: "shortDate", // "mmddyyyy", "ddmmyyyy" or "yyyymmdd"
is: function(s) {
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
- return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test((s || '').replace(/\s+/g," ").replace(/[-.,]/g, "/"));
+ return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test((s || '').replace(/\s+/g," ").replace(/[\-.,]/g, "/"));
},
format: function(s, table, cell, cellIndex) {
if (s) {
@@ -1341,7 +1368,7 @@
// cache header formatting so it doesn't getData for every cell in the column
format = ci.shortDateFormat = ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat;
}
- s = s.replace(/\s+/g," ").replace(/[-.,]/g, "/");
+ s = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error
if (format === "mmddyyyy") {
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
} else if (format === "ddmmyyyy") {
@@ -1368,7 +1395,7 @@
ts.addParser({
id: "metadata",
- is: function(s) {
+ is: function() {
return false;
},
format: function(s, table, cell) {
@@ -1414,7 +1441,7 @@
remove: function(table, c, wo){
var k, $tb,
b = c.$tbodies,
- rmv = (c.widgetOptions.zebra || [ "even", "odd" ]).join(' ');
+ rmv = (wo.zebra || [ "even", "odd" ]).join(' ');
for (k = 0; k < b.length; k++ ){
$tb = $.tablesorter.processTbody(table, b.eq(k), true); // remove tbody
$tb.children().removeClass(rmv);
diff --git a/test.html b/test.html
index af357798..3070fee6 100644
--- a/test.html
+++ b/test.html
@@ -24,15 +24,15 @@
table2 = $table2[0],
th0 = $table1.find('th')[0], // first table header cell
init = false,
- undef, c1, c2, i, l, t;
+ undef, c1, c2, e, i, l, t;
- $('.tester:eq(0)')
+ $table1
.bind('tablesorter-initialized', function(){
init = true;
})
.tablesorter();
- $('.tester:eq(1)').tablesorter({
+ $table2.tablesorter({
headers: {
0: { sorter: 'text' },
1: { sorter: 'text' },
@@ -223,38 +223,61 @@
************************************************/
test( "parser cache; sorton methods", function() {
expect(3);
+ $table1.trigger('sortReset');
// lower case because table was parsed before c1.ignoreCase was changed
- tester.cacheCompare( table1, [ 'test2', 2, 'test1', 3, 'test3', 1, '', '', 'testb', 5, 'testc', 4, 'testa', 6 ], 'unsorted' );
+ tester.cacheCompare( table1, [ 'test2', 'x2', 'test1', 'x3', 'test3', 'x1', '', '', 'testb', 'x5', 'testc', 'x4', 'testa', 'x6' ], 'unsorted' );
$table1.trigger('sorton', [[[ 0,0 ]]]);
- tester.cacheCompare( table1, [ 'test1', 3, 'test2', 2, 'test3', 1, '', '', 'testa', 6, 'testb', 5, 'testc', 4 ], 'ascending sort' );
+ tester.cacheCompare( table1, [ 'test1', 'x3', 'test2', 'x2', 'test3', 'x1', '', '', 'testa', 'x6', 'testb', 'x5', 'testc', 'x4' ], 'ascending sort' );
$table1.trigger('sorton', [[[ 0,1 ]]]);
- tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'descending sort' );
+ tester.cacheCompare( table1, [ 'test3', 'x1', 'test2', 'x2', 'test1', 'x3', '', '', 'testc', 'x4', 'testb', 'x5', 'testa', 'x6' ], 'descending sort' );
});
+
/************************************************
test update methods
************************************************/
test( "parser cache; update methods", function() {
- expect(3);
+ expect(5);
+ c1.ignoreCase = true;
+
+ // updateAll
+ $table1
+ .find('th:eq(1)').removeAttr('class').html('num').end()
+ .find('td:nth-child(2)').html(function(i,h){
+ return h.substring(1);
+ });
+ $table1.trigger('updateAll', [false, function(){
+ c1 = $table1[0].config;
+ var nw = $table1.find('th:eq(1)')[0],
+ hc = c1.headerContent[1] === 'num',
+ hd = c1.$headers[1] === nw,
+ hl = c1.headerList[1] === nw,
+ p1 = c1.parsers[1].id === 'digit';
+ equal(hc && hd && hl && p1, true, 'testing header cache: updateAll - thead');
+ tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateAll - tbody' );
+ }]);
+
// addRows
t = $('testd | 7 | ');
$table1.find('tbody:last').append(t);
- $table1.trigger('addRows', [t, true]);
- tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testd', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'addRows method' );
+ $table1.trigger('addRows', [t, true, function(){
+ tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testd', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'addRows method' );
+ }]);
// updateCell
t = $table1.find('td:contains("testd")');
t.html('texte');
- $table1.trigger('updateCell', [t[0], true]);
- tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'texte', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' );
+ $table1.trigger('updateCell', [t[0], true, function(){
+ tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'texte', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' );
+ }]);
// update
$table1.find('tr.temp').remove();
- c1.ignoreCase = true;
- $table1.trigger('update', [true]);
- tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' );
+ $table1.trigger('update', [true, function(){
+ tester.cacheCompare( table1, [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' );
+ }]);
});
@@ -291,6 +314,26 @@
equal( zebra(), true, 'zebra is applied' );
});
+ /************************************************
+ check destroy method
+ ************************************************/
+ test("testing destroy method", function(){
+ $table2.trigger('sorton', [[[ 0,1 ]]] );
+ $table2.trigger('destroy');
+ expect(7);
+ t = $table2.find('th:first');
+ e = jQuery._data(table2, 'events'); // get a list of all bound events
+ equal( $.isEmptyObject(e), true, 'no events applied' );
+ equal( $table2.data().hasOwnProperty('tablesorter'), false, 'Data removed' );
+ equal( $table2.attr('class'), 'tester', 'All table classes removed' );
+ equal( $table2.find('tr:first').attr('class'), '', 'Header row class removed' );
+ equal( t.attr('class').match('tablesorter'), null, 'Header classes removed' );
+ equal( t.children().length, 0, 'Inner wrapper removed' );
+ equal( typeof (t.data().column) , 'undefined', 'data-column removed');
+
+ $table2.tablesorter();
+ });
+
});
@@ -320,20 +363,20 @@
test-head | num |
- test-foot | num |
+ test-foot | txt |
- test2 | 2 |
- test1 | 3 |
- test3 | 1 |
+ test2 | x2 |
+ test1 | x3 |
+ test3 | x1 |
Info |
- testB | 5 |
- testC | 4 |
- testA | 6 |
+ testB | x5 |
+ testC | x4 |
+ testA | x6 |
| | | | | | | | |