diff --git a/docs/index.html b/docs/index.html
index dc5cc9d6..79825119 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -5294,6 +5294,43 @@ $('table').trigger( 'search', [['', '', '', '', 'orange']] ); // find orange in
getParserById |
This function returns the named parser object.
diff --git a/js/jquery.tablesorter.js b/js/jquery.tablesorter.js
index 868b746d..881983be 100644
--- a/js/jquery.tablesorter.js
+++ b/js/jquery.tablesorter.js
@@ -154,6 +154,18 @@
nextNone : 'activate to remove the sort'
};
+ // These methods can be applied on table.config instance
+ ts.instanceMethods = {
+ // Returns a jQuery object of n-th column header
+ $columnHeader: function(n, options) {
+ var $headers, lastOnly;
+ options = options || {},
+ $headers = (options.headers !== undefined) ? $(options.headers) : this.$headers;
+ lastOnly = (options.lastOnly !== undefined) ? options.lastOnly : true;
+ return lastOnly ? $headers.filter('[data-column="' + n + '"]:last') : $headers.filter('[data-column="' + n + '"]');
+ },
+ };
+
/* debuging utils */
function log() {
var a = arguments[0],
@@ -256,7 +268,7 @@
if (rows.length) {
l = c.columns; // rows[j].cells.length;
for (i = 0; i < l; i++) {
- h = c.$headers.filter('[data-column="' + i + '"]:last');
+ h = c.$columnHeader(i);
// get column indexed table cell
ch = ts.getColumnData( table, c.headers, i );
// get column parser/extractor
@@ -561,7 +573,7 @@
// direction = 2 means reset!
if (list[i][1] !== 2) {
// multicolumn sorting updating - choose the :last in case there are nested columns
- f = c.$headers.not('.sorter-false').filter('[data-column="' + list[i][0] + '"]' + (len === 1 ? ':last' : '') );
+ f = c.$columnHeader(list[i][0], {lastOnly: (len === 1)}).not('.sorter-false');
if (f.length) {
for (j = 0; j < f.length; j++) {
if (!f[j].sortDisabled) {
@@ -601,7 +613,7 @@
// ensure all sortList values are numeric - fixes #127
col = parseInt(v[0], 10);
// make sure header exists
- o = c.$headers.filter('[data-column="' + col + '"]:last')[0];
+ o = c.$columnHeader(col)[0];
if (o) { // prevents error if sorton array is wrong
// o.count = o.count + 1;
t = ('' + v[1]).match(/^(1|d|s|o|n)/);
@@ -705,7 +717,7 @@
// reverse the sorting direction
for (col = 0; col < c.sortList.length; col++) {
s = c.sortList[col];
- order = c.$headers.filter('[data-column="' + s[0] + '"]:last')[0];
+ order = c.$columnHeader( s[0] )[0];
if (s[0] === indx) {
// order.count seems to be incorrect when compared to cell.count
s[1] = order.order[cell.count];
@@ -1051,7 +1063,7 @@
return this.each(function() {
var table = this,
// merge & extend config options
- c = $.extend(true, {}, ts.defaults, settings);
+ c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods);
// save initial settings
c.originalSettings = settings;
// create a table from data (build table widget)
@@ -1600,6 +1612,12 @@
}
};
+ // Use it to add a set of methods to table.config which will be available for all tables.
+ // This should be done before table initialization
+ ts.addInstanceMethods = function(methods) {
+ $.extend(ts.instanceMethods, methods);
+ };
+
ts.getParserById = function(name) {
/*jshint eqeqeq:false */
if (name == 'false') { return false; }
@@ -1955,7 +1973,7 @@
if (s) {
var date, d,
c = table.config,
- ci = c.$headers.filter('[data-column="' + cellIndex + '"]:last'),
+ ci = c.$columnHeader(cellIndex),
format = ci.length && ci[0].dateFormat || ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat;
d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'); // escaped - because JSHint in Firefox was showing it as an error
if (format === 'mmddyyyy') {
diff --git a/js/parsers/parser-metric.js b/js/parsers/parser-metric.js
index db1f85ad..622a265f 100644
--- a/js/parsers/parser-metric.js
+++ b/js/parsers/parser-metric.js
@@ -47,7 +47,7 @@
b, t,
// process number here to get a numerical format (us or eu)
n = $.tablesorter.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table),
- $t = table.config.$headers.filter('[data-column="' + cellIndex + '"]'),
+ $t = table.config.$columnHeader(cellIndex, {lastOnly: false}),
m = $t.data('metric');
if (!m) {
// stored values
diff --git a/js/widgets/widget-filter-formatter-select2.js b/js/widgets/widget-filter-formatter-select2.js
index 9b1ad25c..d8f3e3c9 100644
--- a/js/widgets/widget-filter-formatter-select2.js
+++ b/js/widgets/widget-filter-formatter-select2.js
@@ -36,7 +36,7 @@ ts.filterFormatter.select2 = function($cell, indx, select2Def) {
$cell.find('.select2').select2('val', val);
updateSelect2();
}),
- $header = c.$headers.filter('[data-column="' + indx + '"]:last'),
+ $header = c.$columnHeader(indx),
onlyAvail = $header.hasClass(wo.filter_onlyAvail),
$shcell = [],
matchPrefix = o.match ? '' : '^',
diff --git a/js/widgets/widget-filter.js b/js/widgets/widget-filter.js
index 1b0b1635..d289cd68 100644
--- a/js/widgets/widget-filter.js
+++ b/js/widgets/widget-filter.js
@@ -209,7 +209,7 @@ ts.filter = {
parsed = data.parsed[index],
query = ts.filter.parseFilter(c, data.iFilter.replace(ts.filter.regex.orReplace, "|"), index, parsed);
// look for an exact match with the "or" unless the "filter-match" class is found
- if (!c.$headers.filter('[data-column="' + index + '"]:last').hasClass('filter-match') && /\|/.test(query)) {
+ if (!c.$columnHeader(index).hasClass('filter-match') && /\|/.test(query)) {
// show all results while using filter match. Fixes #727
if (query[ query.length - 1 ] === '|') { query += '*'; }
query = data.anyMatch && $.isArray(data.rowArray) ? '(' + query + ')' : '^(' + query + ')$';
@@ -330,7 +330,7 @@ ts.filter = {
fxn = ts.getColumnData( table, wo.filter_functions, column );
if (fxn) {
// remove "filter-select" from header otherwise the options added here are replaced with all options
- $header = c.$headers.filter('[data-column="' + column + '"]:last').removeClass('filter-select');
+ $header = c.$columnHeader(column).removeClass('filter-select');
// don't build select if "filter-false" or "parser-false" set
noSelect = !($header.hasClass('filter-false') || $header.hasClass('parser-false'));
options = '';
@@ -468,7 +468,7 @@ ts.filter = {
// if no filters saved, then check default settings
if (filters.join('') === '') {
for (indx = 0; indx < c.columns; indx++) {
- filters[indx] = c.$headers.filter('[data-column="' + indx + '"]:last').attr(wo.filter_defaultAttrib) || filters[indx];
+ filters[indx] = c.$columnHeader(indx).attr(wo.filter_defaultAttrib) || filters[indx];
}
}
c.$table.data('lastSearch', filters);
@@ -497,7 +497,7 @@ ts.filter = {
for (column = 0; column < columns; column++) {
disabled = false;
// assuming last cell of a column is the main column
- $header = c.$headers.filter('[data-column="' + column + '"]:last');
+ $header = c.$columnHeader(column);
ffxn = ts.getColumnData( table, wo.filter_functions, column );
buildSelect = (wo.filter_functions && ffxn && typeof ffxn !== "function" ) ||
$header.hasClass('filter-select');
@@ -784,7 +784,7 @@ ts.filter = {
data.parsed = c.$headers.map(function(columnIndex) {
return c.parsers && c.parsers[columnIndex] && c.parsers[columnIndex].parsed ||
// getData won't return "parsed" if other "filter-" class names exist (e.g. | )
- ts.getData && ts.getData(c.$headers.filter('[data-column="' + columnIndex + '"]:last'), ts.getColumnData( table, c.headers, columnIndex ), 'filter') === 'parsed' ||
+ ts.getData && ts.getData(c.$columnHeader(columnIndex), ts.getColumnData( table, c.headers, columnIndex ), 'filter') === 'parsed' ||
$(this).hasClass('filter-parsed');
}).get();
@@ -860,7 +860,7 @@ ts.filter = {
// don't search only filtered if the value is negative ('> -10' => '> -100' will ignore hidden rows)
!(/(>=?\s*-\d)/.test(val) || /(<=?\s*\d)/.test(val)) &&
// if filtering using a select without a "filter-match" class (exact match) - fixes #593
- !( val !== '' && c.$filters && c.$filters.eq(indx).find('select').length && !c.$headers.filter('[data-column="' + indx + '"]:last').hasClass('filter-match') );
+ !( val !== '' && c.$filters && c.$filters.eq(indx).find('select').length && !c.$columnHeader(indx).hasClass('filter-match') );
}
}
notFiltered = $rows.not('.' + wo.filter_filteredRow).length;
@@ -990,7 +990,7 @@ ts.filter = {
// data.iFilter = case insensitive (if wo.filter_ignoreCase is true), data.filter = case sensitive
data.iFilter = wo.filter_ignoreCase ? (data.filter || '').toLocaleLowerCase() : data.filter;
fxn = ts.getColumnData( table, wo.filter_functions, columnIndex );
- $cell = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
+ $cell = c.$columnHeader(columnIndex);
hasSelect = $cell.hasClass('filter-select');
if ( fxn || ( hasSelect && val ) ) {
if (fxn === true || hasSelect) {
@@ -1093,7 +1093,7 @@ ts.filter = {
return $.inArray(value, arry) === indx;
});
- if (c.$headers.filter('[data-column="' + column + '"]:last').hasClass('filter-select-nosort')) {
+ if (c.$columnHeader(column).hasClass('filter-select-nosort')) {
// unsorted select options
return arry;
} else {
@@ -1146,7 +1146,7 @@ ts.filter = {
// check if has class filtered
if (onlyAvail && row.className.match(wo.filter_filteredRow)) { continue; }
// get non-normalized cell content
- if (wo.filter_useParsedData || c.parsers[column].parsed || c.$headers.filter('[data-column="' + column + '"]:last').hasClass('filter-parsed')) {
+ if (wo.filter_useParsedData || c.parsers[column].parsed || c.$columnHeader(column).hasClass('filter-parsed')) {
arry.push( '' + cache.normalized[rowIndex][column] );
} else {
cell = row.cells[column];
@@ -1165,7 +1165,7 @@ ts.filter = {
var indx, val, txt, t, $filters, $filter,
c = table.config,
wo = c.widgetOptions,
- node = c.$headers.filter('[data-column="' + column + '"]:last'),
+ node = c.$columnHeader(column),
// t.data('placeholder') won't work in jQuery older than 1.4.3
options = '',
// Get curent filter value
@@ -1220,7 +1220,7 @@ ts.filter = {
columns = c.columns;
// build default select dropdown
for (columnIndex = 0; columnIndex < columns; columnIndex++) {
- $header = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
+ $header = c.$columnHeader(columnIndex);
noSelect = !($header.hasClass('filter-false') || $header.hasClass('parser-false'));
// look for the filter-select class; build/update it if found
if (($header.hasClass('filter-select') || ts.getColumnData( table, wo.filter_functions, columnIndex ) === true) && noSelect) {
diff --git a/js/widgets/widget-formatter.js b/js/widgets/widget-formatter.js
index 8b8cd4fe..ee2b8df3 100644
--- a/js/widgets/widget-formatter.js
+++ b/js/widgets/widget-formatter.js
@@ -29,7 +29,7 @@
$headers = [];
// set up variables
for ( column = 0; column < c.columns; column++ ) {
- $headers[ column ] = c.$headers.filter('[data-column="' + column + '"]:last');
+ $headers[ column ] = c.$columnHeader(column);
formatter[ column ] = ts.getColumnData( c.table, wo.formatter_column, column ) || false;
}
// main loop
diff --git a/js/widgets/widget-grouping.js b/js/widgets/widget-grouping.js
index 546743dc..530cde8a 100644
--- a/js/widgets/widget-grouping.js
+++ b/js/widgets/widget-grouping.js
@@ -66,12 +66,12 @@ ts.grouping = {
// clear pager saved spacer height (in case the rows are collapsed)
c.$table.data('pagerSavedHeight', 0);
}
- if (column >= 0 && !c.$headers.filter('[data-column="' + column + '"]:last').hasClass('group-false')) {
+ if (column >= 0 && !c.$columnHeader(column).hasClass('group-false')) {
wo.group_currentGroup = ''; // save current groups
wo.group_currentGroups = {};
// group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}"
- groupClass = (c.$headers.filter('[data-column="' + column + '"]:last').attr('class') || '').match(/(group-\w+(-\w+)?)/g);
+ groupClass = (c.$columnHeader(column).attr('class') || '').match(/(group-\w+(-\w+)?)/g);
// grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ]
grouping = groupClass ? groupClass[0].split('-') : ['group','letter',1]; // default to letter 1
@@ -97,14 +97,14 @@ ts.grouping = {
// fixes #438
if (ts.grouping.types[grouping[1]]) {
currentGroup = norm_rows[rowIndex] ?
- ts.grouping.types[grouping[1]]( c, c.$headers.filter('[data-column="' + column + '"]:last'), norm_rows[rowIndex][column], /date/.test(groupClass) ?
+ ts.grouping.types[grouping[1]]( c, c.$columnHeader(column), norm_rows[rowIndex][column], /date/.test(groupClass) ?
grouping[2] : parseInt(grouping[2] || 1, 10) || 1, group, lang ) : currentGroup;
if (group !== currentGroup) {
group = currentGroup;
// show range if number > 1
if (grouping[1] === 'number' && grouping[2] > 1 && currentGroup !== '') {
currentGroup += ' - ' + (parseInt(currentGroup, 10) +
- ((parseInt(grouping[2],10) - 1) * (c.$headers.filter('[data-column="' + column + '"]:last').hasClass(ts.css.sortAsc) ? 1 : -1)));
+ ((parseInt(grouping[2],10) - 1) * (c.$columnHeader(column).hasClass(ts.css.sortAsc) ? 1 : -1)));
}
if ($.isFunction(wo.group_formatter)) {
currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup;
diff --git a/js/widgets/widget-reflow.js b/js/widgets/widget-reflow.js
index 07bec5bf..7e8f9a25 100644
--- a/js/widgets/widget-reflow.js
+++ b/js/widgets/widget-reflow.js
@@ -97,7 +97,7 @@ tablereflow = {
// add to every table cell with thead cell contents
for (i = 0; i < cols; i++) {
- $hdr = c.$headers.filter('[data-column="' + i + '"]');
+ $hdr = c.$columnHeader(i, {lastOnly: false});
if ($hdr.length > 1) {
txt = [];
/*jshint loopfunc:true */
diff --git a/js/widgets/widget-resizable.js b/js/widgets/widget-resizable.js
index fd8e8fca..0f4fb8b4 100644
--- a/js/widgets/widget-resizable.js
+++ b/js/widgets/widget-resizable.js
@@ -109,7 +109,7 @@ ts.addWidget({
.bind('mousedown', function(event) {
// save header cell and mouse position
$target = $(event.target).closest('th');
- var $header = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]');
+ var $header = c.$columnHeader($target.attr('data-column'), {lastOnly: false});
if ($header.length > 1) { $target = $target.add($header); }
// if table is not as wide as it's parent, then resize the table
$next = event.shiftKey ? $target.parent().find('th').not('.resizable-false').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0);
diff --git a/js/widgets/widget-uitheme.js b/js/widgets/widget-uitheme.js
index 90e046dd..3b495fd1 100644
--- a/js/widgets/widget-uitheme.js
+++ b/js/widgets/widget-uitheme.js
@@ -130,9 +130,9 @@ ts.addWidget({
}
}
for (i = 0; i < c.columns; i++) {
- $header = c.$headers.add(c.$extraHeaders).not('.sorter-false').filter('[data-column="' + i + '"]');
+ $header = c.$columnHeader(i, {headers: c.$headers.add(c.$extraHeaders), lastOnly: false}).not('.sorter-false');
$icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $();
- $h = $headers.not('.sorter-false').filter('[data-column="' + i + '"]:last');
+ $h = c.$columnHeader(i, {headers: $headers}).not('.sorter-false');
if ($h.length) {
$header.removeClass(remove);
$icon.removeClass(iconRmv);
|