mirror of
https://github.com/Mottie/tablesorter.git
synced 2024-11-15 23:54:22 +00:00
cleanup & version bump
This commit is contained in:
parent
224d7acb24
commit
35be6689fb
196
README.md
196
README.md
@ -47,6 +47,62 @@ tablesorter can successfully parse and sort many types of data including linked
|
||||
|
||||
View the [complete listing here](https://github.com/Mottie/tablesorter/wiki/Change).
|
||||
|
||||
#### <a name="v2.15.6">Version 2.15.6</a> (3/7/2014)
|
||||
|
||||
* Doc
|
||||
* Added docs for `$.tablesorter.language` which contains the text used in the `aria-label` for the header
|
||||
* Update `isValueInArray` & `sortAppend` docs.
|
||||
|
||||
* Core
|
||||
* Destroy now unbinds the `updateCache` method properly
|
||||
* Update `$.tablesorter.isValueInArray` function & `sortAppend` option. Fixes [issue #523](https://github.com/Mottie/tablesorter/issues/523).
|
||||
* All test dates are now time zone & DST independent. Fixes [issue #516](https://github.com/Mottie/tablesorter/issues/516).
|
||||
* Added tests for `sortForce`, `sortAppend`, `sortMultiSortKey` and `sortResetKey`.
|
||||
* Cache natural sort regex.
|
||||
* Date parsers now return the original cell text instead of an empty string when encountering invalid dates. Sort of fixes [issue #531](https://github.com/Mottie/tablesorter/issues/531).
|
||||
* Event fixes:
|
||||
* Sort events will now only show when the table is being sorted; previously when updating an unsorted table, sort events would fire.
|
||||
* The `updateComplete` event now fires after every triggered update (`update`, `updateRows`, `updateAll`, `updateCell` & `addRows`)
|
||||
* Updated pager to correctly trigger the `updateComplete` event when using ajax.
|
||||
* Added unit tests to ensure these events fire on an empty table.
|
||||
* Fixes [issue #532](https://github.com/Mottie/tablesorter/issues/532)
|
||||
|
||||
* ColumnSelector widget
|
||||
* Make column disable, visible & invisible methods consistent. Fixes [issue #519](https://github.com/Mottie/tablesorter/issues/519)
|
||||
|
||||
* Filter widget
|
||||
* Preset filter searches (set by `data-value` on the header) work again. Fixes issues [#511](https://github.com/Mottie/tablesorter/issues/511) & [#525](https://github.com/Mottie/tablesorter/issues/525).
|
||||
* Add note to docs about adding a placeholder. Fixes [issue #522](https://github.com/Mottie/tablesorter/issues/522).
|
||||
* Filter build select function no longer causes a javascript error on empty tables. Fixes [issue #528](https://github.com/Mottie/tablesorter/issues/528).
|
||||
|
||||
* Grouping widget
|
||||
* The `collapsed` option once again shows the group headers. Fixes issues [#514](https://github.com/Mottie/tablesorter/issues/514) & [533](https://github.com/Mottie/tablesorter/issues/533)
|
||||
* Add `group_saveGroups` & `group_saveReset` options:
|
||||
* The `group_saveGroups` option (`true` by default) saves the group name of any collapsed groups (requires `group_collapsible` to be `true`)
|
||||
* The `group_saveReset` option (`null` by default) contains a jQuery selector string or jQuery object pointing to an element to be used to clear the saved groups.
|
||||
* Both of these options require the storage utility script contained within the `jquery.tablesorter.widgets.js` file.
|
||||
* Fullfils feature request of [issue #514](https://github.com/Mottie/tablesorter/issues/514).
|
||||
* Added details about using regular expressions within the `group_separator` option.
|
||||
|
||||
* Header Titles widget (headerTitles)
|
||||
* New widget which adds the current sort to the header title attribute.
|
||||
* It distinguishes between a text and numeric sort and includes the current sort direction
|
||||
* A prefix can be included.
|
||||
* By default, an ascending sort shows either "A - Z" or "0 - 9", or "Z - A" or "9 - 0" for descending sorts.
|
||||
* Note that date columns will show as numeric
|
||||
* Fixes [issue #529](https://github.com/Mottie/tablesorter/issues/529).
|
||||
|
||||
* Pager (addon & widget)
|
||||
* Ensure empty array `[]` and array of empty strings `['', '', '']` evaluate as the same when checking if the filters have changed. Fixes [issue #202](https://github.com/Mottie/tablesorter/issues/202) (again).
|
||||
* Compare `totalRows` vs. `totalPages` when preventing an ajax call.
|
||||
* Changes to make the `updateComplete` event fire, but because of the asynchronous nature of ajax, it fires before any `sortEnd` events. It may take some more work to resolve this, if it becomes a concern.
|
||||
* Attempted to fix pager row count issue. See [issue #455](https://github.com/Mottie/tablesorter/issues/455).
|
||||
|
||||
* Miscellaneous
|
||||
* Pager custom controls (beta) now shows no pages on a single page. Fixes [issue #518](https://github.com/Mottie/tablesorter/issues/518)
|
||||
* Increase Bootstrap 3 theme css specificity. See [issue #515](https://github.com/Mottie/tablesorter/issues/515)
|
||||
* Checkbox parser no longer causes a js error when a checkbox doesn't exist.
|
||||
|
||||
#### <a name="v2.15.5">Version 2.15.5</a> (2/23/2014)
|
||||
|
||||
* Pager widget now initializes properly when using ajax. Fixes [issue #510](https://github.com/Mottie/tablesorter/issues/510).
|
||||
@ -77,143 +133,3 @@ View the [complete listing here](https://github.com/Mottie/tablesorter/wiki/Chan
|
||||
* Added `delayInit` demo ([pull #504](https://github.com/Mottie/tablesorter/issues/473)) - thanks [Infeligo](https://github.com/Infeligo)!
|
||||
* Fixed some markup issues & rearranged some links
|
||||
* Updated minified widget file date. Fixes [issue #505](https://github.com/Mottie/tablesorter/issues/505)
|
||||
|
||||
#### <a name="v2.15.1">Version 2.15.1</a> (2/19/2014)
|
||||
|
||||
* Filter widget
|
||||
* Switched method of saving last search times, as cloned table parts would not include saved data
|
||||
* Fixes [issue #473](https://github.com/Mottie/tablesorter/issues/473).
|
||||
|
||||
#### <a name="v2.15">Version 2.15.0</a> (2/19/2014)
|
||||
|
||||
* Core
|
||||
* Add accessibility attributes to tablesorter (aria).
|
||||
* Make header's `bindEvent` function public to allow easier binding to cloned table headers.
|
||||
* Add an unsorted header class name option `cssNone` (empty string by default) and now all unsorted headers will have a class name of `tablesorter-headerUnSorted` applied; updated destroy method to remove header unsorted class name.
|
||||
* Ensure only "updateRow" is triggered within the pager plugin to prevent issues with Proptype.js, see [issue #217](https://github.com/Mottie/tablesorter/issues/217).
|
||||
* Clean up all public API functions to accept `table` as either a DOM element or a jQuery table object.
|
||||
* The log will now display console errors and/or warnings based on those key words.
|
||||
* Consolidated all default class names used by the plugin within `$.tablesorter.css` - these are class names that are not set by the options.
|
||||
|
||||
* Docs
|
||||
* Organize the examples section to make it easier to find the desired sort demo.
|
||||
* Add associated tablesorter option (with link) with the appropriate examples.
|
||||
* Add a "Custom parsers" section instead of lumping it in with the widgets.
|
||||
* Add a "Work-in-progress" section for some beta demos.
|
||||
* Add indicators to show which widgets are contained within the `jquery.tablesorter.widgets.js` file.
|
||||
* Add an "API" section which gives details on how to use tablesorters available public variables & functions in both the core and widgets.
|
||||
* Colorize the left border of code blocks to differentiate HTML, CSS and javascript.
|
||||
* Update & consolidate jQuery UI accordion code.
|
||||
* Miscellaneous demo fixes.
|
||||
|
||||
* Parsers
|
||||
* The "shortDate" parser now works properly with header colspans. Fixes [issue #474](https://github.com/Mottie/tablesorter/issues/474).
|
||||
* The "currency" parser will now properly detect currencies which include a plus or minus sign.
|
||||
* The "checkbox" parser (contained in the `parser-input-select.js` file) will now toggle a class name of `checked-#` (`#` is the column index) on the row.
|
||||
* A new `parsed` parameter has been added to the parser code block.
|
||||
* This parameter is set with a boolean value (i.e. `true` or `false`), to signal the filter widget to only search through parsed data when `true`.
|
||||
* All parsers within the "parser-input-select.js" file now include a `parsed:true` parameter.
|
||||
* The [parsers](http://mottie.github.io/tablesorter/docs/example-parsers.html) and [parsers-advanced](http://mottie.github.io/tablesorter/docs/example-parsers-advanced.html) demos have been updated to reflect this addition.
|
||||
|
||||
* css Sticky headers widget:
|
||||
* Add `cssStickyHeaders_zIndex` option. Fixes [issue #466](https://github.com/Mottie/tablesorter/issues/466).
|
||||
* Browser will now scroll to table top after filtering. Fixes [issue #482](https://github.com/Mottie/tablesorter/issues/482).
|
||||
|
||||
* Column selector widget (new!)
|
||||
* This widget can make a table responsive. It uses similar parameters as those used by jQuery mobile to set priorities for hiding columns (uses "data-priority" attribute).
|
||||
* The column priorities range from 1 to 6, with 1 having the highest priority. As the browser window shrinks, lower priority (higher numbers) columns will be hidden first until all numbered priority columns are hidden.
|
||||
* Any named data-priority, other than the numbers 1 - 6, (e.g. "critical" or "persistent") will be treated as a column which *will not be included* in the column selector.
|
||||
* With the addition of some basic selector markup and css, this widget will also allow selecting (hiding or showing) table columns.
|
||||
* Popups can also be targetted for addition of these selectors; [the demo](http://mottie.github.io/tablesorter/docs/example-widget-column-selector.html) includes a Bootstrap popover sample.
|
||||
* Css selectors are used to hide/show columns for optimal speed and therefore will not work in IE8 and older browsers.
|
||||
* jQuery version 1.7+ and tablesorter verison 2.8+ are needed for this widget to work properly.
|
||||
* Check out the [demo](http://mottie.github.io/tablesorter/docs/example-widget-column-selector.html) with more details on how to setup this widget!
|
||||
|
||||
* Editable widget
|
||||
* Refresh other widgets after a cell has been edited. Fixes [issue #487](https://github.com/Mottie/tablesorter/issues/487).
|
||||
|
||||
* Filter widget:
|
||||
* Make operator match higher priority than exact matching. Fixes [issue #465](https://github.com/Mottie/tablesorter/issues/465).
|
||||
* Fix " OR " is now matched case insensitive.
|
||||
* The `filter_cssFilter` option can now contain an array of class names to be applied to each filter input; added in addition to the "tablesorter-filter" class name.
|
||||
* Start filter values are now preserved. Fixes [issue #452](https://github.com/Mottie/tablesorter/issues/452).
|
||||
* Filter formatter demo: Update jQuery UI & stylesheet - fixes UI spinner.
|
||||
* Fix child rows always visible when filtering.
|
||||
* Update beta demo - [select2 external table filters demo](http://mottie.github.io/tablesorter/beta-testing/example-external-filters-using-select2.html), thanks to [mohitmayank](https://github.com/mohitmayank); see [pull request #469](https://github.com/Mottie/tablesorter/pull/469).
|
||||
* Add `filter_hideEmpty` option
|
||||
* Set this option to false to always show the filter row.
|
||||
* By default, the filter row is completely hidden when no rows exist within the tbody (previous behavior)
|
||||
* Fixes [issue #450](https://github.com/Mottie/tablesorter/issues/450)
|
||||
* Rewrite filter match any column code
|
||||
* Removed `filter_anyMatch` option - sorry about not deprecating this first!
|
||||
* Added a `filter_external` option which is set to a jQuery selector string of inputs, outside of the table, to be used for searching table content.
|
||||
* External inputs must have a `data-column="x"` attribute where `"x"` is the associated column to filter; `"x"` can also be set as `"any"` to match any column.
|
||||
* All filters, internal and external, now automatically update and be used with the `$.tablesorter.getFilters` and `$.tablesorter.setFilters` functions.
|
||||
* Please refer to the documentation for the [`filter_external` option](http://mottie.github.io/tablesorter/docs/index.html#widget-filter-external) for more details.
|
||||
* Also check out the updated [filter widget external option](http://mottie.github.io/tablesorter/docs/example-widget-filter-any-match.html) and [filter widget external inputs](http://mottie.github.io/tablesorter/docs/example-widget-filter-external-inputs.html) demos.
|
||||
* This fixes issues [#114](https://github.com/Mottie/tablesorter/issues/114), [#370](https://github.com/Mottie/tablesorter/issues/370), [#471](https://github.com/Mottie/tablesorter/issues/471) and [#490](https://github.com/Mottie/tablesorter/issues/490).
|
||||
* Parsers with a `parsed: true` flag will now automatically force the filter widget to only search through parsed data instead of actual table cell data
|
||||
* This is needed specifically for parsers of input, textarea and select elements.
|
||||
* All parsers within the "parser-input-select.js" file have been updated with this parameter.
|
||||
* This flag is essentially does the same thing as adding a class name of `filter-parsed` to the column header, or `filter: "parsed"` setting to the [`headers` option](http://mottie.github.io/tablesorter/docs/#headers).
|
||||
|
||||
* Filter Formatter (Filter widget extension):
|
||||
* These updated filter widget functions are not completely backward compatible with older versions of the filter widget. Please update both!
|
||||
* Added `compare` & `selected` options:
|
||||
* These options allow the adding of a comparison operator selector to the cell (e.g. `>`, `>=`, `<`, `<=`, etc).
|
||||
* If any `cellText` is included, it is now wrapped in a label with a class name of "compare-select-label" and "compare-select-label#" (where "#" is the column index).
|
||||
* The selector has a class name of "compare-select" and "compare-select#" (where "#" is the column index)
|
||||
* Whichever type of input that is added to the cell is then wrapped in a div with class "compare-select-wrapper" and "compare-select-wrapper#" (where "#" is the column index).
|
||||
* These class names allow styling of an individual filter to keep elements in line, or however you wish to style it.
|
||||
* Filter reset now sets these filters to their default values, not an empty string.
|
||||
* Updated to now properly restore saved filters.
|
||||
* Added `endOfDay` option for jQuery UI Datepicker.
|
||||
* When `true` search dates will include all times from the date chosen when a comparison is made of dates "less than" the set date.
|
||||
* Example 1: if a table entry has a date of "Jan 14, 2014 11:23 AM" and the filter search is set to `<= 1/14/2014`, the table entry will be included in the search; the default set time would otherwise be "1/14/2014 00:00:00" and not include the entry from "11:23 AM". So, the `endOfDay` option sets the time to "23:59:59".
|
||||
* Example 2: if searching for one specific date, this option will now search for all times within that day. For example, searching for `=1/20/2014`, and the results will include dates from 1/20/2014 00:00:00 to 1/20/2014 23:59:59.
|
||||
* When comparing dates greater than the set date, the time will be set to midnight; so this option will not be applied.
|
||||
* Example 3: in two date inputs, the `endOfDay` time is only applied to the "to" input; search for `1/20/2014 - 1/20/2014`
|
||||
* This option is available in both the comparison (one input) and range (two inputs; "to" date input only) date pickers.
|
||||
* Fixes [issue #325](https://github.com/Mottie/tablesorter/issues/325) and [issue #430](https://github.com/Mottie/tablesorter/issues/430).
|
||||
|
||||
* Group widget:
|
||||
* Attempt to fix ajax issue. See [issue #437](https://github.com/Mottie/tablesorter/issues/437).
|
||||
* Combining group widget with pager should now work properly. Fixes [isse #437](https://github.com/Mottie/tablesorter/issues/437).
|
||||
* The widget will now find the correct header cell when multiple thead rows are present.
|
||||
|
||||
* Pager (plugin & widget):
|
||||
* Fixed pager issues with empty tables
|
||||
* When existing rows are removed from the table, the pager display will no properly update to show zero total rows.
|
||||
* When starting from an empty table and content is added, all widgets are refreshed
|
||||
* When updating the table via an update method, the filter search will now be applied properly.
|
||||
* Fixes issues [#426](https://github.com/Mottie/tablesorter/issues/426) & [#455](https://github.com/Mottie/tablesorter/issues/455)
|
||||
* Correct page calculation. Fixes [issue #468](https://github.com/Mottie/tablesorter/issues/468).
|
||||
* Added custom storage keys. Thanks to [eire1130](https://github.com/eire1130); see [pull request #480](https://github.com/Mottie/tablesorter/pull/480) & [issue #481](https://github.com/Mottie/tablesorter/issues/481).
|
||||
* Added a public show error function `$.tablesorter.showError( table, message );`
|
||||
* Pass this function the table DOM element or jQuery object in `table`
|
||||
* The message can either be a string with a message ("table refuses to cooperate")
|
||||
* or, the message can be an HTML string of an entire table row (`'<tr><td colspan="' + table.config.columns + '">yeah, instead of showing your data... I am taking a nap</td></tr>'`)
|
||||
* If the message is blank, all error rows are removed
|
||||
* Fulfills [issue #486](https://github.com/Mottie/tablesorter/issues/486)
|
||||
* Please note that this function was added to both the pager widget & pager plugin; In the next major release, this function will be separate from both, and can be included in the build.
|
||||
* All theme files included a minor update with this change.
|
||||
* Added accessibility attributes to the pager.
|
||||
* Fix jsHint warnings.
|
||||
|
||||
* Resizable widget
|
||||
* Fix reported js error.
|
||||
* The resizable reset function `$.tablesorter.resizableReset(table);` now accepts jQuery objects.
|
||||
|
||||
* Sticky headers widget
|
||||
* Select boxes work again within sticky headers. Fixes [issue #473](https://github.com/Mottie/tablesorter/issues/473).
|
||||
* Browser will scroll to table top after filtering.
|
||||
* This only occurs if the sticky header is active and after a filter is applied.
|
||||
* Fixes [issue #482](https://github.com/Mottie/tablesorter/issues/482).
|
||||
* Use core's new `bindEvents` public function to bind events to cloned sticky header.
|
||||
* Fix sticky header alignment within `attachTo` elements.
|
||||
|
||||
* Miscellaneous
|
||||
* Update all Bootstrap demos to use the latest version (v3.0.3). Thanks [themilkman](https://github.com/themilkman)!
|
||||
* Update all demo pages that use jQuery UI accordion with the newest version. Also added a clickable anchor to each accordion header.
|
||||
* Consolidate default class names within `$.tablesorter.css` for the filter, resizer and stickyHeaders widgets.
|
||||
* Renamed component.json to bower.json
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* tablesorter pager plugin
|
||||
* updated 2/22/2014 (v2.15.4)
|
||||
* updated 3/7/2014 (v2.15.6)
|
||||
*/
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
;(function($) {
|
||||
|
4
addons/pager/jquery.tablesorter.pager.min.js
vendored
4
addons/pager/jquery.tablesorter.pager.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tablesorter",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"dependencies": {
|
||||
"jquery": ">=1.2.6"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**!
|
||||
* TableSorter 2.15.5 - Client-side table sorting with ease!
|
||||
* TableSorter 2.15.6 - Client-side table sorting with ease!
|
||||
* @requires jQuery v1.2.6+
|
||||
*
|
||||
* Copyright (c) 2007 Christian Bach
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
var ts = this;
|
||||
|
||||
ts.version = "2.15.5";
|
||||
ts.version = "2.15.6";
|
||||
|
||||
ts.parsers = [];
|
||||
ts.widgets = [];
|
||||
@ -756,8 +756,7 @@
|
||||
}
|
||||
|
||||
function resortComplete($table, callback){
|
||||
var table = $table[0],
|
||||
c = table.config;
|
||||
var table = $table[0];
|
||||
if (table.isUpdating) {
|
||||
$table.trigger('updateComplete');
|
||||
}
|
||||
|
4
js/jquery.tablesorter.min.js
vendored
4
js/jquery.tablesorter.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
/*! tableSorter 2.8+ widgets - updated 2/21/2014 (v2.15.3)
|
||||
/*! tableSorter 2.8+ widgets - updated 3/7/2014 (v2.15.6)
|
||||
*
|
||||
* Column Styles
|
||||
* Column Filters
|
||||
|
24
js/jquery.tablesorter.widgets.min.js
vendored
24
js/jquery.tablesorter.widgets.min.js
vendored
File diff suppressed because one or more lines are too long
@ -22,7 +22,7 @@
|
||||
// replace separators
|
||||
.replace(/\s+/g," ").replace(/[-.,]/g, "/")
|
||||
// reformat xx/xx/xx to mm/dd/19yy;
|
||||
.replace(regex, format);
|
||||
.replace(regex, format),
|
||||
d = new Date(n),
|
||||
y = d.getFullYear(),
|
||||
rng = table && table.config.dateRange || range,
|
||||
|
@ -138,8 +138,8 @@ tsColSel = ts.columnSelector = {
|
||||
c.selector.$popup.find('.tablesorter-column-selector')
|
||||
.html( colSel.$container.html() )
|
||||
.find('input').each(function(){
|
||||
var indx = $(this).attr('data-column')
|
||||
$(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] )
|
||||
var indx = $(this).attr('data-column');
|
||||
$(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] );
|
||||
});
|
||||
}
|
||||
}).change();
|
||||
@ -213,8 +213,8 @@ tsColSel = ts.columnSelector = {
|
||||
},
|
||||
|
||||
attachTo : function(table, elm) {
|
||||
table = $(table)[0];
|
||||
var colSel, wo, indx,
|
||||
table = $(table)[0],
|
||||
c = table.config,
|
||||
$popup = $(elm);
|
||||
if ($popup.length && c) {
|
||||
@ -228,7 +228,7 @@ tsColSel = ts.columnSelector = {
|
||||
.html( colSel.$container.html() )
|
||||
.find('input').each(function(){
|
||||
var indx = $(this).attr('data-column');
|
||||
$(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] )
|
||||
$(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] );
|
||||
});
|
||||
colSel.$popup = $popup.on('change', 'input', function(){
|
||||
// data input
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*! tablesorter Grouping widget - updated 12/18/2013 (core v2.15.0)
|
||||
/*! tablesorter Grouping widget - updated 3/7/2014 (core v2.15.6)
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
@ -128,7 +128,7 @@ ts.grouping = {
|
||||
.each(function(){
|
||||
var isHidden, $label,
|
||||
$row = $(this),
|
||||
name = $row.text().toLowerCase(),
|
||||
name = $row.find('.group-name').text().toLowerCase(),
|
||||
$rows = $row.nextUntil('tr.group-header').filter(':visible');
|
||||
if (wo.group_count || $.isFunction(wo.group_callback)) {
|
||||
$label = $row.find('.group-count');
|
||||
@ -142,7 +142,7 @@ ts.grouping = {
|
||||
}
|
||||
}
|
||||
if (wo.group_saveGroups && wo.group_currentGroups[wo.group_currentGroup].length) {
|
||||
isHidden = $.inArray( $row.find('.group-name').text(), wo.group_currentGroups[wo.group_currentGroup] ) > -1;
|
||||
isHidden = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] ) > -1;
|
||||
$row.toggleClass('collapsed', isHidden);
|
||||
$rows.toggleClass('group-hidden', isHidden);
|
||||
} else if (wo.group_collapsed && wo.group_collapsible) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Pager widget (beta) for TableSorter 2/23/2014 (v2.15.5) */
|
||||
/* Pager widget (beta) for TableSorter 3/7/2014 (v2.15.6) */
|
||||
/*jshint browser:true, jquery:true, unused:false */
|
||||
;(function($){
|
||||
"use strict";
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "tablesorter",
|
||||
"title": "tablesorter",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"description": "tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.\n\nThis forked version adds lots of new enhancements including: alphanumeric sorting, pager callback functons, multiple widgets providing column styling, ui theme application, sticky headers, column filters and resizer, as well as extended documentation with a lot more demos.",
|
||||
"author": {
|
||||
"name": "Christian Bach",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "tablesorter",
|
||||
"title": "tablesorter",
|
||||
"version": "2.15.5",
|
||||
"version": "2.15.6",
|
||||
"description": "tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.\n\nThis forked version adds lots of new enhancements including: alphanumeric sorting, pager callback functons, multiple widgets providing column styling, ui theme application, sticky headers, column filters and resizer, as well as extended documentation with a lot more demos.",
|
||||
"author": {
|
||||
"name": "Christian Bach",
|
||||
|
524
test.html
524
test.html
@ -15,530 +15,6 @@
|
||||
<script src="testing/testing.js"></script>
|
||||
<script src="testing/testing-ipv6.js"></script>
|
||||
|
||||
<script>
|
||||
/*
|
||||
Core plugin tested
|
||||
========================
|
||||
OPTIONS:
|
||||
cssAsc, cssChildRow, cssDesc, cssHeader, cssHeaderRow, cssInfoBlock, dateFormat, emptyTo, headerList,
|
||||
headers, ignoreCase, initialized, parsers, sortList, sortLocaleCompare, sortReset, stringTo, tableClass,
|
||||
usNumberFormat, widgets (just zebra), sortAppend, sortForce, sortMultiSortKey, sortResetKey
|
||||
|
||||
METHODS:
|
||||
addRows, applyWidgets, destroy, sorton, sortReset, update/updateRow, updateAll, updateCell
|
||||
|
||||
EVENTS:
|
||||
initialized, sortBegin, sortEnd, sortStart, updateComplete
|
||||
|
||||
Not yet tested
|
||||
=========================
|
||||
OPTIONS:
|
||||
cancelSelection, cssIcon, cssProcessing, debug, delayInit, headerTemplate, initWidgets, onRenderHeader,
|
||||
onRenderTemplate, selectorHeaders, selectorRemove, selectorSort, serverSideSorting, showProcessing,
|
||||
sortInitialOrder, sortRestart, strings,
|
||||
textExtraction, textSorter, theme, widthFixed, widgets (also need priority testing)
|
||||
|
||||
METHODS:
|
||||
appendCache, applyWidgetId, sort, refreshWidgets
|
||||
|
||||
EVENTS:
|
||||
-
|
||||
*/
|
||||
|
||||
$(function(){
|
||||
// keep stuff in order; yeah I know every test needs to be atomic - bleh
|
||||
QUnit.config.reorder = false;
|
||||
|
||||
var ts = $.tablesorter,
|
||||
$table1 = $('.tester:eq(0)'),
|
||||
$table2 = $('.tester:eq(1)'),
|
||||
$table3 = $('.tester:eq(2)'),
|
||||
$table4 = $('.tester:eq(3)'),
|
||||
$table5 = $('.tester:eq(4)'), // empty table
|
||||
table1 = $table1[0],
|
||||
table2 = $table2[0],
|
||||
table3 = $table3[0],
|
||||
table4 = $table4[0],
|
||||
th0 = $table1.find('th')[0], // first table header cell
|
||||
init = false,
|
||||
sortIndx = 0,
|
||||
updateIndx = 0,
|
||||
updateCallback = 0,
|
||||
events = ['sortStart', 'sortBegin', 'sortEnd' ],
|
||||
returnTime = function(string){
|
||||
return new Date(string).getTime();
|
||||
},
|
||||
undef, c1, c2, c3, c4, e, i, l, t;
|
||||
|
||||
$table1
|
||||
.bind('tablesorter-initialized', function(){
|
||||
init = true;
|
||||
})
|
||||
.bind( events.join(' '), function(e){
|
||||
if (e.type === events[sortIndx%3]) {
|
||||
sortIndx++;
|
||||
}
|
||||
})
|
||||
.bind('updateComplete', function(){
|
||||
updateIndx++;
|
||||
})
|
||||
.tablesorter();
|
||||
|
||||
$table2.tablesorter({
|
||||
headers: {
|
||||
0: { sorter: 'text' },
|
||||
1: { sorter: 'text' },
|
||||
2: { sorter: false }
|
||||
}
|
||||
});
|
||||
|
||||
$table3.tablesorter({
|
||||
emptyTo: "bottom",
|
||||
stringTo: "max", // non-numeric content is treated as a MAX value
|
||||
headers: {
|
||||
0: { empty : "top" }, // sort empty cells to the top
|
||||
2: { string: "min" }, // non-numeric content is treated as a MIN value
|
||||
3: { sorter: "digit", empty : "zero", string : "top" }
|
||||
}
|
||||
});
|
||||
|
||||
$table4.tablesorter({
|
||||
sortAppend : [[2,0],[3,0]],
|
||||
sortForce : [[0,0],[1,0]],
|
||||
initialized: function(table){
|
||||
var e, c = table.config;
|
||||
// trigger sort on 5th column
|
||||
// this method is used because triggering a "sorton" would ignore sortForce/sortAppend
|
||||
c.$headers.eq(4).trigger('sort');
|
||||
e = $.Event('sort');
|
||||
e.which = 1;
|
||||
e.shiftKey = true;
|
||||
c.$headers.eq(5).trigger(e);
|
||||
}
|
||||
});
|
||||
|
||||
$table5
|
||||
.bind( events.join(' '), function(e){
|
||||
if (e.type === events[sortIndx%3]) {
|
||||
sortIndx++;
|
||||
}
|
||||
})
|
||||
.bind('updateComplete', function(){
|
||||
updateIndx++;
|
||||
})
|
||||
.tablesorter();
|
||||
|
||||
// ensure all sort events fire on an empty table
|
||||
$table5.trigger('sorton', [ [[0,0]] ]);
|
||||
|
||||
/************************************************
|
||||
JSHint testing
|
||||
************************************************/
|
||||
// Run JSHint on main js files
|
||||
tester.jsHintTest('JSHint core', 'js/jquery.tablesorter.js');
|
||||
tester.jsHintTest('JSHint pager', 'addons/pager/jquery.tablesorter.pager.js');
|
||||
tester.jsHintTest('JSHint widgets', 'js/jquery.tablesorter.widgets.js');
|
||||
tester.jsHintTest('JSHint group widget', 'js/widgets/widget-grouping.js');
|
||||
tester.jsHintTest('JSHint scroller widget', 'js/widgets/widget-scroller.js');
|
||||
|
||||
/************************************************
|
||||
Initialization
|
||||
************************************************/
|
||||
test( "tablesorter loaded & initialized", function() {
|
||||
expect(3);
|
||||
equal( typeof ts, 'object', "tablesorter loaded");
|
||||
equal( table1.hasInitialized, true, "tablesorter initialized flag");
|
||||
equal( init, true, "tablesorter initialized event");
|
||||
});
|
||||
|
||||
c1 = table1.config;
|
||||
c2 = table2.config;
|
||||
c3 = table3.config;
|
||||
c4 = table4.config;
|
||||
|
||||
/************************************************
|
||||
check isDigit function
|
||||
************************************************/
|
||||
var d = ts.isDigit;
|
||||
test( "isDigit", function() {
|
||||
expect(17);
|
||||
ok( d('-1'), "allow negative (-1)");
|
||||
ok( d('+1'), "allow plus (+1)");
|
||||
ok( d('(1)'), "allow parenthesis (1)");
|
||||
ok( d('123'), "string has numbers ('123')");
|
||||
ok( d(123), "has numbers (123)");
|
||||
ok( d('1.2'), "remove decimal (1.2)");
|
||||
ok( d('1,234'),"remove commas (1,234)");
|
||||
ok( d("11'"), "remove apostrophe's (11')"); // 11 feet
|
||||
ok( d('3\'4"'),"remove quotes (3'4\")"); // 3 foot 4 inches
|
||||
ok( d(' 12 '), "remove spaces ( 12 )");
|
||||
ok( !d('x'), "non-digit alphabet");
|
||||
ok( !d('1x'), "digit + alphabet");
|
||||
ok( !d('x1'), "alphabet + digit");
|
||||
ok( !d('@'), "non-digit symbols");
|
||||
ok( !d('1-'), "negative after (1-) not allowed?");
|
||||
ok( !d('1+'), "plus after (1+) not allowed?");
|
||||
ok( !d('$2'), "no money; the currency parser will catch these");
|
||||
});
|
||||
|
||||
/************************************************
|
||||
check formatFloat function
|
||||
************************************************/
|
||||
var ff = function(str) {
|
||||
return ts.formatFloat(str, table1);
|
||||
};
|
||||
test( "formatFloat", function() {
|
||||
expect(18);
|
||||
strictEqual( ff(''), '', 'returns empty string' );
|
||||
strictEqual( ff(5), 5, 'returns numerical values');
|
||||
|
||||
c1.usNumberFormat = false;
|
||||
strictEqual( ts.formatFloat('1,234,567.89'), 1234567.89, 'use format float without including table - defaults to US number format');
|
||||
|
||||
strictEqual( ff('1 234,56'), 1234.56, 'parse non-U.S. (French) number format');
|
||||
strictEqual( ff('1.234,56'), 1234.56, 'parse non-U.S. (German) number format');
|
||||
strictEqual( ff('-32,32'), -32.32, 'negative non-U.S. signed numbers');
|
||||
strictEqual( ff('-1.234,56'), -1234.56, 'negative non-U.S. signed numbers');
|
||||
strictEqual( ff('(32,32)'), -32.32, 'parenthesis wrapped non-U.S. negative number');
|
||||
strictEqual( ff(' (32,32) '), -32.32, 'space + parenthesis wrapped non-U.S. negative number');
|
||||
|
||||
c1.usNumberFormat = true;
|
||||
strictEqual( ff('1,234.56'), 1234.56, 'parse U.S. number format');
|
||||
strictEqual( ff('-32.32'), -32.32, 'negative U.S. signed numbers');
|
||||
strictEqual( ff('(32.32)'), -32.32, 'parenthesis wrapped U.S. negative number');
|
||||
strictEqual( ff(' (32.32)'), -32.32, 'space + parenthesis wrapped U.S. negative number');
|
||||
|
||||
strictEqual( ff('fred'), 'fred', 'return string if not a number');
|
||||
strictEqual( ff(' fred '), 'fred', 'return trimmed string if not a number');
|
||||
strictEqual( ff('fred 12'), 'fred 12', 'return string if number not at beginning');
|
||||
strictEqual( ff('12fred'), 12, 'parse number + string into number only');
|
||||
strictEqual( ff('(fred)'), '(fred)', 'leave parenthesis intact on strings');
|
||||
|
||||
});
|
||||
|
||||
/************************************************
|
||||
get data function - jQuery data > meta > headers option > header class name
|
||||
************************************************/
|
||||
var gd = function(n){
|
||||
return ts.getData( c2.$headers[n], c2.headers[n], 'sorter' );
|
||||
};
|
||||
|
||||
test( "getData", function() {
|
||||
expect(4);
|
||||
var txt = [ 'jQuery data', 'meta data', 'headers option', 'header class name' ];
|
||||
for (i = 0; i < 4; i++) {
|
||||
equal( gd(i), 'false', txt[i]); // all columns have sorter false set
|
||||
}
|
||||
});
|
||||
|
||||
/************************************************
|
||||
character equivalent replacement
|
||||
************************************************/
|
||||
test( "replace accents", function() {
|
||||
expect(6);
|
||||
strictEqual( ts.replaceAccents('\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5'), 'aaaaaaaAAAAAAA', "replaced a's");
|
||||
strictEqual( ts.replaceAccents('\u00e9\u00e8\u00ea\u00eb\u011b\u0119\u00c9\u00c8\u00ca\u00cb\u011a\u0118'), 'eeeeeeEEEEEE', "replaced e's");
|
||||
strictEqual( ts.replaceAccents('\u00ed\u00ec\u0130\u00ee\u00ef\u0131\u00cd\u00cc\u0130\u00ce\u00cf'), 'iiiiiiIIiII', "replaced i's");
|
||||
strictEqual( ts.replaceAccents('\u00f3\u00f2\u00f4\u00f5\u00f6\u00d3\u00d2\u00d4\u00d5\u00d6'), 'oooooOOOOO', "replaced o's");
|
||||
strictEqual( ts.replaceAccents('\u00fa\u00f9\u00fb\u00fc\u016f\u00da\u00d9\u00db\u00dc\u016e'), 'uuuuuUUUUU', "replaced u's");
|
||||
strictEqual( ts.replaceAccents('\u00e7\u0107\u010d\u00c7\u0106\u010c\u00df\u1e9e'), 'cccCCCssSS', "replaced c & s sharp");
|
||||
});
|
||||
|
||||
/************************************************
|
||||
check all default parsers
|
||||
************************************************/
|
||||
var p = ts.parsers,
|
||||
// test by parser
|
||||
parserTests = 85,
|
||||
// skipping metadata parser
|
||||
sample1 = {
|
||||
'text' : { 'test': 'test', 'TesT': 'test', '\u00e1 test': '\u00e1 test' },
|
||||
'currency' : { '\u00a31': 1, '($2.23)': -2.23, '5\u20ac': 5, '(11\u00a4)': -11, '500\u00a5': 500, '25\u00a2': 25, '$1,000.50': 1000.5 },
|
||||
'ipAddress' : { '255.255.255.255': 255255255255, '32.32.32.32': 32032032032, '1.1.1.1': 1001001001 },
|
||||
'url' : { 'http://google.com': 'google.com', 'ftp://fred.com': 'fred.com', 'https://github.com': 'github.com' },
|
||||
'isoDate' : { '2012/12/12': returnTime('2012/12/12'), '2012-12/12': returnTime('2012/12/12'), '2013-1-1': returnTime('2013/1/1'), '2013/1/1 12:34:56 AM': returnTime('2013/1/1 12:34:56 AM') },
|
||||
'percent' : { '100%': 100, '22%': 22, '%2': 2, '2 %': 2, '(4%)': -4, '1,234.56 %': 1234.56 },
|
||||
'usLongDate': { 'Feb 23, 1999': returnTime('Feb 23, 1999'), 'Feb 23, 1999 12:34': returnTime('Feb 23, 1999 12:34'), 'Feb 23, 1999 12:34 AM': returnTime('Feb 23, 1999 12:34 AM'), 'Feb 23, 1999 12:34:56 PM': returnTime('Feb 23, 1999 12:34:56 PM'), '01 Jan 2013': returnTime('01 Jan 2013') },
|
||||
'shortDate' : { '1/2/2001': returnTime('1/2/2001'), '1 2 2001': returnTime('1/2/2001'), '1.2.2001': returnTime('1/2/2001'), '1-2-2001': returnTime('1/2/2001'), '1/2/2001 12:34 PM' : returnTime('1/2/2001 12:34 PM'), '1.2.2001 13:34' : returnTime('1/2/2001 13:34') },
|
||||
'time' : { '12:34 AM': returnTime('2000/01/01 12:34 AM'), '1:00 pm': returnTime('2000/01/01 1:00 pm') },
|
||||
'digit' : { '12': 12, '$23': 23, '&44^': 44, '#(33)': -33, '1,000': 1000, '12.34': 12.34 }
|
||||
},
|
||||
// switch ignoreCase, sortLocalCompare & shortDate "ddmmyyyy"
|
||||
sample2 = {
|
||||
'text' : { 'TesT': 'TesT', '\u00e1 test': 'a test' },
|
||||
'currency' : { '\u20ac 123 456,78': 123456.78, '\u20ac 123.456,78': 123456.78 },
|
||||
'shortDate' : { '2/1/2001': returnTime('1/2/2001'), '2-1-2001': returnTime('1/2/2001'), '2 1,2001': returnTime('1/2/2001') }
|
||||
},
|
||||
// shortdate to "yyyymmdd"
|
||||
sample3 = {
|
||||
'shortDate' : { '2001/1/2': returnTime('1/2/2001'), '2001-1/2': returnTime('1/2/2001'), '2001,1.2': returnTime('1/2/2001') }
|
||||
},
|
||||
report = function(s) {
|
||||
for (i = 0; i < p.length; i++) {
|
||||
t = p[i].id;
|
||||
if (s.hasOwnProperty(t)) {
|
||||
$.each(s[t], function(k,v){
|
||||
// check "is" and "format" functions
|
||||
if (p[i].is(k)) {
|
||||
equal( p[i].format(k, table1, th0, 0), v, t + ' parser: "' + k + '" parsed to ' + v );
|
||||
} else {
|
||||
equal( p[i].format(k, table1, th0, 0), v, t + ' parser **NOT DETECTED**: "' + k + '", but returns ' + v );
|
||||
}
|
||||
});
|
||||
// test for undefined & null - probably overkill
|
||||
strictEqual( p[i].format(undef, table1, th0, 0), undef, t + ' parser: will return undefined values properly' );
|
||||
strictEqual( p[i].format(null, table1, th0, 0), null, t + ' parser: will return null values properly' );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test( "testing parsers", function() {
|
||||
expect(parserTests);
|
||||
report(sample1);
|
||||
|
||||
c1.sortLocaleCompare = true;
|
||||
c1.ignoreCase = false;
|
||||
c1.usNumberFormat = false;
|
||||
th0.dateFormat = c1.dateFormat = "ddmmyyyy";
|
||||
report(sample2);
|
||||
|
||||
c1.usNumberFormat = true;
|
||||
th0.dateFormat = c1.dateFormat = "yyyymmdd";
|
||||
report(sample3);
|
||||
|
||||
// undocumented sortValue
|
||||
equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'zzz', 'metadata parser found sortValue');
|
||||
c1.parserMetadataName = 'poe';
|
||||
equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'nevermore', 'metadata parser found poe');
|
||||
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test parser cache
|
||||
************************************************/
|
||||
test( "parser cache; sorton methods; empty & string", function() {
|
||||
expect(17);
|
||||
$table1.trigger('sortReset');
|
||||
// lower case because table was parsed before c1.ignoreCase was changed
|
||||
tester.cacheCompare( table1, 'all', [ 'test2', 'x2', 'test1', 'x3', 'test3', 'x1', '', '', 'testb', 'x5', 'testc', 'x4', 'testa', 'x6' ], 'unsorted' );
|
||||
|
||||
$table1.trigger('sorton', [[[ 0,0 ]]]);
|
||||
tester.cacheCompare( table1, 'all', [ 'test1', 'x3', 'test2', 'x2', 'test3', 'x1', '', '', 'testa', 'x6', 'testb', 'x5', 'testc', 'x4' ], 'ascending sort' );
|
||||
|
||||
$table1.trigger('sorton', [[[ 0,1 ]]]);
|
||||
tester.cacheCompare( table1, 'all', [ 'test3', 'x1', 'test2', 'x2', 'test1', 'x3', '', '', 'testc', 'x4', 'testb', 'x5', 'testa', 'x6' ], 'descending sort' );
|
||||
|
||||
// empty cell position
|
||||
$table3.trigger('sorton', [[[ 0,0 ]]]);
|
||||
tester.cacheCompare( table3, 0, [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'asc sort; empty to top' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 0,1 ]]]);
|
||||
tester.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'desc sort; empty to top' );
|
||||
|
||||
// string position within number column
|
||||
$table3.trigger('sorton', [[[ 1,0 ]]]);
|
||||
tester.cacheCompare( table3, 1, [ -35, -5, -1, 1, 2, 4, 33, 44, 'nr', '' ], 'asc sort; empty to bottom; string to max' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 1,1 ]]]);
|
||||
tester.cacheCompare( table3, 1, [ 'nr', 44, 33, 4, 2, 1, -1, -5, -35, '' ], 'desc sort; empty to bottom; string to max' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 2,0 ]]]);
|
||||
tester.cacheCompare( table3, 2, [ 'nr', 'nr', 1, 2, 3, 4, 5, 6, 7, '' ], 'asc sort; empty to bottom; string to min' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 2,1 ]]]);
|
||||
tester.cacheCompare( table3, 2, [ 7, 6, 5, 4, 3, 2, 1, 'nr', 'nr', '' ], 'desc sort; empty to bottom; string to min' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,0 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4 ], 'asc sort; empty to zero; string to top' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,1 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4 ], 'desc sort; empty to zero; string to top' );
|
||||
|
||||
$table3.find('th:eq(3)').data('string', 'bottom');
|
||||
$table3.trigger('update');
|
||||
tester.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4, 'n/a #1', 'n/a #2' ], 'desc sort; empty to zero; string to bottom' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,0 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4, 'n/a #1', 'n/a #2' ], 'asc sort; empty to zero; string to bottom' );
|
||||
|
||||
$table3.find('th:eq(3)').data('string', 'none');
|
||||
c3.headers[3].empty = "bottom";
|
||||
c3.sortList = [[ 3, 1 ]]; // added to test sortList
|
||||
$table3.trigger('update');
|
||||
tester.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, 'n/a #1', 'n/a #2', -0.1, -2.2, -8.4, '' ], 'desc sort; empty to zero; string to none/zero' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,0 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, 'n/a #1', 'n/a #2', 5.2, 11.4, 23.6, 97.4, '' ], 'asc sort; empty to zero; string to none/zero' );
|
||||
|
||||
t = [ 'x', 'X', 'y', 'Y', 'z', 'Z', 'a', 'A', 'b', 'B', 'c', 'C' ];
|
||||
deepEqual( t.sort($.tablesorter.sortText), [ 'A', 'B', 'C', 'X', 'Y', 'Z', 'a', 'b', 'c', 'x', 'y', 'z' ], 'test sortText function directly' );
|
||||
|
||||
t = [ 'a02', 'a10', 'a43', 'a255', 'a102', 'a33', '', 'a1', 'a55', 'a87' ];
|
||||
deepEqual( t.sort($.tablesorter.sortNatural), [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'test sortNatural function directly' );
|
||||
|
||||
});
|
||||
|
||||
test( "sort Events", function(){
|
||||
expect(1);
|
||||
// table1 sorted twice in the above test; sortIndx = 9 then empty table5 x1 (total = 3 events x 3)
|
||||
equal( sortIndx, 9, 'sortStart, sortBegin & sortEnd fired in order x3; including empty table' );
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test update methods
|
||||
************************************************/
|
||||
test( "parser cache; update methods & callbacks", function() {
|
||||
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(){
|
||||
updateCallback++;
|
||||
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, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateAll - tbody' );
|
||||
}]);
|
||||
|
||||
// addRows
|
||||
t = $('<tr class="temp"><td>testd</td><td>7</td></tr>');
|
||||
$table1.find('tbody:last').append(t);
|
||||
$table1.trigger('addRows', [t, true, function(){
|
||||
updateCallback++;
|
||||
tester.cacheCompare( table1, 'all', [ '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, function(){
|
||||
updateCallback++;
|
||||
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'texte', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' );
|
||||
}]);
|
||||
|
||||
// update
|
||||
$table1.find('tr.temp').remove();
|
||||
$table1.trigger('update', [true, function(){
|
||||
updateCallback++;
|
||||
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' );
|
||||
}]);
|
||||
|
||||
// update empty table
|
||||
$table5.trigger('update', [false, function(){
|
||||
updateCallback++;
|
||||
}]);
|
||||
|
||||
});
|
||||
|
||||
test( "UpdateComplete Event", function(){
|
||||
expect(1);
|
||||
// table1 updated 4x in the above test
|
||||
// table5 updated 1x
|
||||
equal( updateIndx, updateCallback, 'updatedComplete and update callback functions working properly' );
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test sortForce, sortAppend, sortMultiSortKey and sortResetKey options
|
||||
************************************************/
|
||||
asyncTest( "sortForce, sortAppend, sortMultiSortKey & sortResetKey", function(){
|
||||
expect(3);
|
||||
var count = 0;
|
||||
tester.cacheCompare( table4, 3, [ 2, 1, 7, 6, 5, 3, 4, 8, 9, 10 ], 'force x2 + sorted x2 + append x2, ascending' );
|
||||
$table4.on('sortEnd', function(){
|
||||
count++;
|
||||
if (count === 1) {
|
||||
tester.cacheCompare( table4, 3, [ 2, 1, 6, 7, 5, 4, 3, 8, 10, 9 ], 'force x2 + sorted x2 + append x2, descending' );
|
||||
c4.sortResetKey = 'shiftKey';
|
||||
var e = $.Event('sort');
|
||||
e.which = 1;
|
||||
e.shiftKey = true; // testing sortResetKey
|
||||
c4.$headers.eq(0).trigger(e);
|
||||
} else {
|
||||
tester.cacheCompare( table4, 3, [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], 'sortResetKey' );
|
||||
$table4.off('sortEnd');
|
||||
start();
|
||||
}
|
||||
});
|
||||
var e = $.Event('sort');
|
||||
c4.sortMultiSortKey = 'altKey';
|
||||
e.which = 1;
|
||||
e.altKey = true; // testing sortMultiSortKey
|
||||
c4.$headers.eq(5).trigger(e);
|
||||
});
|
||||
|
||||
/************************************************
|
||||
check header css
|
||||
************************************************/
|
||||
test( "testing header css & sortReset method", function(){
|
||||
expect(7);
|
||||
t = $(th0);
|
||||
equal( $table1.hasClass(ts.css.table), true, 'table class applied');
|
||||
equal( t.hasClass(ts.css.header), true, 'Header class present' );
|
||||
equal( t.parent().hasClass(ts.css.headerRow), true, 'Header row class present' );
|
||||
equal( $table1.find('tbody:eq(1)').hasClass(c1.cssInfoBlock), true, 'Tbody info block class present' );
|
||||
$table1.trigger('sorton', [[[ 0,1 ]]] );
|
||||
equal( t.hasClass(ts.css.sortDesc), true, 'Descending class present' );
|
||||
$table1.trigger('sorton', [[[ 0,0 ]]] );
|
||||
equal( t.hasClass(ts.css.sortAsc), true, 'Ascending class present' );
|
||||
$table1.trigger('sortReset');
|
||||
equal( t.hasClass(ts.css.sortAsc) || t.hasClass(ts.css.sortDesc), false, 'Testing sortReset' );
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test apply widgets function using zebra widget
|
||||
************************************************/
|
||||
var zebra = function(){
|
||||
t = true;
|
||||
$table2.find('tbody tr').each(function(){
|
||||
t = t ? $(this).hasClass('odd') || $(this).hasClass('even') : false;
|
||||
});
|
||||
return t;
|
||||
};
|
||||
|
||||
test( "apply zebra widget", function(){
|
||||
expect(2);
|
||||
equal( zebra(), false, 'zebra not applied' );
|
||||
c2.widgets = [ 'zebra' ];
|
||||
$table2.trigger('applyWidgets');
|
||||
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();
|
||||
});
|
||||
|
||||
/************************************************
|
||||
ipv6 parser testing
|
||||
************************************************/
|
||||
ipv6tests();
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
|
@ -87,3 +87,525 @@ var tester = {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
Core plugin tested
|
||||
========================
|
||||
OPTIONS:
|
||||
cssAsc, cssChildRow, cssDesc, cssHeader, cssHeaderRow, cssInfoBlock, dateFormat, emptyTo, headerList,
|
||||
headers, ignoreCase, initialized, parsers, sortList, sortLocaleCompare, sortReset, stringTo, tableClass,
|
||||
usNumberFormat, widgets (just zebra), sortAppend, sortForce, sortMultiSortKey, sortResetKey
|
||||
|
||||
METHODS:
|
||||
addRows, applyWidgets, destroy, sorton, sortReset, update/updateRow, updateAll, updateCell
|
||||
|
||||
EVENTS:
|
||||
initialized, sortBegin, sortEnd, sortStart, updateComplete
|
||||
|
||||
Not yet tested
|
||||
=========================
|
||||
OPTIONS:
|
||||
cancelSelection, cssIcon, cssProcessing, debug, delayInit, headerTemplate, initWidgets, onRenderHeader,
|
||||
onRenderTemplate, selectorHeaders, selectorRemove, selectorSort, serverSideSorting, showProcessing,
|
||||
sortInitialOrder, sortRestart, strings,
|
||||
textExtraction, textSorter, theme, widthFixed, widgets (also need priority testing)
|
||||
|
||||
METHODS:
|
||||
appendCache, applyWidgetId, sort, refreshWidgets
|
||||
|
||||
EVENTS:
|
||||
-
|
||||
*/
|
||||
|
||||
$(function(){
|
||||
// keep stuff in order; yeah I know every test needs to be atomic - bleh
|
||||
QUnit.config.reorder = false;
|
||||
|
||||
var ts = $.tablesorter,
|
||||
$table1 = $('.tester:eq(0)'),
|
||||
$table2 = $('.tester:eq(1)'),
|
||||
$table3 = $('.tester:eq(2)'),
|
||||
$table4 = $('.tester:eq(3)'),
|
||||
$table5 = $('.tester:eq(4)'), // empty table
|
||||
table1 = $table1[0],
|
||||
table2 = $table2[0],
|
||||
table3 = $table3[0],
|
||||
table4 = $table4[0],
|
||||
th0 = $table1.find('th')[0], // first table header cell
|
||||
init = false,
|
||||
sortIndx = 0,
|
||||
updateIndx = 0,
|
||||
updateCallback = 0,
|
||||
events = ['sortStart', 'sortBegin', 'sortEnd' ],
|
||||
returnTime = function(string){
|
||||
return new Date(string).getTime();
|
||||
},
|
||||
undef, c1, c2, c3, c4, e, i, l, t;
|
||||
|
||||
$table1
|
||||
.bind('tablesorter-initialized', function(){
|
||||
init = true;
|
||||
})
|
||||
.bind( events.join(' '), function(e){
|
||||
if (e.type === events[sortIndx%3]) {
|
||||
sortIndx++;
|
||||
}
|
||||
})
|
||||
.bind('updateComplete', function(){
|
||||
updateIndx++;
|
||||
})
|
||||
.tablesorter();
|
||||
|
||||
$table2.tablesorter({
|
||||
headers: {
|
||||
0: { sorter: 'text' },
|
||||
1: { sorter: 'text' },
|
||||
2: { sorter: false }
|
||||
}
|
||||
});
|
||||
|
||||
$table3.tablesorter({
|
||||
emptyTo: "bottom",
|
||||
stringTo: "max", // non-numeric content is treated as a MAX value
|
||||
headers: {
|
||||
0: { empty : "top" }, // sort empty cells to the top
|
||||
2: { string: "min" }, // non-numeric content is treated as a MIN value
|
||||
3: { sorter: "digit", empty : "zero", string : "top" }
|
||||
}
|
||||
});
|
||||
|
||||
$table4.tablesorter({
|
||||
sortAppend : [[2,0],[3,0]],
|
||||
sortForce : [[0,0],[1,0]],
|
||||
initialized: function(table){
|
||||
var e, c = table.config;
|
||||
// trigger sort on 5th column
|
||||
// this method is used because triggering a "sorton" would ignore sortForce/sortAppend
|
||||
c.$headers.eq(4).trigger('sort');
|
||||
e = $.Event('sort');
|
||||
e.which = 1;
|
||||
e.shiftKey = true;
|
||||
c.$headers.eq(5).trigger(e);
|
||||
}
|
||||
});
|
||||
|
||||
$table5
|
||||
.bind( events.join(' '), function(e){
|
||||
if (e.type === events[sortIndx%3]) {
|
||||
sortIndx++;
|
||||
}
|
||||
})
|
||||
.bind('updateComplete', function(){
|
||||
updateIndx++;
|
||||
})
|
||||
.tablesorter();
|
||||
|
||||
// ensure all sort events fire on an empty table
|
||||
$table5.trigger('sorton', [ [[0,0]] ]);
|
||||
|
||||
/************************************************
|
||||
JSHint testing
|
||||
************************************************/
|
||||
// Run JSHint on main js files
|
||||
tester.jsHintTest('JSHint core', 'js/jquery.tablesorter.js');
|
||||
tester.jsHintTest('JSHint pager', 'addons/pager/jquery.tablesorter.pager.js');
|
||||
tester.jsHintTest('JSHint widgets', 'js/jquery.tablesorter.widgets.js');
|
||||
tester.jsHintTest('JSHint group widget', 'js/widgets/widget-grouping.js');
|
||||
tester.jsHintTest('JSHint scroller widget', 'js/widgets/widget-scroller.js');
|
||||
|
||||
/************************************************
|
||||
Initialization
|
||||
************************************************/
|
||||
test( "tablesorter loaded & initialized", function() {
|
||||
expect(3);
|
||||
equal( typeof ts, 'object', "tablesorter loaded");
|
||||
equal( table1.hasInitialized, true, "tablesorter initialized flag");
|
||||
equal( init, true, "tablesorter initialized event");
|
||||
});
|
||||
|
||||
c1 = table1.config;
|
||||
c2 = table2.config;
|
||||
c3 = table3.config;
|
||||
c4 = table4.config;
|
||||
|
||||
/************************************************
|
||||
check isDigit function
|
||||
************************************************/
|
||||
var d = ts.isDigit;
|
||||
test( "isDigit", function() {
|
||||
expect(17);
|
||||
ok( d('-1'), "allow negative (-1)");
|
||||
ok( d('+1'), "allow plus (+1)");
|
||||
ok( d('(1)'), "allow parenthesis (1)");
|
||||
ok( d('123'), "string has numbers ('123')");
|
||||
ok( d(123), "has numbers (123)");
|
||||
ok( d('1.2'), "remove decimal (1.2)");
|
||||
ok( d('1,234'),"remove commas (1,234)");
|
||||
ok( d("11'"), "remove apostrophe's (11')"); // 11 feet
|
||||
ok( d('3\'4"'),"remove quotes (3'4\")"); // 3 foot 4 inches
|
||||
ok( d(' 12 '), "remove spaces ( 12 )");
|
||||
ok( !d('x'), "non-digit alphabet");
|
||||
ok( !d('1x'), "digit + alphabet");
|
||||
ok( !d('x1'), "alphabet + digit");
|
||||
ok( !d('@'), "non-digit symbols");
|
||||
ok( !d('1-'), "negative after (1-) not allowed?");
|
||||
ok( !d('1+'), "plus after (1+) not allowed?");
|
||||
ok( !d('$2'), "no money; the currency parser will catch these");
|
||||
});
|
||||
|
||||
/************************************************
|
||||
check formatFloat function
|
||||
************************************************/
|
||||
var ff = function(str) {
|
||||
return ts.formatFloat(str, table1);
|
||||
};
|
||||
test( "formatFloat", function() {
|
||||
expect(18);
|
||||
strictEqual( ff(''), '', 'returns empty string' );
|
||||
strictEqual( ff(5), 5, 'returns numerical values');
|
||||
|
||||
c1.usNumberFormat = false;
|
||||
strictEqual( ts.formatFloat('1,234,567.89'), 1234567.89, 'use format float without including table - defaults to US number format');
|
||||
|
||||
strictEqual( ff('1 234,56'), 1234.56, 'parse non-U.S. (French) number format');
|
||||
strictEqual( ff('1.234,56'), 1234.56, 'parse non-U.S. (German) number format');
|
||||
strictEqual( ff('-32,32'), -32.32, 'negative non-U.S. signed numbers');
|
||||
strictEqual( ff('-1.234,56'), -1234.56, 'negative non-U.S. signed numbers');
|
||||
strictEqual( ff('(32,32)'), -32.32, 'parenthesis wrapped non-U.S. negative number');
|
||||
strictEqual( ff(' (32,32) '), -32.32, 'space + parenthesis wrapped non-U.S. negative number');
|
||||
|
||||
c1.usNumberFormat = true;
|
||||
strictEqual( ff('1,234.56'), 1234.56, 'parse U.S. number format');
|
||||
strictEqual( ff('-32.32'), -32.32, 'negative U.S. signed numbers');
|
||||
strictEqual( ff('(32.32)'), -32.32, 'parenthesis wrapped U.S. negative number');
|
||||
strictEqual( ff(' (32.32)'), -32.32, 'space + parenthesis wrapped U.S. negative number');
|
||||
|
||||
strictEqual( ff('fred'), 'fred', 'return string if not a number');
|
||||
strictEqual( ff(' fred '), 'fred', 'return trimmed string if not a number');
|
||||
strictEqual( ff('fred 12'), 'fred 12', 'return string if number not at beginning');
|
||||
strictEqual( ff('12fred'), 12, 'parse number + string into number only');
|
||||
strictEqual( ff('(fred)'), '(fred)', 'leave parenthesis intact on strings');
|
||||
|
||||
});
|
||||
|
||||
/************************************************
|
||||
get data function - jQuery data > meta > headers option > header class name
|
||||
************************************************/
|
||||
var gd = function(n){
|
||||
return ts.getData( c2.$headers[n], c2.headers[n], 'sorter' );
|
||||
};
|
||||
|
||||
test( "getData", function() {
|
||||
expect(4);
|
||||
var txt = [ 'jQuery data', 'meta data', 'headers option', 'header class name' ];
|
||||
for (i = 0; i < 4; i++) {
|
||||
equal( gd(i), 'false', txt[i]); // all columns have sorter false set
|
||||
}
|
||||
});
|
||||
|
||||
/************************************************
|
||||
character equivalent replacement
|
||||
************************************************/
|
||||
test( "replace accents", function() {
|
||||
expect(6);
|
||||
strictEqual( ts.replaceAccents('\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5'), 'aaaaaaaAAAAAAA', "replaced a's");
|
||||
strictEqual( ts.replaceAccents('\u00e9\u00e8\u00ea\u00eb\u011b\u0119\u00c9\u00c8\u00ca\u00cb\u011a\u0118'), 'eeeeeeEEEEEE', "replaced e's");
|
||||
strictEqual( ts.replaceAccents('\u00ed\u00ec\u0130\u00ee\u00ef\u0131\u00cd\u00cc\u0130\u00ce\u00cf'), 'iiiiiiIIiII', "replaced i's");
|
||||
strictEqual( ts.replaceAccents('\u00f3\u00f2\u00f4\u00f5\u00f6\u00d3\u00d2\u00d4\u00d5\u00d6'), 'oooooOOOOO', "replaced o's");
|
||||
strictEqual( ts.replaceAccents('\u00fa\u00f9\u00fb\u00fc\u016f\u00da\u00d9\u00db\u00dc\u016e'), 'uuuuuUUUUU', "replaced u's");
|
||||
strictEqual( ts.replaceAccents('\u00e7\u0107\u010d\u00c7\u0106\u010c\u00df\u1e9e'), 'cccCCCssSS', "replaced c & s sharp");
|
||||
});
|
||||
|
||||
/************************************************
|
||||
check all default parsers
|
||||
************************************************/
|
||||
var p = ts.parsers,
|
||||
// test by parser
|
||||
parserTests = 85,
|
||||
// skipping metadata parser
|
||||
sample1 = {
|
||||
'text' : { 'test': 'test', 'TesT': 'test', '\u00e1 test': '\u00e1 test' },
|
||||
'currency' : { '\u00a31': 1, '($2.23)': -2.23, '5\u20ac': 5, '(11\u00a4)': -11, '500\u00a5': 500, '25\u00a2': 25, '$1,000.50': 1000.5 },
|
||||
'ipAddress' : { '255.255.255.255': 255255255255, '32.32.32.32': 32032032032, '1.1.1.1': 1001001001 },
|
||||
'url' : { 'http://google.com': 'google.com', 'ftp://fred.com': 'fred.com', 'https://github.com': 'github.com' },
|
||||
'isoDate' : { '2012/12/12': returnTime('2012/12/12'), '2012-12/12': returnTime('2012/12/12'), '2013-1-1': returnTime('2013/1/1'), '2013/1/1 12:34:56 AM': returnTime('2013/1/1 12:34:56 AM') },
|
||||
'percent' : { '100%': 100, '22%': 22, '%2': 2, '2 %': 2, '(4%)': -4, '1,234.56 %': 1234.56 },
|
||||
'usLongDate': { 'Feb 23, 1999': returnTime('Feb 23, 1999'), 'Feb 23, 1999 12:34': returnTime('Feb 23, 1999 12:34'), 'Feb 23, 1999 12:34 AM': returnTime('Feb 23, 1999 12:34 AM'), 'Feb 23, 1999 12:34:56 PM': returnTime('Feb 23, 1999 12:34:56 PM'), '01 Jan 2013': returnTime('01 Jan 2013') },
|
||||
'shortDate' : { '1/2/2001': returnTime('1/2/2001'), '1 2 2001': returnTime('1/2/2001'), '1.2.2001': returnTime('1/2/2001'), '1-2-2001': returnTime('1/2/2001'), '1/2/2001 12:34 PM' : returnTime('1/2/2001 12:34 PM'), '1.2.2001 13:34' : returnTime('1/2/2001 13:34') },
|
||||
'time' : { '12:34 AM': returnTime('2000/01/01 12:34 AM'), '1:00 pm': returnTime('2000/01/01 1:00 pm') },
|
||||
'digit' : { '12': 12, '$23': 23, '&44^': 44, '#(33)': -33, '1,000': 1000, '12.34': 12.34 }
|
||||
},
|
||||
// switch ignoreCase, sortLocalCompare & shortDate "ddmmyyyy"
|
||||
sample2 = {
|
||||
'text' : { 'TesT': 'TesT', '\u00e1 test': 'a test' },
|
||||
'currency' : { '\u20ac 123 456,78': 123456.78, '\u20ac 123.456,78': 123456.78 },
|
||||
'shortDate' : { '2/1/2001': returnTime('1/2/2001'), '2-1-2001': returnTime('1/2/2001'), '2 1,2001': returnTime('1/2/2001') }
|
||||
},
|
||||
// shortdate to "yyyymmdd"
|
||||
sample3 = {
|
||||
'shortDate' : { '2001/1/2': returnTime('1/2/2001'), '2001-1/2': returnTime('1/2/2001'), '2001,1.2': returnTime('1/2/2001') }
|
||||
},
|
||||
report = function(s) {
|
||||
for (i = 0; i < p.length; i++) {
|
||||
t = p[i].id;
|
||||
if (s.hasOwnProperty(t)) {
|
||||
$.each(s[t], function(k,v){
|
||||
// check "is" and "format" functions
|
||||
if (p[i].is(k)) {
|
||||
equal( p[i].format(k, table1, th0, 0), v, t + ' parser: "' + k + '" parsed to ' + v );
|
||||
} else {
|
||||
equal( p[i].format(k, table1, th0, 0), v, t + ' parser **NOT DETECTED**: "' + k + '", but returns ' + v );
|
||||
}
|
||||
});
|
||||
// test for undefined & null - probably overkill
|
||||
strictEqual( p[i].format(undef, table1, th0, 0), undef, t + ' parser: will return undefined values properly' );
|
||||
strictEqual( p[i].format(null, table1, th0, 0), null, t + ' parser: will return null values properly' );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test( "testing parsers", function() {
|
||||
expect(parserTests);
|
||||
report(sample1);
|
||||
|
||||
c1.sortLocaleCompare = true;
|
||||
c1.ignoreCase = false;
|
||||
c1.usNumberFormat = false;
|
||||
th0.dateFormat = c1.dateFormat = "ddmmyyyy";
|
||||
report(sample2);
|
||||
|
||||
c1.usNumberFormat = true;
|
||||
th0.dateFormat = c1.dateFormat = "yyyymmdd";
|
||||
report(sample3);
|
||||
|
||||
// undocumented sortValue
|
||||
equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'zzz', 'metadata parser found sortValue');
|
||||
c1.parserMetadataName = 'poe';
|
||||
equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'nevermore', 'metadata parser found poe');
|
||||
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test parser cache
|
||||
************************************************/
|
||||
test( "parser cache; sorton methods; empty & string", function() {
|
||||
expect(17);
|
||||
$table1.trigger('sortReset');
|
||||
// lower case because table was parsed before c1.ignoreCase was changed
|
||||
tester.cacheCompare( table1, 'all', [ 'test2', 'x2', 'test1', 'x3', 'test3', 'x1', '', '', 'testb', 'x5', 'testc', 'x4', 'testa', 'x6' ], 'unsorted' );
|
||||
|
||||
$table1.trigger('sorton', [[[ 0,0 ]]]);
|
||||
tester.cacheCompare( table1, 'all', [ 'test1', 'x3', 'test2', 'x2', 'test3', 'x1', '', '', 'testa', 'x6', 'testb', 'x5', 'testc', 'x4' ], 'ascending sort' );
|
||||
|
||||
$table1.trigger('sorton', [[[ 0,1 ]]]);
|
||||
tester.cacheCompare( table1, 'all', [ 'test3', 'x1', 'test2', 'x2', 'test1', 'x3', '', '', 'testc', 'x4', 'testb', 'x5', 'testa', 'x6' ], 'descending sort' );
|
||||
|
||||
// empty cell position
|
||||
$table3.trigger('sorton', [[[ 0,0 ]]]);
|
||||
tester.cacheCompare( table3, 0, [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'asc sort; empty to top' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 0,1 ]]]);
|
||||
tester.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'desc sort; empty to top' );
|
||||
|
||||
// string position within number column
|
||||
$table3.trigger('sorton', [[[ 1,0 ]]]);
|
||||
tester.cacheCompare( table3, 1, [ -35, -5, -1, 1, 2, 4, 33, 44, 'nr', '' ], 'asc sort; empty to bottom; string to max' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 1,1 ]]]);
|
||||
tester.cacheCompare( table3, 1, [ 'nr', 44, 33, 4, 2, 1, -1, -5, -35, '' ], 'desc sort; empty to bottom; string to max' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 2,0 ]]]);
|
||||
tester.cacheCompare( table3, 2, [ 'nr', 'nr', 1, 2, 3, 4, 5, 6, 7, '' ], 'asc sort; empty to bottom; string to min' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 2,1 ]]]);
|
||||
tester.cacheCompare( table3, 2, [ 7, 6, 5, 4, 3, 2, 1, 'nr', 'nr', '' ], 'desc sort; empty to bottom; string to min' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,0 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4 ], 'asc sort; empty to zero; string to top' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,1 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4 ], 'desc sort; empty to zero; string to top' );
|
||||
|
||||
$table3.find('th:eq(3)').data('string', 'bottom');
|
||||
$table3.trigger('update');
|
||||
tester.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4, 'n/a #1', 'n/a #2' ], 'desc sort; empty to zero; string to bottom' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,0 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4, 'n/a #1', 'n/a #2' ], 'asc sort; empty to zero; string to bottom' );
|
||||
|
||||
$table3.find('th:eq(3)').data('string', 'none');
|
||||
c3.headers[3].empty = "bottom";
|
||||
c3.sortList = [[ 3, 1 ]]; // added to test sortList
|
||||
$table3.trigger('update');
|
||||
tester.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, 'n/a #1', 'n/a #2', -0.1, -2.2, -8.4, '' ], 'desc sort; empty to zero; string to none/zero' );
|
||||
|
||||
$table3.trigger('sorton', [[[ 3,0 ]]]);
|
||||
tester.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, 'n/a #1', 'n/a #2', 5.2, 11.4, 23.6, 97.4, '' ], 'asc sort; empty to zero; string to none/zero' );
|
||||
|
||||
t = [ 'x', 'X', 'y', 'Y', 'z', 'Z', 'a', 'A', 'b', 'B', 'c', 'C' ];
|
||||
deepEqual( t.sort($.tablesorter.sortText), [ 'A', 'B', 'C', 'X', 'Y', 'Z', 'a', 'b', 'c', 'x', 'y', 'z' ], 'test sortText function directly' );
|
||||
|
||||
t = [ 'a02', 'a10', 'a43', 'a255', 'a102', 'a33', '', 'a1', 'a55', 'a87' ];
|
||||
deepEqual( t.sort($.tablesorter.sortNatural), [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'test sortNatural function directly' );
|
||||
|
||||
});
|
||||
|
||||
test( "sort Events", function(){
|
||||
expect(1);
|
||||
// table1 sorted twice in the above test; sortIndx = 9 then empty table5 x1 (total = 3 events x 3)
|
||||
equal( sortIndx, 9, 'sortStart, sortBegin & sortEnd fired in order x3; including empty table' );
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test update methods
|
||||
************************************************/
|
||||
test( "parser cache; update methods & callbacks", function() {
|
||||
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(){
|
||||
updateCallback++;
|
||||
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, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateAll - tbody' );
|
||||
}]);
|
||||
|
||||
// addRows
|
||||
t = $('<tr class="temp"><td>testd</td><td>7</td></tr>');
|
||||
$table1.find('tbody:last').append(t);
|
||||
$table1.trigger('addRows', [t, true, function(){
|
||||
updateCallback++;
|
||||
tester.cacheCompare( table1, 'all', [ '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, function(){
|
||||
updateCallback++;
|
||||
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'texte', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' );
|
||||
}]);
|
||||
|
||||
// update
|
||||
$table1.find('tr.temp').remove();
|
||||
$table1.trigger('update', [true, function(){
|
||||
updateCallback++;
|
||||
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' );
|
||||
}]);
|
||||
|
||||
// update empty table
|
||||
$table5.trigger('update', [false, function(){
|
||||
updateCallback++;
|
||||
}]);
|
||||
|
||||
});
|
||||
|
||||
test( "UpdateComplete Event", function(){
|
||||
expect(1);
|
||||
// table1 updated 4x in the above test
|
||||
// table5 updated 1x
|
||||
equal( updateIndx, updateCallback, 'updatedComplete and update callback functions working properly' );
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test sortForce, sortAppend, sortMultiSortKey and sortResetKey options
|
||||
************************************************/
|
||||
asyncTest( "sortForce, sortAppend, sortMultiSortKey & sortResetKey", function(){
|
||||
expect(3);
|
||||
var count = 0;
|
||||
tester.cacheCompare( table4, 3, [ 2, 1, 7, 6, 5, 3, 4, 8, 9, 10 ], 'force x2 + sorted x2 + append x2, ascending' );
|
||||
$table4.on('sortEnd', function(){
|
||||
count++;
|
||||
if (count === 1) {
|
||||
tester.cacheCompare( table4, 3, [ 2, 1, 6, 7, 5, 4, 3, 8, 10, 9 ], 'force x2 + sorted x2 + append x2, descending' );
|
||||
c4.sortResetKey = 'shiftKey';
|
||||
var e = $.Event('sort');
|
||||
e.which = 1;
|
||||
e.shiftKey = true; // testing sortResetKey
|
||||
c4.$headers.eq(0).trigger(e);
|
||||
} else {
|
||||
tester.cacheCompare( table4, 3, [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], 'sortResetKey' );
|
||||
$table4.off('sortEnd');
|
||||
start();
|
||||
}
|
||||
});
|
||||
var e = $.Event('sort');
|
||||
c4.sortMultiSortKey = 'altKey';
|
||||
e.which = 1;
|
||||
e.altKey = true; // testing sortMultiSortKey
|
||||
c4.$headers.eq(5).trigger(e);
|
||||
});
|
||||
|
||||
/************************************************
|
||||
check header css
|
||||
************************************************/
|
||||
test( "testing header css & sortReset method", function(){
|
||||
expect(7);
|
||||
t = $(th0);
|
||||
equal( $table1.hasClass(ts.css.table), true, 'table class applied');
|
||||
equal( t.hasClass(ts.css.header), true, 'Header class present' );
|
||||
equal( t.parent().hasClass(ts.css.headerRow), true, 'Header row class present' );
|
||||
equal( $table1.find('tbody:eq(1)').hasClass(c1.cssInfoBlock), true, 'Tbody info block class present' );
|
||||
$table1.trigger('sorton', [[[ 0,1 ]]] );
|
||||
equal( t.hasClass(ts.css.sortDesc), true, 'Descending class present' );
|
||||
$table1.trigger('sorton', [[[ 0,0 ]]] );
|
||||
equal( t.hasClass(ts.css.sortAsc), true, 'Ascending class present' );
|
||||
$table1.trigger('sortReset');
|
||||
equal( t.hasClass(ts.css.sortAsc) || t.hasClass(ts.css.sortDesc), false, 'Testing sortReset' );
|
||||
});
|
||||
|
||||
/************************************************
|
||||
test apply widgets function using zebra widget
|
||||
************************************************/
|
||||
var zebra = function(){
|
||||
t = true;
|
||||
$table2.find('tbody tr').each(function(){
|
||||
t = t ? $(this).hasClass('odd') || $(this).hasClass('even') : false;
|
||||
});
|
||||
return t;
|
||||
};
|
||||
|
||||
test( "apply zebra widget", function(){
|
||||
expect(2);
|
||||
equal( zebra(), false, 'zebra not applied' );
|
||||
c2.widgets = [ 'zebra' ];
|
||||
$table2.trigger('applyWidgets');
|
||||
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();
|
||||
});
|
||||
|
||||
/************************************************
|
||||
ipv6 parser testing
|
||||
************************************************/
|
||||
ipv6tests();
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user