Build: Add jscs checking & fix style issues

Thanks @Herst!
This commit is contained in:
Mottie 2015-07-22 23:29:51 -05:00
parent bd296c844f
commit 75de112ef6
63 changed files with 18095 additions and 17995 deletions

65
.jscsrc Normal file
View File

@ -0,0 +1,65 @@
{
"disallowDanglingUnderscores": true,
"disallowEmptyBlocks": true,
"disallowKeywords": [
"with"
],
"disallowMixedSpacesAndTabs": "smart",
"disallowMultipleLineBreaks": true,
"disallowMultipleLineStrings": true,
"disallowNewlineBeforeBlockStatements": true,
"disallowOperatorBeforeLineBreak": [
"."
],
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowSpaceBeforeBinaryOperators": [
","
],
"disallowSpaceBeforePostfixUnaryOperators": true,
"disallowSpacesInCallExpression": true,
"disallowTrailingComma": true,
"maximumLineLength": {
"allowRegex": true,
"allowUrlComments": true,
"tabSize": 2,
"value": 180
},
"requireBlocksOnNewline": 1,
"requireCommaBeforeLineBreak": true,
"requireCurlyBraces": [
"do"
],
"requireDollarBeforejQueryAssignment": true,
"requireDotNotation": true,
"requireLineFeedAtFileEnd": true,
"requireParenthesesAroundIIFE": true,
"requireSemicolons": true,
"requireSpaceAfterBinaryOperators": true,
"requireSpaceAfterKeywords": [
"if",
"else",
"for",
"while",
"do",
"switch",
"case",
"return",
"try",
"catch",
"typeof"
],
"requireSpaceAfterLineComment": true,
"requireSpaceBeforeBinaryOperators": true,
"requireSpacesInConditionalExpression": true,
"requireSpacesInForStatement": true,
"requireSpacesInsideArrayBrackets": "all",
"validateIndentation": {
"includeEmptyLines": false,
"value": "\t"
},
"validateQuoteMarks": {
"escape": true,
"mark": "'"
}
}

View File

@ -209,6 +209,26 @@ module.exports = function( grunt ) {
} }
}, },
jscs: {
src: [
'addons/pager/*.js',
'!addons/pager/*.min.js',
'js/jquery.*.js',
'js/**/*.js',
'!js/_test-*.js',
'!js/jquery.tablesorter.combined.js',
'!js/jquery.tablesorter.widgets.js',
'!js/extras/jquery.dragtable.mod.js', // indents with spaces; keeping original formatting to make diffs easier
'!js/extras/jquery.metadata.js', // phasing this one out anyway
'!js/**/_test-*.js',
'!js/*.min.js',
'!js/**/semver*.js'
],
options: {
config: '.jscsrc'
}
},
jshint: { jshint: {
files: { files: {
src: [ src: [
@ -317,8 +337,9 @@ module.exports = function( grunt ) {
grunt.loadNpmTasks( 'grunt-contrib-copy' ); grunt.loadNpmTasks( 'grunt-contrib-copy' );
grunt.loadNpmTasks( 'grunt-contrib-watch' ); grunt.loadNpmTasks( 'grunt-contrib-watch' );
grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
grunt.loadNpmTasks( 'grunt-jscs' );
grunt.registerTask( 'test', [ 'jshint', 'qunit' ] ); grunt.registerTask( 'test', [ 'jscs', 'jshint', 'qunit' ] );
tasks = [ tasks = [
'clean:build', 'clean:build',

View File

@ -4,7 +4,7 @@
*/ */
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
;(function($) { ;(function($) {
"use strict"; 'use strict';
/*jshint supernew:true */ /*jshint supernew:true */
var ts = $.tablesorter; var ts = $.tablesorter;
@ -176,13 +176,13 @@
// form the output string (can now get a new output string from the server) // form the output string (can now get a new output string from the server)
s = ( p.ajaxData && p.ajaxData.output ? p.ajaxData.output || p.output : p.output ) s = ( p.ajaxData && p.ajaxData.output ? p.ajaxData.output || p.output : p.output )
// {page} = one-based index; {page+#} = zero based index +/- value // {page} = one-based index; {page+#} = zero based index +/- value
.replace(/\{page([\-+]\d+)?\}/gi, function(m,n){ .replace(/\{page([\-+]\d+)?\}/gi, function(m, n){
return p.totalPages ? p.page + (n ? parseInt(n, 10) : 1) : 0; return p.totalPages ? p.page + (n ? parseInt(n, 10) : 1) : 0;
}) })
// {totalPages}, {extra}, {extra:0} (array) or {extra : key} (object) // {totalPages}, {extra}, {extra:0} (array) or {extra : key} (object)
.replace(/\{\w+(\s*:\s*\w+)?\}/gi, function(m){ .replace(/\{\w+(\s*:\s*\w+)?\}/gi, function(m){
var len, indx, var len, indx,
str = m.replace(/[{}\s]/g,''), str = m.replace(/[{}\s]/g, ''),
extra = str.split(':'), extra = str.split(':'),
data = p.ajaxData, data = p.ajaxData,
// return zero for default page/row numbers // return zero for default page/row numbers
@ -209,7 +209,7 @@
// rebind startRow/page inputs // rebind startRow/page inputs
$out.find('.ts-startRow, .ts-page').unbind('change' + namespace).bind('change' + namespace, function(){ $out.find('.ts-startRow, .ts-page').unbind('change' + namespace).bind('change' + namespace, function(){
var v = $(this).val(), var v = $(this).val(),
pg = $(this).hasClass('ts-startRow') ? Math.floor( v/p.size ) + 1 : v; pg = $(this).hasClass('ts-startRow') ? Math.floor( v / p.size ) + 1 : v;
c.$table.trigger('pageSet' + namespace, [ pg ]); c.$table.trigger('pageSet' + namespace, [ pg ]);
}); });
} }
@ -242,7 +242,7 @@
current_page = p.page + 1, current_page = p.page + 1,
start_page = skip_set_size, start_page = skip_set_size,
end_page = pg - skip_set_size, end_page = pg - skip_set_size,
option_pages = [1], option_pages = [ 1 ],
// construct default options pages array // construct default options pages array
option_pages_start_page = (large_collection) ? skip_set_size : 1; option_pages_start_page = (large_collection) ? skip_set_size : 1;
@ -286,7 +286,7 @@
option_pages = $.grep(option_pages, function(value, indx) { option_pages = $.grep(option_pages, function(value, indx) {
return $.inArray(value, option_pages) === indx; return $.inArray(value, option_pages) === indx;
}) })
.sort(function(a,b) { return a - b; }); .sort(function(a, b) { return a - b; });
return option_pages; return option_pages;
}, },
@ -376,7 +376,7 @@
renderAjax = function(data, table, p, xhr, exception){ renderAjax = function(data, table, p, xhr, exception){
// process data // process data
if ( typeof(p.ajaxProcessing) === "function" ) { if ( typeof p.ajaxProcessing === 'function' ) {
// ajaxProcessing result: [ total, rows, headers ] // ajaxProcessing result: [ total, rows, headers ]
var i, j, t, hsh, $f, $sh, $headers, $h, icon, th, d, l, rr_count, len, var i, j, t, hsh, $f, $sh, $headers, $h, icon, th, d, l, rr_count, len,
c = table.config, c = table.config,
@ -483,7 +483,7 @@
p.last.currentFilters = p.currentFilters; p.last.currentFilters = p.currentFilters;
p.last.sortList = (c.sortList || []).join(','); p.last.sortList = (c.sortList || []).join(',');
updatePageDisplay(table, p, false); updatePageDisplay(table, p, false);
$table.trigger('updateCache', [function(){ $table.trigger('updateCache', [ function(){
if (p.initialized) { if (p.initialized) {
// apply widgets after table has rendered & after a delay to prevent // apply widgets after table has rendered & after a delay to prevent
// multiple applyWidget blocking code from blocking this trigger // multiple applyWidget blocking code from blocking this trigger
@ -495,9 +495,9 @@
.trigger('applyWidgets') .trigger('applyWidgets')
.trigger('pagerChange', p); .trigger('pagerChange', p);
updatePageDisplay(table, p, true); updatePageDisplay(table, p, true);
}, 0); }, 0);
} }
}]); } ]);
} }
if (!p.initialized) { if (!p.initialized) {
@ -555,7 +555,7 @@
c = table.config, c = table.config,
url = (p.ajaxUrl) ? p.ajaxUrl url = (p.ajaxUrl) ? p.ajaxUrl
// allow using "{page+1}" in the url string to switch to a non-zero based index // allow using "{page+1}" in the url string to switch to a non-zero based index
.replace(/\{page([\-+]\d+)?\}/, function(s,n){ return p.page + (n ? parseInt(n, 10) : 0); }) .replace(/\{page([\-+]\d+)?\}/, function(s, n){ return p.page + (n ? parseInt(n, 10) : 0); })
.replace(/\{size\}/g, p.size) : '', .replace(/\{size\}/g, p.size) : '',
sortList = c.sortList, sortList = c.sortList,
filterList = p.currentFilters || $(table).data('lastSearch') || [], filterList = p.currentFilters || $(table).data('lastSearch') || [],
@ -584,7 +584,7 @@
url = url.replace(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/g, arry.length ? arry.join('&') : filterCol ); url = url.replace(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/g, arry.length ? arry.join('&') : filterCol );
p.currentFilters = filterList; p.currentFilters = filterList;
} }
if ( typeof(p.customAjaxUrl) === "function" ) { if ( typeof p.customAjaxUrl === 'function' ) {
url = p.customAjaxUrl(table, url); url = p.customAjaxUrl(table, url);
} }
if (c.debug) { if (c.debug) {
@ -940,13 +940,13 @@
changeHeight(table, p); changeHeight(table, p);
updatePageDisplay(table, p, true); updatePageDisplay(table, p, true);
}) })
.bind('pageSize refreshComplete '.split(' ').join(namespace + ' '), function(e,v){ .bind('pageSize refreshComplete '.split(' ').join(namespace + ' '), function(e, v){
e.stopPropagation(); e.stopPropagation();
setPageSize(table, parseInt(v, 10) || p.settings.size || 10, p); setPageSize(table, parseInt(v, 10) || p.settings.size || 10, p);
hideRows(table, p); hideRows(table, p);
updatePageDisplay(table, p, false); updatePageDisplay(table, p, false);
}) })
.bind('pageSet pagerUpdate '.split(' ').join(namespace + ' '), function(e,v){ .bind('pageSet pagerUpdate '.split(' ').join(namespace + ' '), function(e, v){
e.stopPropagation(); e.stopPropagation();
// force pager refresh // force pager refresh
if (e.type === 'pagerUpdate') { if (e.type === 'pagerUpdate') {
@ -973,7 +973,7 @@
ts.log('Pager: >> Container not found'); ts.log('Pager: >> Container not found');
} }
pager.find(ctrls.join(',')) pager.find(ctrls.join(','))
.attr("tabindex", 0) .attr('tabindex', 0)
.unbind('click' + namespace) .unbind('click' + namespace)
.bind('click' + namespace, function(e){ .bind('click' + namespace, function(e){
e.stopPropagation(); e.stopPropagation();
@ -1024,17 +1024,18 @@
$t.trigger('pagerBeforeInitialized', p); $t.trigger('pagerBeforeInitialized', p);
enablePager(table, p, false); enablePager(table, p, false);
if ( typeof(p.ajaxUrl) === 'string' ) { if ( typeof p.ajaxUrl === 'string' ) {
// ajax pager; interact with database // ajax pager; interact with database
p.ajax = true; p.ajax = true;
//When filtering with ajax, allow only custom filtering function, disable default filtering since it will be done server side. // When filtering with ajax, allow only custom filtering function, disable default
// filtering since it will be done server side.
c.widgetOptions.filter_serversideFiltering = true; c.widgetOptions.filter_serversideFiltering = true;
c.serverSideSorting = true; c.serverSideSorting = true;
moveToPage(table, p); moveToPage(table, p);
} else { } else {
p.ajax = false; p.ajax = false;
// Regular pager; all rows stored in memory // Regular pager; all rows stored in memory
$(this).trigger("appendCache", true); $(this).trigger('appendCache', true);
hideRowsSetup(table, p); hideRowsSetup(table, p);
} }
@ -1087,9 +1088,9 @@
} }
}; };
// extend plugin scope // extend plugin scope
$.fn.extend({ $.fn.extend({
tablesorterPager: $.tablesorterPager.construct tablesorterPager: $.tablesorterPager.construct
}); });
})(jQuery); })(jQuery);

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -198,7 +198,7 @@
// node could be a jquery object // node could be a jquery object
// http://jsperf.com/jquery-vs-instanceof-jquery/2 // http://jsperf.com/jquery-vs-instanceof-jquery/2
$node = node.jquery ? node : $(node); $node = node.jquery ? node : $(node);
if (typeof(t) === 'string') { if (typeof t === 'string') {
// check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow! // check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow!
// http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/ // http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/
if ( t === 'basic' && typeof ( te = $node.attr(c.textAttribute) ) !== 'undefined' ) { if ( t === 'basic' && typeof ( te = $node.attr(c.textAttribute) ) !== 'undefined' ) {
@ -206,7 +206,7 @@
} }
return $.trim( node.textContent || $node.text() ); return $.trim( node.textContent || $node.text() );
} else { } else {
if (typeof(t) === 'function') { if (typeof t === 'function') {
return $.trim( t($node[0], c.table, cellIndex) ); return $.trim( t($node[0], c.table, cellIndex) );
} else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') { } else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') {
return $.trim( te($node[0], c.table, cellIndex) ); return $.trim( te($node[0], c.table, cellIndex) );
@ -266,7 +266,7 @@
// make sure txt is a string (extractor may have converted it) // make sure txt is a string (extractor may have converted it)
parser.format( '' + txt, c.table, cell, colIndex ); parser.format( '' + txt, c.table, cell, colIndex );
if ( c.ignoreCase && typeof val === 'string' ) { if ( c.ignoreCase && typeof val === 'string' ) {
val = val.toLowerCase(); val = val.toLowerCase();
} }
} }
return val; return val;
@ -510,20 +510,22 @@
// set up header template // set up header template
t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i); t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i);
if (c.onRenderTemplate) { if (c.onRenderTemplate) {
h = c.onRenderTemplate.apply($t, [index, t]); h = c.onRenderTemplate.apply( $t, [ index, t ] );
if (h && typeof h === 'string') { t = h; } // only change t if something is returned if (h && typeof h === 'string') { t = h; } // only change t if something is returned
} }
$t.html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner $t.html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner
} }
if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index, c, c.$table]); } if (c.onRenderHeader) { c.onRenderHeader.apply( $t, [ index, c, c.$table ] ); }
// *** remove this.column value if no conflicts found // *** remove this.column value if no conflicts found
elem.column = parseInt( $t.attr('data-column'), 10); elem.column = parseInt( $t.attr('data-column'), 10);
elem.order = formatSortingOrder( ts.getData($t, ch, 'sortInitialOrder') || c.sortInitialOrder ) ? [1,0,2] : [0,1,2]; elem.order = formatSortingOrder( ts.getData( $t, ch, 'sortInitialOrder' ) || c.sortInitialOrder ) ?
[ 1, 0, 2 ] : // desc, asc, unsorted
[ 0, 1, 2 ]; // asc, desc, unsorted
elem.count = -1; // set to -1 because clicking on the header automatically adds one elem.count = -1; // set to -1 because clicking on the header automatically adds one
elem.lockedOrder = false; elem.lockedOrder = false;
lock = ts.getData($t, ch, 'lockedOrder') || false; lock = ts.getData($t, ch, 'lockedOrder') || false;
if (typeof lock !== 'undefined' && lock !== false) { if (typeof lock !== 'undefined' && lock !== false) {
elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [1,1,1] : [0,0,0]; elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [ 1, 1, 1 ] : [ 0, 0, 0 ];
} }
$t.addClass(ts.css.header + ' ' + c.cssHeader); $t.addClass(ts.css.header + ' ' + c.cssHeader);
// add cell to headerList // add cell to headerList
@ -593,9 +595,9 @@
list = c.sortList, list = c.sortList,
len = list.length, len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone, none = ts.css.sortNone + ' ' + c.cssNone,
css = [ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc], css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ], cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
aria = ['ascending', 'descending'], aria = [ 'ascending', 'descending' ],
// find the footer // find the footer
$t = $(table).find('tfoot tr').children() $t = $(table).find('tfoot tr').children()
.add( $( c.namespace + '_extra_headers' ) ) .add( $( c.namespace + '_extra_headers' ) )
@ -665,7 +667,7 @@
dir = ('' + val[1]).match(/^(1|d|s|o|n)/); dir = ('' + val[1]).match(/^(1|d|s|o|n)/);
dir = dir ? dir[0] : ''; dir = dir ? dir[0] : '';
// 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext // 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext
switch(dir) { switch (dir) {
case '1': case 'd': // descending case '1': case 'd': // descending
dir = 1; dir = 1;
break; break;
@ -741,11 +743,11 @@
// add column to sort list // add column to sort list
order = cell.order[cell.count]; order = cell.order[cell.count];
if (order < 2) { if (order < 2) {
c.sortList.push([indx, order]); c.sortList.push([ indx, order ]);
// add other columns if header spans across multiple // add other columns if header spans across multiple
if (cell.colSpan > 1) { if (cell.colSpan > 1) {
for (col = 1; col < cell.colSpan; col++) { for (col = 1; col < cell.colSpan; col++) {
c.sortList.push([indx + col, order]); c.sortList.push([ indx + col, order ]);
} }
} }
} }
@ -756,7 +758,7 @@
for (col = 0; col < c.sortAppend.length; col++) { for (col = 0; col < c.sortAppend.length; col++) {
s = ts.isValueInArray(c.sortAppend[col][0], c.sortList); s = ts.isValueInArray(c.sortAppend[col][0], c.sortList);
if (s >= 0) { if (s >= 0) {
c.sortList.splice(s,1); c.sortList.splice(s, 1);
} }
} }
} }
@ -770,7 +772,7 @@
// order.count seems to be incorrect when compared to cell.count // order.count seems to be incorrect when compared to cell.count
s[1] = order.order[cell.count]; s[1] = order.order[cell.count];
if (s[1] === 2) { if (s[1] === 2) {
c.sortList.splice(col,1); c.sortList.splice(col, 1);
order.count = -1; order.count = -1;
} }
} }
@ -779,11 +781,11 @@
// add column to sort list array // add column to sort list array
order = cell.order[cell.count]; order = cell.order[cell.count];
if (order < 2) { if (order < 2) {
c.sortList.push([indx, order]); c.sortList.push([ indx, order ]);
// add other columns if header spans across multiple // add other columns if header spans across multiple
if (cell.colSpan > 1) { if (cell.colSpan > 1) {
for (col = 1; col < cell.colSpan; col++) { for (col = 1; col < cell.colSpan; col++) {
c.sortList.push([indx + col, order]); c.sortList.push([ indx + col, order ]);
} }
} }
} }
@ -857,10 +859,10 @@
x = dir ? a : b; x = dir ? a : b;
y = dir ? b : a; y = dir ? b : a;
// text sort function // text sort function
if (typeof(cts) === 'function') { if (typeof cts === 'function') {
// custom OVERALL text sorter // custom OVERALL text sorter
sort = cts(x[col], y[col], dir, col, table); sort = cts(x[col], y[col], dir, col, table);
} else if (typeof(cts) === 'object' && cts.hasOwnProperty(col)) { } else if (typeof cts === 'object' && cts.hasOwnProperty(col)) {
// custom text sorter for a SPECIFIC COLUMN // custom text sorter for a SPECIFIC COLUMN
sort = cts[col](x[col], y[col], dir, col, table); sort = cts[col](x[col], y[col], dir, col, table);
} else { } else {
@ -893,14 +895,14 @@
// this will catch spamming of the updateCell method // this will catch spamming of the updateCell method
if (resrt !== false && !c.serverSideSorting && !c.table.isProcessing) { if (resrt !== false && !c.serverSideSorting && !c.table.isProcessing) {
if (sl.length) { if (sl.length) {
c.$table.trigger('sorton', [sl, function(){ c.$table.trigger('sorton', [ sl, function(){
resortComplete(c, callback); resortComplete(c, callback);
}, true]); }, true ]);
} else { } else {
c.$table.trigger('sortReset', [function(){ c.$table.trigger('sortReset', [ function(){
resortComplete(c, callback); resortComplete(c, callback);
ts.applyWidget(c.table, false); ts.applyWidget(c.table, false);
}]); } ]);
} }
} else { } else {
resortComplete(c, callback); resortComplete(c, callback);
@ -1100,10 +1102,10 @@
ts.construct = function(settings) { ts.construct = function(settings) {
return this.each(function() { return this.each(function() {
var table = this, var table = this,
// merge & extend config options // merge & extend config options
c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods); c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods);
// save initial settings // save initial settings
c.originalSettings = settings; c.originalSettings = settings;
// create a table from data (build table widget) // create a table from data (build table widget)
if (!table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE') { if (!table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE') {
// return the table (in case the original target is the table's container) // return the table (in case the original target is the table's container)
@ -1158,7 +1160,7 @@
c.namespace = '.tablesorter' + Math.random().toString(16).slice(2); c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
} else { } else {
// make sure namespace starts with a period & doesn't have weird characters // make sure namespace starts with a period & doesn't have weird characters
c.namespace = '.' + c.namespace.replace(/\W/g,''); c.namespace = '.' + c.namespace.replace(/\W/g, '');
} }
c.$table.children().children('tr').attr('role', 'row'); c.$table.children().children('tr').attr('role', 'row');
@ -1202,7 +1204,7 @@
ts.applyWidget(table, true); ts.applyWidget(table, true);
// if user has supplied a sort list to constructor // if user has supplied a sort list to constructor
if (c.sortList.length > 0) { if (c.sortList.length > 0) {
$table.trigger('sorton', [c.sortList, {}, !c.initWidgets, true]); $table.trigger('sorton', [ c.sortList, {}, !c.initWidgets, true ]);
} else { } else {
setHeadersCss(table); setHeadersCss(table);
if (c.initWidgets) { if (c.initWidgets) {
@ -1241,22 +1243,22 @@
table = $(table)[0]; table = $(table)[0];
var overallWidth, percent, $tbodies, len, index, var overallWidth, percent, $tbodies, len, index,
c = table.config, c = table.config,
colgroup = c.$table.children('colgroup'); $colgroup = c.$table.children('colgroup');
// remove plugin-added colgroup, in case we need to refresh the widths // remove plugin-added colgroup, in case we need to refresh the widths
if (colgroup.length && colgroup.hasClass(ts.css.colgroup)) { if ($colgroup.length && $colgroup.hasClass(ts.css.colgroup)) {
colgroup.remove(); $colgroup.remove();
} }
if (c.widthFixed && c.$table.children('colgroup').length === 0) { if (c.widthFixed && c.$table.children('colgroup').length === 0) {
colgroup = $('<colgroup class="' + ts.css.colgroup + '">'); $colgroup = $('<colgroup class="' + ts.css.colgroup + '">');
overallWidth = c.$table.width(); overallWidth = c.$table.width();
// only add col for visible columns - fixes #371 // only add col for visible columns - fixes #371
$tbodies = c.$tbodies.find('tr:first').children(':visible'); //.each(function() $tbodies = c.$tbodies.find('tr:first').children(':visible'); // .each(function()
len = $tbodies.length; len = $tbodies.length;
for ( index = 0; index < len; index++ ) { for ( index = 0; index < len; index++ ) {
percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%'; percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%';
colgroup.append( $('<col>').css('width', percent) ); $colgroup.append( $('<col>').css('width', percent) );
} }
c.$table.prepend(colgroup); c.$table.prepend($colgroup);
} }
}; };
@ -1303,12 +1305,12 @@
cellId = rowIndex + '-' + $cell.index(); cellId = rowIndex + '-' + $cell.index();
rowSpan = cell.rowSpan || 1; rowSpan = cell.rowSpan || 1;
colSpan = cell.colSpan || 1; colSpan = cell.colSpan || 1;
if (typeof(matrix[rowIndex]) === 'undefined') { if (typeof matrix[rowIndex] === 'undefined') {
matrix[rowIndex] = []; matrix[rowIndex] = [];
} }
// Find first available column in the first row // Find first available column in the first row
for (k = 0; k < matrix[rowIndex].length + 1; k++) { for (k = 0; k < matrix[rowIndex].length + 1; k++) {
if (typeof(matrix[rowIndex][k]) === 'undefined') { if (typeof matrix[rowIndex][k] === 'undefined') {
firstAvailCol = k; firstAvailCol = k;
break; break;
} }
@ -1317,7 +1319,7 @@
// add data-column // add data-column
$cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex $cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex
for (k = rowIndex; k < rowIndex + rowSpan; k++) { for (k = rowIndex; k < rowIndex + rowSpan; k++) {
if (typeof(matrix[k]) === 'undefined') { if (typeof matrix[k] === 'undefined') {
matrix[k] = []; matrix[k] = [];
} }
matrixrow = matrix[k]; matrixrow = matrix[k];
@ -1333,10 +1335,10 @@
// *** Process table *** // *** Process table ***
// add processing indicator // add processing indicator
ts.isProcessing = function(table, toggle, $ths) { ts.isProcessing = function(table, toggle, $ths) {
table = $(table); $table = $(table);
var c = table[0].config, var c = $table[0].config,
// default to all headers // default to all headers
$h = $ths || table.find('.' + ts.css.header); $h = $ths || $table.find('.' + ts.css.header);
if (toggle) { if (toggle) {
// don't use sortList if custom $ths used // don't use sortList if custom $ths used
if (typeof $ths !== 'undefined' && c.sortList.length > 0) { if (typeof $ths !== 'undefined' && c.sortList.length > 0) {
@ -1346,9 +1348,9 @@
return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0; return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0;
}); });
} }
table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing); $table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing);
} else { } else {
table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing); $table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing);
} }
}; };
@ -1478,8 +1480,8 @@
$f = $t.find('tfoot:first > tr').children('th, td'); $f = $t.find('tfoot:first > tr').children('th, td');
if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) { if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) {
// reapply uitheme classes, in case we want to maintain appearance // reapply uitheme classes, in case we want to maintain appearance
$t.trigger('applyWidgetId', ['uitheme']); $t.trigger('applyWidgetId', [ 'uitheme' ]);
$t.trigger('applyWidgetId', ['zebra']); $t.trigger('applyWidgetId', [ 'zebra' ]);
} }
// remove widget added rows, just in case // remove widget added rows, just in case
$h.find('tr').not($r).remove(); $h.find('tr').not($r).remove();
@ -1491,7 +1493,7 @@
.removeData('tablesorter') .removeData('tablesorter')
.unbind( events.replace(/\s+/g, ' ') ); .unbind( events.replace(/\s+/g, ' ') );
c.$headers.add($f) c.$headers.add($f)
.removeClass( [ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone].join(' ') ) .removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
.removeAttr('data-column') .removeAttr('data-column')
.removeAttr('aria-label') .removeAttr('aria-label')
.attr('aria-disabled', 'true'); .attr('aria-disabled', 'true');
@ -1697,8 +1699,8 @@
}; };
ts.hasWidget = function(table, name){ ts.hasWidget = function(table, name){
table = $(table); $table = $(table);
return table.length && table[0].config && table[0].config.widgetInit[name] || false; return $table.length && $table[0].config && $table[0].config.widgetInit[name] || false;
}; };
ts.getWidgetById = function(name) { ts.getWidgetById = function(name) {
@ -1738,7 +1740,7 @@
if (c.debug) { time = new Date(); } if (c.debug) { time = new Date(); }
// look for widgets to apply from in table class // look for widgets to apply from in table class
// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget // stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' )+ '\\s', 'g' ); wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' );
if ( tableClass.match( wd ) ) { if ( tableClass.match( wd ) ) {
// extract out the widget id from the table class (widget id's can include dashes) // extract out the widget id from the table class (widget id's can include dashes)
w = tableClass.match( wd ); w = tableClass.match( wd );
@ -1946,13 +1948,13 @@
typeof table !== 'undefined' ? table : true; typeof table !== 'undefined' ? table : true;
if (t) { if (t) {
// US Format - 1,234,567.89 -> 1234567.89 // US Format - 1,234,567.89 -> 1234567.89
s = s.replace(/,/g,''); s = s.replace(/,/g, '');
} else { } else {
// German Format = 1.234.567,89 -> 1234567.89 // German Format = 1.234.567,89 -> 1234567.89
// French Format = 1 234 567,89 -> 1234567.89 // French Format = 1 234 567,89 -> 1234567.89
s = s.replace(/[\s|\.]/g,'').replace(/,/g,'.'); s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.');
} }
if(/^\s*\([.\d]+\)/.test(s)) { if (/^\s*\([.\d]+\)/.test(s)) {
// make (#) into a negative number -> (10) = -10 // make (#) into a negative number -> (10) = -10
s = s.replace(/^\s*\(([.\d]+)\)/, '-$1'); s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
} }
@ -2020,7 +2022,7 @@
ts.addParser({ ts.addParser({
id: 'currency', id: 'currency',
is: function(s) { is: function(s) {
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g,'')); // £$€¤¥¢ return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g, '')); // £$€¤¥¢
}, },
format: function(s, table) { format: function(s, table) {
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table); var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
@ -2095,7 +2097,7 @@
id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd' id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
is: function(s) { is: function(s) {
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included // 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) { format: function(s, table, cell, cellIndex) {
if (s) { if (s) {

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! Parser: distance */ /*! Parser: distance */
!function(a){"use strict";var b=a.tablesorter;b.symbolRegex=/[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g,b.processFractions=function(c,d){if(c){var e,f=0;c=a.trim(c.replace(/\"/,"")),/\s/.test(c)&&(f=b.formatFloat(c.split(" ")[0],d),c=a.trim(c.substring(c.indexOf(" "),c.length))),/\//g.test(c)?(e=c.split("/"),c=f+parseInt(e[0],10)/parseInt(e[1]||1,10)):b.symbolRegex.test(c)&&(c=f+c.replace(b.symbolRegex,function(a){return{"⅛":".125","⅜":".375","⅝":".625","⅞":".875","¼":".25","½":".5","¾":".75"}[a]}))}return c||0},a.tablesorter.addParser({id:"distance",is:function(){return!1},format:function(a,c){if(""===a)return"";var d=/^\s*\S*(\s+\S+)?\s*\'/.test(a)?a.split("'"):[0,a],e=b.processFractions(d[0],c),f=b.processFractions(d[1],c);return/[\'\"]/.test(a)?parseFloat(e)+(parseFloat(f)/12||0):parseFloat(e)+parseFloat(f)},type:"numeric"})}(jQuery); !function(a){"use strict";var b=a.tablesorter;b.symbolRegex=/[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g,b.processFractions=function(c,d){if(c){var e,f=0;c=a.trim(c.replace(/\"/,"")),/\s/.test(c)&&(f=b.formatFloat(c.split(" ")[0],d),c=a.trim(c.substring(c.indexOf(" "),c.length))),/\//g.test(c)?(e=c.split("/"),c=f+parseInt(e[0],10)/parseInt(e[1]||1,10)):b.symbolRegex.test(c)&&(c=f+c.replace(b.symbolRegex,function(a){return{"⅛":".125","⅜":".375","⅝":".625","⅞":".875","¼":".25","½":".5","¾":".75"}[a]}))}return c||0},a.tablesorter.addParser({id:"distance",is:function(){return!1},format:function(a,c){if(""===a)return"";var d=/^\s*\S*(\s+\S+)?\s*\'/.test(a)?a.split(/\'/):[0,a],e=b.processFractions(d[0],c),f=b.processFractions(d[1],c);return/[\'\"]/.test(a)?parseFloat(e)+(parseFloat(f)/12||0):parseFloat(e)+parseFloat(f)},type:"numeric"})}(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -188,7 +188,7 @@
// node could be a jquery object // node could be a jquery object
// http://jsperf.com/jquery-vs-instanceof-jquery/2 // http://jsperf.com/jquery-vs-instanceof-jquery/2
$node = node.jquery ? node : $(node); $node = node.jquery ? node : $(node);
if (typeof(t) === 'string') { if (typeof t === 'string') {
// check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow! // check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow!
// http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/ // http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/
if ( t === 'basic' && typeof ( te = $node.attr(c.textAttribute) ) !== 'undefined' ) { if ( t === 'basic' && typeof ( te = $node.attr(c.textAttribute) ) !== 'undefined' ) {
@ -196,7 +196,7 @@
} }
return $.trim( node.textContent || $node.text() ); return $.trim( node.textContent || $node.text() );
} else { } else {
if (typeof(t) === 'function') { if (typeof t === 'function') {
return $.trim( t($node[0], c.table, cellIndex) ); return $.trim( t($node[0], c.table, cellIndex) );
} else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') { } else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') {
return $.trim( te($node[0], c.table, cellIndex) ); return $.trim( te($node[0], c.table, cellIndex) );
@ -256,7 +256,7 @@
// make sure txt is a string (extractor may have converted it) // make sure txt is a string (extractor may have converted it)
parser.format( '' + txt, c.table, cell, colIndex ); parser.format( '' + txt, c.table, cell, colIndex );
if ( c.ignoreCase && typeof val === 'string' ) { if ( c.ignoreCase && typeof val === 'string' ) {
val = val.toLowerCase(); val = val.toLowerCase();
} }
} }
return val; return val;
@ -500,20 +500,22 @@
// set up header template // set up header template
t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i); t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i);
if (c.onRenderTemplate) { if (c.onRenderTemplate) {
h = c.onRenderTemplate.apply($t, [index, t]); h = c.onRenderTemplate.apply( $t, [ index, t ] );
if (h && typeof h === 'string') { t = h; } // only change t if something is returned if (h && typeof h === 'string') { t = h; } // only change t if something is returned
} }
$t.html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner $t.html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner
} }
if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index, c, c.$table]); } if (c.onRenderHeader) { c.onRenderHeader.apply( $t, [ index, c, c.$table ] ); }
// *** remove this.column value if no conflicts found // *** remove this.column value if no conflicts found
elem.column = parseInt( $t.attr('data-column'), 10); elem.column = parseInt( $t.attr('data-column'), 10);
elem.order = formatSortingOrder( ts.getData($t, ch, 'sortInitialOrder') || c.sortInitialOrder ) ? [1,0,2] : [0,1,2]; elem.order = formatSortingOrder( ts.getData( $t, ch, 'sortInitialOrder' ) || c.sortInitialOrder ) ?
[ 1, 0, 2 ] : // desc, asc, unsorted
[ 0, 1, 2 ]; // asc, desc, unsorted
elem.count = -1; // set to -1 because clicking on the header automatically adds one elem.count = -1; // set to -1 because clicking on the header automatically adds one
elem.lockedOrder = false; elem.lockedOrder = false;
lock = ts.getData($t, ch, 'lockedOrder') || false; lock = ts.getData($t, ch, 'lockedOrder') || false;
if (typeof lock !== 'undefined' && lock !== false) { if (typeof lock !== 'undefined' && lock !== false) {
elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [1,1,1] : [0,0,0]; elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [ 1, 1, 1 ] : [ 0, 0, 0 ];
} }
$t.addClass(ts.css.header + ' ' + c.cssHeader); $t.addClass(ts.css.header + ' ' + c.cssHeader);
// add cell to headerList // add cell to headerList
@ -583,9 +585,9 @@
list = c.sortList, list = c.sortList,
len = list.length, len = list.length,
none = ts.css.sortNone + ' ' + c.cssNone, none = ts.css.sortNone + ' ' + c.cssNone,
css = [ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc], css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ], cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
aria = ['ascending', 'descending'], aria = [ 'ascending', 'descending' ],
// find the footer // find the footer
$t = $(table).find('tfoot tr').children() $t = $(table).find('tfoot tr').children()
.add( $( c.namespace + '_extra_headers' ) ) .add( $( c.namespace + '_extra_headers' ) )
@ -655,7 +657,7 @@
dir = ('' + val[1]).match(/^(1|d|s|o|n)/); dir = ('' + val[1]).match(/^(1|d|s|o|n)/);
dir = dir ? dir[0] : ''; dir = dir ? dir[0] : '';
// 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext // 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext
switch(dir) { switch (dir) {
case '1': case 'd': // descending case '1': case 'd': // descending
dir = 1; dir = 1;
break; break;
@ -731,11 +733,11 @@
// add column to sort list // add column to sort list
order = cell.order[cell.count]; order = cell.order[cell.count];
if (order < 2) { if (order < 2) {
c.sortList.push([indx, order]); c.sortList.push([ indx, order ]);
// add other columns if header spans across multiple // add other columns if header spans across multiple
if (cell.colSpan > 1) { if (cell.colSpan > 1) {
for (col = 1; col < cell.colSpan; col++) { for (col = 1; col < cell.colSpan; col++) {
c.sortList.push([indx + col, order]); c.sortList.push([ indx + col, order ]);
} }
} }
} }
@ -746,7 +748,7 @@
for (col = 0; col < c.sortAppend.length; col++) { for (col = 0; col < c.sortAppend.length; col++) {
s = ts.isValueInArray(c.sortAppend[col][0], c.sortList); s = ts.isValueInArray(c.sortAppend[col][0], c.sortList);
if (s >= 0) { if (s >= 0) {
c.sortList.splice(s,1); c.sortList.splice(s, 1);
} }
} }
} }
@ -760,7 +762,7 @@
// order.count seems to be incorrect when compared to cell.count // order.count seems to be incorrect when compared to cell.count
s[1] = order.order[cell.count]; s[1] = order.order[cell.count];
if (s[1] === 2) { if (s[1] === 2) {
c.sortList.splice(col,1); c.sortList.splice(col, 1);
order.count = -1; order.count = -1;
} }
} }
@ -769,11 +771,11 @@
// add column to sort list array // add column to sort list array
order = cell.order[cell.count]; order = cell.order[cell.count];
if (order < 2) { if (order < 2) {
c.sortList.push([indx, order]); c.sortList.push([ indx, order ]);
// add other columns if header spans across multiple // add other columns if header spans across multiple
if (cell.colSpan > 1) { if (cell.colSpan > 1) {
for (col = 1; col < cell.colSpan; col++) { for (col = 1; col < cell.colSpan; col++) {
c.sortList.push([indx + col, order]); c.sortList.push([ indx + col, order ]);
} }
} }
} }
@ -847,10 +849,10 @@
x = dir ? a : b; x = dir ? a : b;
y = dir ? b : a; y = dir ? b : a;
// text sort function // text sort function
if (typeof(cts) === 'function') { if (typeof cts === 'function') {
// custom OVERALL text sorter // custom OVERALL text sorter
sort = cts(x[col], y[col], dir, col, table); sort = cts(x[col], y[col], dir, col, table);
} else if (typeof(cts) === 'object' && cts.hasOwnProperty(col)) { } else if (typeof cts === 'object' && cts.hasOwnProperty(col)) {
// custom text sorter for a SPECIFIC COLUMN // custom text sorter for a SPECIFIC COLUMN
sort = cts[col](x[col], y[col], dir, col, table); sort = cts[col](x[col], y[col], dir, col, table);
} else { } else {
@ -883,14 +885,14 @@
// this will catch spamming of the updateCell method // this will catch spamming of the updateCell method
if (resrt !== false && !c.serverSideSorting && !c.table.isProcessing) { if (resrt !== false && !c.serverSideSorting && !c.table.isProcessing) {
if (sl.length) { if (sl.length) {
c.$table.trigger('sorton', [sl, function(){ c.$table.trigger('sorton', [ sl, function(){
resortComplete(c, callback); resortComplete(c, callback);
}, true]); }, true ]);
} else { } else {
c.$table.trigger('sortReset', [function(){ c.$table.trigger('sortReset', [ function(){
resortComplete(c, callback); resortComplete(c, callback);
ts.applyWidget(c.table, false); ts.applyWidget(c.table, false);
}]); } ]);
} }
} else { } else {
resortComplete(c, callback); resortComplete(c, callback);
@ -1090,10 +1092,10 @@
ts.construct = function(settings) { ts.construct = function(settings) {
return this.each(function() { return this.each(function() {
var table = this, var table = this,
// merge & extend config options // merge & extend config options
c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods); c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods);
// save initial settings // save initial settings
c.originalSettings = settings; c.originalSettings = settings;
// create a table from data (build table widget) // create a table from data (build table widget)
if (!table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE') { if (!table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE') {
// return the table (in case the original target is the table's container) // return the table (in case the original target is the table's container)
@ -1148,7 +1150,7 @@
c.namespace = '.tablesorter' + Math.random().toString(16).slice(2); c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
} else { } else {
// make sure namespace starts with a period & doesn't have weird characters // make sure namespace starts with a period & doesn't have weird characters
c.namespace = '.' + c.namespace.replace(/\W/g,''); c.namespace = '.' + c.namespace.replace(/\W/g, '');
} }
c.$table.children().children('tr').attr('role', 'row'); c.$table.children().children('tr').attr('role', 'row');
@ -1192,7 +1194,7 @@
ts.applyWidget(table, true); ts.applyWidget(table, true);
// if user has supplied a sort list to constructor // if user has supplied a sort list to constructor
if (c.sortList.length > 0) { if (c.sortList.length > 0) {
$table.trigger('sorton', [c.sortList, {}, !c.initWidgets, true]); $table.trigger('sorton', [ c.sortList, {}, !c.initWidgets, true ]);
} else { } else {
setHeadersCss(table); setHeadersCss(table);
if (c.initWidgets) { if (c.initWidgets) {
@ -1231,22 +1233,22 @@
table = $(table)[0]; table = $(table)[0];
var overallWidth, percent, $tbodies, len, index, var overallWidth, percent, $tbodies, len, index,
c = table.config, c = table.config,
colgroup = c.$table.children('colgroup'); $colgroup = c.$table.children('colgroup');
// remove plugin-added colgroup, in case we need to refresh the widths // remove plugin-added colgroup, in case we need to refresh the widths
if (colgroup.length && colgroup.hasClass(ts.css.colgroup)) { if ($colgroup.length && $colgroup.hasClass(ts.css.colgroup)) {
colgroup.remove(); $colgroup.remove();
} }
if (c.widthFixed && c.$table.children('colgroup').length === 0) { if (c.widthFixed && c.$table.children('colgroup').length === 0) {
colgroup = $('<colgroup class="' + ts.css.colgroup + '">'); $colgroup = $('<colgroup class="' + ts.css.colgroup + '">');
overallWidth = c.$table.width(); overallWidth = c.$table.width();
// only add col for visible columns - fixes #371 // only add col for visible columns - fixes #371
$tbodies = c.$tbodies.find('tr:first').children(':visible'); //.each(function() $tbodies = c.$tbodies.find('tr:first').children(':visible'); // .each(function()
len = $tbodies.length; len = $tbodies.length;
for ( index = 0; index < len; index++ ) { for ( index = 0; index < len; index++ ) {
percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%'; percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%';
colgroup.append( $('<col>').css('width', percent) ); $colgroup.append( $('<col>').css('width', percent) );
} }
c.$table.prepend(colgroup); c.$table.prepend($colgroup);
} }
}; };
@ -1293,12 +1295,12 @@
cellId = rowIndex + '-' + $cell.index(); cellId = rowIndex + '-' + $cell.index();
rowSpan = cell.rowSpan || 1; rowSpan = cell.rowSpan || 1;
colSpan = cell.colSpan || 1; colSpan = cell.colSpan || 1;
if (typeof(matrix[rowIndex]) === 'undefined') { if (typeof matrix[rowIndex] === 'undefined') {
matrix[rowIndex] = []; matrix[rowIndex] = [];
} }
// Find first available column in the first row // Find first available column in the first row
for (k = 0; k < matrix[rowIndex].length + 1; k++) { for (k = 0; k < matrix[rowIndex].length + 1; k++) {
if (typeof(matrix[rowIndex][k]) === 'undefined') { if (typeof matrix[rowIndex][k] === 'undefined') {
firstAvailCol = k; firstAvailCol = k;
break; break;
} }
@ -1307,7 +1309,7 @@
// add data-column // add data-column
$cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex $cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex
for (k = rowIndex; k < rowIndex + rowSpan; k++) { for (k = rowIndex; k < rowIndex + rowSpan; k++) {
if (typeof(matrix[k]) === 'undefined') { if (typeof matrix[k] === 'undefined') {
matrix[k] = []; matrix[k] = [];
} }
matrixrow = matrix[k]; matrixrow = matrix[k];
@ -1323,10 +1325,10 @@
// *** Process table *** // *** Process table ***
// add processing indicator // add processing indicator
ts.isProcessing = function(table, toggle, $ths) { ts.isProcessing = function(table, toggle, $ths) {
table = $(table); $table = $(table);
var c = table[0].config, var c = $table[0].config,
// default to all headers // default to all headers
$h = $ths || table.find('.' + ts.css.header); $h = $ths || $table.find('.' + ts.css.header);
if (toggle) { if (toggle) {
// don't use sortList if custom $ths used // don't use sortList if custom $ths used
if (typeof $ths !== 'undefined' && c.sortList.length > 0) { if (typeof $ths !== 'undefined' && c.sortList.length > 0) {
@ -1336,9 +1338,9 @@
return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0; return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0;
}); });
} }
table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing); $table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing);
} else { } else {
table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing); $table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing);
} }
}; };
@ -1468,8 +1470,8 @@
$f = $t.find('tfoot:first > tr').children('th, td'); $f = $t.find('tfoot:first > tr').children('th, td');
if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) { if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) {
// reapply uitheme classes, in case we want to maintain appearance // reapply uitheme classes, in case we want to maintain appearance
$t.trigger('applyWidgetId', ['uitheme']); $t.trigger('applyWidgetId', [ 'uitheme' ]);
$t.trigger('applyWidgetId', ['zebra']); $t.trigger('applyWidgetId', [ 'zebra' ]);
} }
// remove widget added rows, just in case // remove widget added rows, just in case
$h.find('tr').not($r).remove(); $h.find('tr').not($r).remove();
@ -1481,7 +1483,7 @@
.removeData('tablesorter') .removeData('tablesorter')
.unbind( events.replace(/\s+/g, ' ') ); .unbind( events.replace(/\s+/g, ' ') );
c.$headers.add($f) c.$headers.add($f)
.removeClass( [ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone].join(' ') ) .removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
.removeAttr('data-column') .removeAttr('data-column')
.removeAttr('aria-label') .removeAttr('aria-label')
.attr('aria-disabled', 'true'); .attr('aria-disabled', 'true');
@ -1687,8 +1689,8 @@
}; };
ts.hasWidget = function(table, name){ ts.hasWidget = function(table, name){
table = $(table); $table = $(table);
return table.length && table[0].config && table[0].config.widgetInit[name] || false; return $table.length && $table[0].config && $table[0].config.widgetInit[name] || false;
}; };
ts.getWidgetById = function(name) { ts.getWidgetById = function(name) {
@ -1728,7 +1730,7 @@
if (c.debug) { time = new Date(); } if (c.debug) { time = new Date(); }
// look for widgets to apply from in table class // look for widgets to apply from in table class
// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget // stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' )+ '\\s', 'g' ); wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' );
if ( tableClass.match( wd ) ) { if ( tableClass.match( wd ) ) {
// extract out the widget id from the table class (widget id's can include dashes) // extract out the widget id from the table class (widget id's can include dashes)
w = tableClass.match( wd ); w = tableClass.match( wd );
@ -1936,13 +1938,13 @@
typeof table !== 'undefined' ? table : true; typeof table !== 'undefined' ? table : true;
if (t) { if (t) {
// US Format - 1,234,567.89 -> 1234567.89 // US Format - 1,234,567.89 -> 1234567.89
s = s.replace(/,/g,''); s = s.replace(/,/g, '');
} else { } else {
// German Format = 1.234.567,89 -> 1234567.89 // German Format = 1.234.567,89 -> 1234567.89
// French Format = 1 234 567,89 -> 1234567.89 // French Format = 1 234 567,89 -> 1234567.89
s = s.replace(/[\s|\.]/g,'').replace(/,/g,'.'); s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.');
} }
if(/^\s*\([.\d]+\)/.test(s)) { if (/^\s*\([.\d]+\)/.test(s)) {
// make (#) into a negative number -> (10) = -10 // make (#) into a negative number -> (10) = -10
s = s.replace(/^\s*\(([.\d]+)\)/, '-$1'); s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
} }
@ -2010,7 +2012,7 @@
ts.addParser({ ts.addParser({
id: 'currency', id: 'currency',
is: function(s) { is: function(s) {
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g,'')); // £$€¤¥¢ return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g, '')); // £$€¤¥¢
}, },
format: function(s, table) { format: function(s, table) {
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table); var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
@ -2085,7 +2087,7 @@
id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd' id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
is: function(s) { is: function(s) {
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included // 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) { format: function(s, table, cell, cellIndex) {
if (s) { if (s) {

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*! Parser: Extract out date - updated 10/26/2014 (v2.18.0) */ /*! Parser: Extract out date - updated 10/26/2014 (v2.18.0) */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
"use strict"; 'use strict';
var regex = { var regex = {
usLong : /[A-Z]{3,10}\.?\s+\d{1,2},?\s+(?:\d{4})(?:\s+\d{1,2}:\d{2}(?::\d{2})?(?:\s+[AP]M)?)?/i, usLong : /[A-Z]{3,10}\.?\s+\d{1,2},?\s+(?:\d{4})(?:\s+\d{1,2}:\d{2}(?::\d{2})?(?:\s+[AP]M)?)?/i,
@ -15,10 +15,10 @@
}; };
/*! extract US Long Date *//* (ignore any other text) /*! extract US Long Date *//* (ignore any other text)
* e.g. "Sue's Birthday! Jun 26, 2004 7:22 AM (8# 2oz)" * e.g. 'Sue's Birthday! Jun 26, 2004 7:22 AM (8# 2oz)'
* demo: http://jsfiddle.net/Mottie/abkNM/4165/ */ * demo: http://jsfiddle.net/Mottie/abkNM/4165/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractUSLongDate", id: 'extractUSLongDate',
is: function () { is: function () {
// don't auto detect this parser // don't auto detect this parser
return false; return false;
@ -32,67 +32,67 @@
} }
return s; return s;
}, },
type: "numeric" type: 'numeric'
}); });
/*! extract MMDDYYYY *//* (ignore any other text) /*! extract MMDDYYYY *//* (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/4166/ */ * demo: http://jsfiddle.net/Mottie/abkNM/4166/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractMMDDYYYY", id: 'extractMMDDYYYY',
is: function () { is: function () {
// don't auto detect this parser // don't auto detect this parser
return false; return false;
}, },
format: function (s) { format: function (s) {
var date, var date,
str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.mdy) : s; str = s ? s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/').match(regex.mdy) : s;
if (str) { if (str) {
date = new Date( str[0] ); date = new Date( str[0] );
return date instanceof Date && isFinite(date) ? date.getTime() : s; return date instanceof Date && isFinite(date) ? date.getTime() : s;
} }
return s; return s;
}, },
type: "numeric" type: 'numeric'
}); });
/*! extract DDMMYYYY *//* (ignore any other text) /*! extract DDMMYYYY *//* (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/4167/ */ * demo: http://jsfiddle.net/Mottie/abkNM/4167/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractDDMMYYYY", id: 'extractDDMMYYYY',
is: function () { is: function () {
// don't auto detect this parser // don't auto detect this parser
return false; return false;
}, },
format: function (s) { format: function (s) {
var date, var date,
str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.dmy) : s; str = s ? s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/').match(regex.dmy) : s;
if (str) { if (str) {
date = new Date( str[0].replace(regex.dmyreplace, "$2/$1/$3") ); date = new Date( str[0].replace(regex.dmyreplace, '$2/$1/$3') );
return date instanceof Date && isFinite(date) ? date.getTime() : s; return date instanceof Date && isFinite(date) ? date.getTime() : s;
} }
return s; return s;
}, },
type: "numeric" type: 'numeric'
}); });
/*! extract YYYYMMDD *//* (ignore any other text) /*! extract YYYYMMDD *//* (ignore any other text)
* demo: http://jsfiddle.net/Mottie/abkNM/4168/ */ * demo: http://jsfiddle.net/Mottie/abkNM/4168/ */
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "extractYYYYMMDD", id: 'extractYYYYMMDD',
is: function () { is: function () {
// don't auto detect this parser // don't auto detect this parser
return false; return false;
}, },
format: function (s) { format: function (s) {
var date, var date,
str = s ? s.replace(/\s+/g," ").replace(/[\-.,]/g, "/").match(regex.ymd) : s; str = s ? s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/').match(regex.ymd) : s;
if (str) { if (str) {
date = new Date( str[0].replace(regex.ymdreplace, "$2/$3/$1") ); date = new Date( str[0].replace(regex.ymdreplace, '$2/$3/$1') );
return date instanceof Date && isFinite(date) ? date.getTime() : s; return date instanceof Date && isFinite(date) ? date.getTime() : s;
} }
return s; return s;
}, },
type: "numeric" type: 'numeric'
}); });
})(jQuery); })(jQuery);

View File

@ -6,7 +6,7 @@
*/ */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var iso8601date = /^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/; var iso8601date = /^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/;

View File

@ -2,7 +2,7 @@
/* Demo: http://jsfiddle.net/Mottie/abkNM/4169/ */ /* Demo: http://jsfiddle.net/Mottie/abkNM/4169/ */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.dates = $.extend({}, ts.dates, { ts.dates = $.extend({}, ts.dates, {
@ -12,7 +12,7 @@
ts.dates.monthLower = ts.dates.monthCased.join(',').toLocaleLowerCase().split(','); ts.dates.monthLower = ts.dates.monthCased.join(',').toLocaleLowerCase().split(',');
ts.addParser({ ts.addParser({
id: "month", id: 'month',
is: function(){ is: function(){
return false; return false;
}, },
@ -20,7 +20,7 @@
if (s) { if (s) {
var j = -1, c = table.config, var j = -1, c = table.config,
n = c.ignoreCase ? s.toLocaleLowerCase() : s; n = c.ignoreCase ? s.toLocaleLowerCase() : s;
$.each(ts.dates[ 'month' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){ $.each(ts.dates[ 'month' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i, v){
if (j < 0 && n.match(v)) { if (j < 0 && n.match(v)) {
j = i; j = i;
return false; return false;
@ -32,7 +32,7 @@
} }
return s; return s;
}, },
type: "numeric" type: 'numeric'
}); });
})(jQuery); })(jQuery);

View File

@ -2,7 +2,7 @@
/* Include the 'widget-filter-type-insideRange.js' to filter ranges */ /* Include the 'widget-filter-type-insideRange.js' to filter ranges */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
'use strict'; 'use strict';
var regex = { var regex = {
mdy : /(\d{1,2}[-\s]\d{1,2}[-\s]\d{4}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/gi, mdy : /(\d{1,2}[-\s]\d{1,2}[-\s]\d{4}(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?)/gi,

View File

@ -2,7 +2,7 @@
/* Demo: http://mottie.github.io/tablesorter/docs/example-parsers-dates.html */ /* Demo: http://mottie.github.io/tablesorter/docs/example-parsers-dates.html */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
"use strict"; 'use strict';
// Make the date be within +/- range of the 2 digit year // Make the date be within +/- range of the 2 digit year
// so if the current year is 2020, and the 2 digit year is 80 (2080 - 2020 > 50), it becomes 1980 // so if the current year is 2020, and the 2 digit year is 80 (2080 - 2020 > 50), it becomes 1980
@ -23,7 +23,7 @@
var y, rng, var y, rng,
n = s n = s
// replace separators // replace separators
.replace(/\s+/g," ").replace(/[-.,]/g, "/") .replace(/\s+/g, ' ').replace(/[-.,]/g, '/')
// reformat xx/xx/xx to mm/dd/19yy; // reformat xx/xx/xx to mm/dd/19yy;
.replace(regex, format), .replace(regex, format),
d = new Date(n); d = new Date(n);
@ -31,7 +31,7 @@
y = d.getFullYear(); y = d.getFullYear();
rng = table && table.config.dateRange || range; rng = table && table.config.dateRange || range;
// if date > 50 years old (set range), add 100 years // if date > 50 years old (set range), add 100 years
// this will work when people start using "50" and mean "2050" // this will work when people start using '50' and mean '2050'
while (now - y > rng) { while (now - y > rng) {
y += 100; y += 100;
} }
@ -42,39 +42,39 @@
}; };
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "ddmmyy", id: 'ddmmyy',
is: function() { is: function() {
return false; return false;
}, },
format: function(s, table) { format: function(s, table) {
// reformat dd/mm/yy to mm/dd/19yy; // reformat dd/mm/yy to mm/dd/19yy;
return ts.formatDate(s, ts.dates.regxxxxyy, "$2/$1/19$3", table); return ts.formatDate(s, ts.dates.regxxxxyy, '$2/$1/19$3', table);
}, },
type: "numeric" type: 'numeric'
}); });
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "mmddyy", id: 'mmddyy',
is: function() { is: function() {
return false; return false;
}, },
format: function(s, table) { format: function(s, table) {
// reformat mm/dd/yy to mm/dd/19yy // reformat mm/dd/yy to mm/dd/19yy
return ts.formatDate(s, ts.dates.regxxxxyy, "$1/$2/19$3", table); return ts.formatDate(s, ts.dates.regxxxxyy, '$1/$2/19$3', table);
}, },
type: "numeric" type: 'numeric'
}); });
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "yymmdd", id: 'yymmdd',
is: function() { is: function() {
return false; return false;
}, },
format: function(s, table) { format: function(s, table) {
// reformat yy/mm/dd to mm/dd/19yy // reformat yy/mm/dd to mm/dd/19yy
return ts.formatDate(s, ts.dates.regyyxxxx, "$2/$3/19$1", table); return ts.formatDate(s, ts.dates.regyyxxxx, '$2/$3/19$1', table);
}, },
type: "numeric" type: 'numeric'
}); });
})(jQuery); })(jQuery);

View File

@ -2,7 +2,7 @@
/* Demo: http://jsfiddle.net/Mottie/abkNM/4169/ */ /* Demo: http://jsfiddle.net/Mottie/abkNM/4169/ */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.dates = $.extend({}, ts.dates, { ts.dates = $.extend({}, ts.dates, {
@ -12,7 +12,7 @@
ts.dates.weekdayLower = ts.dates.weekdayCased.join(',').toLocaleLowerCase().split(','); ts.dates.weekdayLower = ts.dates.weekdayCased.join(',').toLocaleLowerCase().split(',');
ts.addParser({ ts.addParser({
id: "weekday", id: 'weekday',
is: function(){ is: function(){
return false; return false;
}, },
@ -20,7 +20,7 @@
if (s) { if (s) {
var j = -1, c = table.config; var j = -1, c = table.config;
s = c.ignoreCase ? s.toLocaleLowerCase() : s; s = c.ignoreCase ? s.toLocaleLowerCase() : s;
$.each(ts.dates[ 'weekday' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){ $.each(ts.dates[ 'weekday' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i, v){
if (j < 0 && s.match(v)) { if (j < 0 && s.match(v)) {
j = i; j = i;
return false; return false;
@ -32,7 +32,7 @@
} }
return s; return s;
}, },
type: "numeric" type: 'numeric'
}); });
})(jQuery); })(jQuery);

View File

@ -2,7 +2,7 @@
/* Extract dates using popular natural language date parsers */ /* Extract dates using popular natural language date parsers */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
'use strict'; 'use strict';
/*! Sugar (http://sugarjs.com/dates#comparing_dates) */ /*! Sugar (http://sugarjs.com/dates#comparing_dates) */
/* demo: http://jsfiddle.net/Mottie/abkNM/4163/ */ /* demo: http://jsfiddle.net/Mottie/abkNM/4163/ */

View File

@ -1,7 +1,7 @@
/*! Parser: duration & countdown - updated 2/7/2015 (v2.19.0) */ /*! Parser: duration & countdown - updated 2/7/2015 (v2.19.0) */
/*jshint jquery:true, unused:false */ /*jshint jquery:true, unused:false */
;(function($){ ;(function($){
'use strict'; 'use strict';
// If any number > 9999, then set table.config.durationLength = 5 // If any number > 9999, then set table.config.durationLength = 5
// The below regex matches this duration example: 1y 23d 12h 44m 9s // The below regex matches this duration example: 1y 23d 12h 44m 9s

View File

@ -5,21 +5,21 @@
*/ */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.symbolRegex = /[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g; ts.symbolRegex = /[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g;
ts.processFractions = function(n, table) { ts.processFractions = function(n, table) {
if (n) { if (n) {
var t, p = 0; var t, p = 0;
n = $.trim(n.replace(/\"/,'')); n = $.trim(n.replace(/\"/, ''));
// look for a space in the first part of the number: "10 3/4" and save the "10" // look for a space in the first part of the number: '10 3/4' and save the '10'
if (/\s/.test(n)) { if (/\s/.test(n)) {
p = ts.formatFloat(n.split(' ')[0], table); p = ts.formatFloat(n.split(' ')[0], table);
// remove stuff to the left of the space // remove stuff to the left of the space
n = $.trim(n.substring(n.indexOf(' '), n.length)); n = $.trim(n.substring(n.indexOf(' '), n.length));
} }
// look for a "/" to calculate fractions // look for a '/' to calculate fractions
if (/\//g.test(n)) { if (/\//g.test(n)) {
t = n.split('/'); t = n.split('/');
// turn 3/4 into .75; make sure we don't divide by zero // turn 3/4 into .75; make sure we don't divide by zero
@ -52,10 +52,10 @@
if (s === '') { return ''; } if (s === '') { return ''; }
// look for feet symbol = ' // look for feet symbol = '
// very generic test to catch 1.1', 1 1/2' and 1½' // very generic test to catch 1.1', 1 1/2' and 1½'
var d = (/^\s*\S*(\s+\S+)?\s*\'/.test(s)) ? s.split("'") : [0,s], var d = (/^\s*\S*(\s+\S+)?\s*\'/.test(s)) ? s.split(/\'/) : [ 0, s ],
f = ts.processFractions(d[0], table), // feet f = ts.processFractions(d[0], table), // feet
i = ts.processFractions(d[1], table); // inches i = ts.processFractions(d[1], table); // inches
return (/[\'\"]/).test(s) ? parseFloat(f) + (parseFloat(i)/12 || 0) : parseFloat(f) + parseFloat(i); return (/[\'\"]/).test(s) ? parseFloat(f) + (parseFloat(i) / 12 || 0) : parseFloat(f) + parseFloat(i);
}, },
type: 'numeric' type: 'numeric'
}); });

View File

@ -4,33 +4,33 @@
*/ */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
// basic list from http://en.wikipedia.org/wiki/List_of_file_formats // basic list from http://en.wikipedia.org/wiki/List_of_file_formats
// To add a custom equivalent, define: // To add a custom equivalent, define:
// $.tablesorter.fileTypes.equivalents['xx'] = "A|B|C"; // $.tablesorter.fileTypes.equivalents['xx'] = 'A|B|C';
$.tablesorter.fileTypes = { $.tablesorter.fileTypes = {
// divides filetype extensions in the equivalent list below // divides filetype extensions in the equivalent list below
separator : '|', separator : '|',
equivalents : { equivalents : {
"3D Image" : "3dm|3ds|dwg|max|obj", '3D Image' : '3dm|3ds|dwg|max|obj',
"Audio" : "aif|aac|ape|flac|la|m4a|mid|midi|mp2|mp3|ogg|ra|raw|rm|wav|wma", 'Audio' : 'aif|aac|ape|flac|la|m4a|mid|midi|mp2|mp3|ogg|ra|raw|rm|wav|wma',
"Compressed" : "7z|bin|cab|cbr|gz|gzip|iso|lha|lz|rar|tar|tgz|zip|zipx|zoo", 'Compressed' : '7z|bin|cab|cbr|gz|gzip|iso|lha|lz|rar|tar|tgz|zip|zipx|zoo',
"Database" : "csv|dat|db|dbf|json|ldb|mdb|myd|pdb|sql|tsv|wdb|wmdb|xlr|xls|xlsx|xml", 'Database' : 'csv|dat|db|dbf|json|ldb|mdb|myd|pdb|sql|tsv|wdb|wmdb|xlr|xls|xlsx|xml',
"Development" : "asm|c|class|cls|cpp|cc|cs|cxx|cbp|cs|dba|fla|h|java|lua|pl|py|pyc|pyo|sh|sln|r|rb|vb", 'Development' : 'asm|c|class|cls|cpp|cc|cs|cxx|cbp|cs|dba|fla|h|java|lua|pl|py|pyc|pyo|sh|sln|r|rb|vb',
"Document" : "doc|docx|odt|ott|pages|pdf|rtf|tex|wpd|wps|wrd|wri", 'Document' : 'doc|docx|odt|ott|pages|pdf|rtf|tex|wpd|wps|wrd|wri',
"Executable" : "apk|app|com|exe|gadget|lnk|msi", 'Executable' : 'apk|app|com|exe|gadget|lnk|msi',
"Fonts" : "eot|fnt|fon|otf|ttf|woff", 'Fonts' : 'eot|fnt|fon|otf|ttf|woff',
"Icons" : "ani|cur|icns|ico", 'Icons' : 'ani|cur|icns|ico',
"Images" : "bmp|gif|jpg|jpeg|jpe|jp2|pic|png|psd|tga|tif|tiff|wmf|webp", 'Images' : 'bmp|gif|jpg|jpeg|jpe|jp2|pic|png|psd|tga|tif|tiff|wmf|webp',
"Presentation" : "pps|ppt", 'Presentation' : 'pps|ppt',
"Published" : "chp|epub|lit|pub|ppp|fm|mobi", 'Published' : 'chp|epub|lit|pub|ppp|fm|mobi',
"Script" : "as|bat|cgi|cmd|jar|js|lua|scpt|scptd|sh|vbs|vb|wsf", 'Script' : 'as|bat|cgi|cmd|jar|js|lua|scpt|scptd|sh|vbs|vb|wsf',
"Styles" : "css|less|sass", 'Styles' : 'css|less|sass',
"Text" : "info|log|md|markdown|nfo|tex|text|txt", 'Text' : 'info|log|md|markdown|nfo|tex|text|txt',
"Vectors" : "awg|ai|eps|cdr|ps|svg", 'Vectors' : 'awg|ai|eps|cdr|ps|svg',
"Video" : "asf|avi|flv|m4v|mkv|mov|mp4|mpe|mpeg|mpg|ogg|rm|rv|swf|vob|wmv", 'Video' : 'asf|avi|flv|m4v|mkv|mov|mp4|mpe|mpeg|mpg|ogg|rm|rv|swf|vob|wmv',
"Web" : "asp|aspx|cer|cfm|htm|html|php|url|xhtml" 'Web' : 'asp|aspx|cer|cfm|htm|html|php|url|xhtml'
} }
}; };
@ -48,9 +48,9 @@
m = $.tablesorter.fileTypes.matching, m = $.tablesorter.fileTypes.matching,
types = $.tablesorter.fileTypes.equivalents; types = $.tablesorter.fileTypes.equivalents;
if (!m) { if (!m) {
// make a string to "quick" match the existing equivalents // make a string to 'quick' match the existing equivalents
t = []; t = [];
$.each(types, function(i,v){ $.each(types, function(i, v){
t.push(v); t.push(v);
}); });
m = $.tablesorter.fileTypes.matching = sep + t.join(sep) + sep; m = $.tablesorter.fileTypes.matching = sep + t.join(sep) + sep;

View File

@ -3,7 +3,7 @@
Globalize.locale( 'xx' ) prior to initializing tablesorter! */ Globalize.locale( 'xx' ) prior to initializing tablesorter! */
/*jshint jquery:true */ /*jshint jquery:true */
;( function( $ ) { ;( function( $ ) {
'use strict'; 'use strict';
/*! jQuery Globalize date parser (https://github.com/jquery/globalize#date-module) */ /*! jQuery Globalize date parser (https://github.com/jquery/globalize#date-module) */
/* demo: http://jsfiddle.net/Mottie/0j18Lw8r/ */ /* demo: http://jsfiddle.net/Mottie/0j18Lw8r/ */

View File

@ -1,28 +1,28 @@
/*! Parser: ignoreArticles - updated 9/15/2014 (v2.17.8) *//* /*! Parser: ignoreArticles - updated 9/15/2014 (v2.17.8) *//*
* This parser will remove "The", "A" and "An" from the beginning of a book * This parser will remove 'The', 'A' and 'An' from the beginning of a book
* or movie title, so it sorts by the second word or number * or movie title, so it sorts by the second word or number
* Demo: http://jsfiddle.net/Mottie/abkNM/5/ * Demo: http://jsfiddle.net/Mottie/abkNM/5/
*/ */
/*jshint browser: true, jquery:true, unused:false */ /*jshint browser: true, jquery:true, unused:false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
// basic list from http://en.wikipedia.org/wiki/Article_%28grammar%29 // basic list from http://en.wikipedia.org/wiki/Article_%28grammar%29
ts.ignoreArticles = { ts.ignoreArticles = {
"en" : "the, a, an", 'en' : 'the, a, an',
"de" : "der, die, das, des, dem, den, ein, eine, einer, eines, einem, einen", 'de' : 'der, die, das, des, dem, den, ein, eine, einer, eines, einem, einen',
"nl" : "de, het, de, een", 'nl' : 'de, het, de, een',
"es" : "el, la, lo, los, las, un, una, unos, unas", 'es' : 'el, la, lo, los, las, un, una, unos, unas',
"pt" : "o, a, os, as, um, uma, uns, umas", 'pt' : 'o, a, os, as, um, uma, uns, umas',
"fr" : "le, la, l'_, les, un, une, des", 'fr' : 'le, la, l\'_, les, un, une, des',
"it" : "il, lo, la, l'_, i, gli, le, un', uno, una, un", 'it' : 'il, lo, la, l\'_, i, gli, le, un\', uno, una, un',
"hu" : "a, az, egy" 'hu' : 'a, az, egy'
}; };
// To add a custom parser, define: // To add a custom parser, define:
// $.tablesorter.ignoreArticles['xx'] = "A, B, C"; // $.tablesorter.ignoreArticles['xx'] = 'A, B, C';
// and then set the language id 'xx' in the headers option // and then set the language id 'xx' in the headers option
// ignoreArticles : 'xx' // ignoreArticles : 'xx'
@ -40,11 +40,11 @@ var ts = $.tablesorter;
if (!c.headers) { c.headers = {}; } if (!c.headers) { c.headers = {}; }
if (!c.headers[cellIndex]) { c.headers[cellIndex] = {}; } if (!c.headers[cellIndex]) { c.headers[cellIndex] = {}; }
lang = ts.getData( c.$headers.eq(cellIndex), ts.getColumnData( table, c.headers, cellIndex ), 'ignoreArticles' ); lang = ts.getData( c.$headers.eq(cellIndex), ts.getColumnData( table, c.headers, cellIndex ), 'ignoreArticles' );
art = (ts.ignoreArticles[lang] || "the, a, an" ) + ""; art = (ts.ignoreArticles[lang] || 'the, a, an' ) + '';
c.headers[cellIndex].ignoreArticlesRegex = new RegExp('^(' + $.trim( art.split(/\s*\,\s*/).join('\\s|') + "\\s" ).replace("_\\s","") + ')', 'i'); c.headers[cellIndex].ignoreArticlesRegex = new RegExp('^(' + $.trim( art.split(/\s*\,\s*/).join('\\s|') + '\\s' ).replace('_\\s', '') + ')', 'i');
// exception regex stored in c.headers[cellIndex].ignoreArticlesRegex2 // exception regex stored in c.headers[cellIndex].ignoreArticlesRegex2
ignore = ts.getData( c.$headers.eq(cellIndex), ts.getColumnData( table, c.headers, cellIndex ), 'ignoreArticlesExcept' ); ignore = ts.getData( c.$headers.eq(cellIndex), ts.getColumnData( table, c.headers, cellIndex ), 'ignoreArticlesExcept' );
c.headers[cellIndex].ignoreArticlesRegex2 = ignore !== '' ? new RegExp('^(' + ignore.replace(/\s/g, "\\s") + ')', 'i') : ''; c.headers[cellIndex].ignoreArticlesRegex2 = ignore !== '' ? new RegExp('^(' + ignore.replace(/\s/g, '\\s') + ')', 'i') : '';
} }
art = c.headers[cellIndex].ignoreArticlesRegex; art = c.headers[cellIndex].ignoreArticlesRegex;
if (art.test(str)) { if (art.test(str)) {

View File

@ -2,10 +2,10 @@
/* alt attribute parser for jQuery 1.7+ & tablesorter 2.7.11+ */ /* alt attribute parser for jQuery 1.7+ & tablesorter 2.7.11+ */
/*jshint jquery:true, unused:false */ /*jshint jquery:true, unused:false */
;(function($){ ;(function($){
"use strict"; 'use strict';
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "image", id: 'image',
is: function(){ is: function(){
return false; return false;
}, },
@ -13,7 +13,7 @@
return $(cell).find('img').attr(table.config.imgAttr || 'alt') || s; return $(cell).find('img').attr(table.config.imgAttr || 'alt') || s;
}, },
parsed : true, // filter widget flag parsed : true, // filter widget flag
type: "text" type: 'text'
}); });
})(jQuery); })(jQuery);

View File

@ -4,7 +4,7 @@
*/ */
/*jshint browser: true, jquery:true, unused:false */ /*jshint browser: true, jquery:true, unused:false */
;( function( $ ) { ;( function( $ ) {
'use strict'; 'use strict';
var updateServer = function( event, $table, $input ) { var updateServer = function( event, $table, $input ) {
// do something here to update your server, if needed // do something here to update your server, if needed

View File

@ -6,7 +6,7 @@
*/ */
/*jshint jquery:true */ /*jshint jquery:true */
;( function( $ ) { ;( function( $ ) {
'use strict'; 'use strict';
var prefixes = { var prefixes = {
// 'prefix' : [ base 10, base 2 ] // 'prefix' : [ base 10, base 2 ]
@ -23,7 +23,7 @@
'h|hecto' : [ 1e2, 1e2 ], 'h|hecto' : [ 1e2, 1e2 ],
'da|deka' : [ 1e1, 1e1 ], 'da|deka' : [ 1e1, 1e1 ],
'd|deci' : [ 1e-1, 1e-1 ], 'd|deci' : [ 1e-1, 1e-1 ],
'c|centi' : [ 1e-2, 1e-2], 'c|centi' : [ 1e-2, 1e-2 ],
'm|milli' : [ 1e-3, 1e-3 ], 'm|milli' : [ 1e-3, 1e-3 ],
'µ|micro' : [ 1e-6, 1e-6 ], 'µ|micro' : [ 1e-6, 1e-6 ],
'n|nano' : [ 1e-9, 1e-9 ], 'n|nano' : [ 1e-9, 1e-9 ],

View File

@ -3,7 +3,7 @@
*/ */
/*jshint jquery:true */ /*jshint jquery:true */
;(function($){ ;(function($){
"use strict"; 'use strict';
// Change language of the named numbers as needed // Change language of the named numbers as needed
var named = { var named = {
@ -99,7 +99,7 @@
}; };
$.tablesorter.addParser({ $.tablesorter.addParser({
id: "namedNumbers", id: 'namedNumbers',
is: function () { is: function () {
return false; return false;
}, },
@ -116,7 +116,7 @@
// make sure to let zero get parsed, so check hasOwnProperty // make sure to let zero get parsed, so check hasOwnProperty
return result || named.numbers.hasOwnProperty( str ) ? result : $.tablesorter.formatFloat( str || '', table ); return result || named.numbers.hasOwnProperty( str ) ? result : $.tablesorter.formatFloat( str || '', table );
}, },
type: "numeric" type: 'numeric'
}); });
})( jQuery ); })( jQuery );

View File

@ -69,7 +69,7 @@
// it's fastest & easiest for tablesorter to sort decimal values (vs hex) // it's fastest & easiest for tablesorter to sort decimal values (vs hex)
groups[i] = hex ? ('0000' + groups[i]).slice(-4) : groups[i] = hex ? ('0000' + groups[i]).slice(-4) :
('00000' + (parseInt(groups[i], 16) || 0)).slice(-5); ('00000' + (parseInt(groups[i], 16) || 0)).slice(-5);
expandedAddress += ( i != validGroupCount-1) ? groups[i] + ':' : groups[i]; expandedAddress += ( i != validGroupCount - 1) ? groups[i] + ':' : groups[i];
} }
return hex ? expandedAddress : expandedAddress.replace(/:/g, ''); return hex ? expandedAddress : expandedAddress.replace(/:/g, '');
}, },

View File

@ -5,7 +5,7 @@
*/ */
/*jshint jquery:true, unused:false */ /*jshint jquery:true, unused:false */
;(function($){ ;(function($){
"use strict"; 'use strict';
// allow lower case roman numerals, since lists use i, ii, iii, etc. // allow lower case roman numerals, since lists use i, ii, iii, etc.
var validator = /^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/i, var validator = /^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/i,
@ -34,7 +34,7 @@
return num; return num;
}, },
type: "numeric" type: 'numeric'
}); });
$.tablesorter.addParser({ $.tablesorter.addParser({
@ -75,7 +75,7 @@
return num ? s.replace(orig, num) : s; return num ? s.replace(orig, num) : s;
}, },
type: "text" type: 'text'
}); });
$.tablesorter.addParser({ $.tablesorter.addParser({
@ -111,7 +111,7 @@
return num ? num : s; return num ? num : s;
}, },
type: "numeric" type: 'numeric'
}); });
})(jQuery); })(jQuery);

View File

@ -5,142 +5,143 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.alignChar = { ts.alignChar = {
init : function(table, c, wo) { init : function(table, c, wo) {
c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){ c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){
var $this = $(this), var $this = $(this),
vars = { vars = {
column : this.column, column : this.column,
align : $this.attr(wo.alignChar_charAttrib), align : $this.attr(wo.alignChar_charAttrib),
alignIndex : parseInt( $this.attr(wo.alignChar_indexAttrib) || 0, 10), alignIndex : parseInt( $this.attr(wo.alignChar_indexAttrib) || 0, 10),
adjust : parseFloat($this.attr(wo.alignChar_adjustAttrib)) || 0 adjust : parseFloat($this.attr(wo.alignChar_adjustAttrib)) || 0
}; };
vars.regex = new RegExp('\\' + vars.align, 'g'); vars.regex = new RegExp('\\' + vars.align, 'g');
if (typeof vars.align !== 'undefined') { if (typeof vars.align !== 'undefined') {
wo.alignChar_savedVars[this.column] = vars; wo.alignChar_savedVars[this.column] = vars;
ts.alignChar.setup(table, c, wo, vars); ts.alignChar.setup(table, c, wo, vars);
} }
}); });
}, },
setup: function(table, c, wo, v){ setup: function(table, c, wo, v){
// do nothing for empty tables // do nothing for empty tables
if ($.isEmptyObject(c.cache)) { return; } if ($.isEmptyObject(c.cache)) { return; }
var tbodyIndex, rowIndex, start, end, last, index, rows, val, count, var tbodyIndex, rowIndex, start, end, last, index, rows, val, count,
len, wLeft, wRight, alignChar, $row, len, wLeft, wRight, alignChar, $row,
left = [], left = [],
right = []; right = [];
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){ for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){
rows = c.cache[tbodyIndex]; rows = c.cache[tbodyIndex];
len = rows.normalized.length; len = rows.normalized.length;
for (rowIndex = 0; rowIndex < len; rowIndex++) { for (rowIndex = 0; rowIndex < len; rowIndex++) {
// set up to work with modified cache v2.16.0+ // set up to work with modified cache v2.16.0+
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row; $row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row;
val = $row.find('td').eq(v.column).text().replace(/[ ]/g, "\u00a0"); val = $row.find('td').eq(v.column).text().replace(/[ ]/g, '\u00a0');
// count how many "align" characters are in the string // count how many 'align' characters are in the string
count = (val.match( v.regex ) || []).length; count = (val.match( v.regex ) || []).length;
// set alignment @ alignIndex (one-based index) // set alignment @ alignIndex (one-based index)
if (count > 0 && v.alignIndex > 0) { if (count > 0 && v.alignIndex > 0) {
end = Math.min(v.alignIndex, count); end = Math.min(v.alignIndex, count);
start = 0; start = 0;
index = 0; index = 0;
last = 0; last = 0;
// find index of nth align character based on alignIndex (data-align-index) // find index of nth align character based on alignIndex (data-align-index)
while (start++ < end) { while (start++ < end) {
last = val.indexOf(v.align, last + 1); last = val.indexOf(v.align, last + 1);
index = last < 0 ? index : last; index = last < 0 ? index : last;
}
} else {
index = val.indexOf(v.align);
}
if ( index >= 0 ) {
left.push( val.substring(0, index) || '' );
right.push( val.substring(index, val.length) || '' );
} else {
// no align character found!
// put val in right or left based on the align index
left.push( (count >= 1 && v.alignIndex >= count) ? '' : val || '' );
right.push( (count >= 1 && v.alignIndex >= count) ? val || '' : '' );
} }
} else {
index = val.indexOf(v.align);
} }
if ( index >= 0 ) { }
left.push( val.substring(0, index) || '' );
right.push( val.substring(index, val.length) || '' ); // find widest segments
} else { wLeft = ($.extend([], left)).sort(function(a, b){ return b.length - a.length; })[0];
// no align character found! wRight = ($.extend([], right)).sort(function(a, b){ return b.length - a.length; })[0];
// put val in right or left based on the align index // calculate percentage widths
left.push( (count >= 1 && v.alignIndex >= count) ? '' : val || '' ); v.width = v.width || ( Math.floor(wLeft.length / (wLeft.length + wRight.length) * 100) + v.adjust );
right.push( (count >= 1 && v.alignIndex >= count) ? val || '' : '' ); wLeft = 'min-width:' + v.width + '%';
wRight = 'min-width:' + (100 - v.width) + '%';
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){
rows = c.cache[tbodyIndex];
len = rows.normalized.length;
for (rowIndex = 0; rowIndex < len; rowIndex++) {
alignChar = $(wo.alignChar_wrap).length ? $(wo.alignChar_wrap).html(v.align)[0].outerHTML : v.align;
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row;
last = right[rowIndex].slice(v.align.length);
$row.find('td').eq(v.column).html(
'<span class="ts-align-wrap"><span class="ts-align-left" style="' + wLeft + '">' + left[rowIndex] + '</span>' +
'<span class="ts-align-right" style="' + wRight + '">' + ( last.length ? alignChar + last : '' ) + '</span></span>'
);
}
}
wo.alignChar_initialized = true;
},
remove: function(table, c, column){
if ($.isEmptyObject(c.cache)) { return; }
var tbodyIndex, rowIndex, len, rows, $row, $cell;
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){
rows = c.cache[tbodyIndex];
len = rows.normalized.length;
for (rowIndex = 0; rowIndex < len; rowIndex++) {
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row;
$cell = $row.find('td').eq(column);
$cell.html( $cell.text().replace(/\s/g, ' ') );
} }
} }
} }
};
// find widest segments ts.addWidget({
wLeft = ($.extend([], left)).sort(function(a,b){ return b.length - a.length; })[0]; id: 'alignChar',
wRight = ($.extend([], right)).sort(function(a,b){ return b.length - a.length; })[0]; priority: 100,
// calculate percentage widths options: {
v.width = v.width || ( Math.floor(wLeft.length / (wLeft.length + wRight.length) * 100) + v.adjust ); alignChar_wrap : '',
wLeft = 'min-width:' + v.width + '%'; alignChar_charAttrib : 'data-align-char',
wRight = 'min-width:' + (100 - v.width) + '%'; alignChar_indexAttrib : 'data-align-index',
alignChar_adjustAttrib : 'data-align-adjust' // percentage width adjustments
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){ },
rows = c.cache[tbodyIndex]; init: function(table, thisWidget, c, wo){
len = rows.normalized.length; wo.alignChar_initialized = false;
for (rowIndex = 0; rowIndex < len; rowIndex++) { wo.alignChar_savedVars = [];
alignChar = $(wo.alignChar_wrap).length ? $(wo.alignChar_wrap).html(v.align)[0].outerHTML : v.align; ts.alignChar.init(table, c, wo);
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row; c.$table.on('pagerEnd refreshAlign', function(){
last = right[rowIndex].slice(v.align.length); c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){
$row.find('td').eq(v.column).html( ts.alignChar.remove(table, c, this.column);
'<span class="ts-align-wrap"><span class="ts-align-left" style="' + wLeft + '">' + left[rowIndex] + '</span>' + });
'<span class="ts-align-right" style="' + wRight + '">' + ( last.length ? alignChar + last : '' ) + '</span></span>' ts.alignChar.init(table, c, wo);
); });
},
format : function(table, c, wo){
// reinitialize in case table is empty when first initialized
if (!wo.alignChar_initialized) {
c.$table.trigger('refreshAlign');
} }
} },
wo.alignChar_initialized = true; remove : function(table, c, wo, refreshing){
if (refreshing) { return; }
},
remove: function(table, c, column){
if ($.isEmptyObject(c.cache)) { return; }
var tbodyIndex, rowIndex, len, rows, $row, $cell;
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){
rows = c.cache[tbodyIndex];
len = rows.normalized.length;
for (rowIndex = 0; rowIndex < len; rowIndex++) {
$row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row;
$cell = $row.find('td').eq(column);
$cell.html( $cell.text().replace(/\s/g, ' ') );
}
}
}
};
ts.addWidget({
id: 'alignChar',
priority: 100,
options: {
alignChar_wrap : '',
alignChar_charAttrib : 'data-align-char',
alignChar_indexAttrib : 'data-align-index',
alignChar_adjustAttrib : 'data-align-adjust' // percentage width adjustments
},
init: function(table, thisWidget, c, wo){
wo.alignChar_initialized = false;
wo.alignChar_savedVars = [];
ts.alignChar.init(table, c, wo);
c.$table.on('pagerEnd refreshAlign', function(){
c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){ c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){
ts.alignChar.remove(table, c, this.column); ts.alignChar.remove(table, c, this.column);
}); });
ts.alignChar.init(table, c, wo); wo.alignChar_initialized = false;
});
},
format : function(table, c, wo){
// reinitialize in case table is empty when first initialized
if (!wo.alignChar_initialized) {
c.$table.trigger('refreshAlign');
} }
}, });
remove : function(table, c, wo, refreshing){
if (refreshing) { return; }
c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){
ts.alignChar.remove(table, c, this.column);
});
wo.alignChar_initialized = false;
}
});
})(jQuery); })(jQuery);

View File

@ -5,8 +5,8 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter = $.tablesorter || {}, var ts = $.tablesorter = $.tablesorter || {},
// build a table from data (requires existing <table> tag) // build a table from data (requires existing <table> tag)
// data.header contains an array of header titles // data.header contains an array of header titles
@ -40,7 +40,7 @@ var ts = $.tablesorter = $.tablesorter || {},
// valid JSON! // valid JSON!
return bt.object( table, d, wo ); return bt.object( table, d, wo );
} }
} catch(ignore) {} } catch (ignore) {}
// fall through in case it's a csv string // fall through in case it's a csv string
} }
// Array // Array
@ -105,7 +105,7 @@ var ts = $.tablesorter = $.tablesorter || {},
// *** CSV only options *** // *** CSV only options ***
build_csvStartLine : 0, // line within the csv to start adding to table build_csvStartLine : 0, // line within the csv to start adding to table
build_csvSeparator : ",", // csv separator build_csvSeparator : ',', // csv separator
// *** build object options *** // *** build object options ***
build_objectRowKey : 'rows', // object key containing table rows build_objectRowKey : 'rows', // object key containing table rows
@ -225,7 +225,7 @@ var ts = $.tablesorter = $.tablesorter || {},
var c, h, var c, h,
csv = wo.build_type === 'csv' || typeof data === 'string', csv = wo.build_type === 'csv' || typeof data === 'string',
$t = $(table), $t = $(table),
lines = csv ? data.replace('\r','').split('\n') : data, lines = csv ? data.replace('\r', '').split('\n') : data,
len = lines.length, len = lines.length,
printedLines = 0, printedLines = 0,
infooter = false, infooter = false,
@ -276,13 +276,13 @@ var ts = $.tablesorter = $.tablesorter || {},
// CSV Parser by Brian Huisman (http://www.greywyvern.com/?post=258) // CSV Parser by Brian Huisman (http://www.greywyvern.com/?post=258)
bt.splitCSV = function(str, sep) { bt.splitCSV = function(str, sep) {
var x, tl, var x, tl,
thisCSV = $.trim(str).split(sep = sep || ","); thisCSV = $.trim(str).split(sep = sep || ',');
for ( x = thisCSV.length - 1; x >= 0; x-- ) { for ( x = thisCSV.length - 1; x >= 0; x-- ) {
if ( thisCSV[x].replace(/\"\s+$/, '"').charAt(thisCSV[x].length - 1) === '"' ) { if ( thisCSV[x].replace(/\"\s+$/, '"').charAt(thisCSV[x].length - 1) === '"' ) {
if ( (tl = thisCSV[x].replace(/^\s+\"/, '"')).length > 1 && tl.charAt(0) === '"' ) { if ( (tl = thisCSV[x].replace(/^\s+\"/, '"')).length > 1 && tl.charAt(0) === '"' ) {
thisCSV[x] = thisCSV[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"'); thisCSV[x] = thisCSV[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"');
} else if (x) { } else if (x) {
thisCSV.splice(x - 1, 2, [thisCSV[x - 1], thisCSV[x]].join(sep)); thisCSV.splice(x - 1, 2, [ thisCSV[x - 1], thisCSV[x] ].join(sep));
} else { } else {
thisCSV = thisCSV.shift().split(sep).concat(thisCSV); thisCSV = thisCSV.shift().split(sep).concat(thisCSV);
} }
@ -304,7 +304,7 @@ var ts = $.tablesorter = $.tablesorter || {},
bt.buildComplete(table, wo); bt.buildComplete(table, wo);
}; };
/* ==== Object example ==== /* ==== Object example ====
data : { data : {
headers : [ headers : [
[ [
@ -345,9 +345,9 @@ var ts = $.tablesorter = $.tablesorter || {},
} }
] ]
} }
*/ */
bt.object = function(table, data, wo) { bt.object = function(table, data, wo) {
// "rows" // 'rows'
var j, l, t, $c, $t, $tb, $tr, var j, l, t, $c, $t, $tb, $tr,
c = table.config, c = table.config,
kh = wo.build_objectHeaderKey, kh = wo.build_objectHeaderKey,

View File

@ -32,7 +32,7 @@
.off(wo.chart_event) .off(wo.chart_event)
.on(wo.chart_event, function() { .on(wo.chart_event, function() {
if (this.hasInitialized) { if (this.hasInitialized) {
// refresh "c" variable in case options are updated dynamically // refresh 'c' variable in case options are updated dynamically
var c = this.config; var c = this.config;
chart.getCols(c, c.widgetOptions); chart.getCols(c, c.widgetOptions);
chart.getData(c, c.widgetOptions); chart.getData(c, c.widgetOptions);
@ -258,7 +258,7 @@
// Set the label column // Set the label column
chart_labelCol: 0, chart_labelCol: 0,
// data sort, should always be first row, might want [[0,1]] // data sort, should always be first row, might want [[0,1]]
chart_sort: [[0,0]], chart_sort: [ [ 0, 0 ] ],
// event to trigger get updated data // event to trigger get updated data
chart_event: 'chartData' chart_event: 'chartData'
}, },

View File

@ -5,362 +5,362 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter, var ts = $.tablesorter,
namespace = '.tscolsel', namespace = '.tscolsel',
tsColSel = ts.columnSelector = { tsColSel = ts.columnSelector = {
queryAll : '@media only all { [columns] { display: none; } } ', queryAll : '@media only all { [columns] { display: none; } } ',
queryBreak : '@media all and (min-width: [size]) { [columns] { display: table-cell; } } ', queryBreak : '@media all and (min-width: [size]) { [columns] { display: table-cell; } } ',
init: function(table, c, wo) { init: function(table, c, wo) {
var $t, colSel; var $t, colSel;
// abort if no input is contained within the layout // abort if no input is contained within the layout
$t = $(wo.columnSelector_layout); $t = $(wo.columnSelector_layout);
if (!$t.find('input').add( $t.filter('input') ).length) { if (!$t.find('input').add( $t.filter('input') ).length) {
if (c.debug) { if (c.debug) {
ts.log('ColumnSelector: >> ERROR: Column Selector aborting, no input found in the layout! ***'); ts.log('ColumnSelector: >> ERROR: Column Selector aborting, no input found in the layout! ***');
}
return;
} }
return;
}
// unique table class name // unique table class name
c.$table.addClass( c.namespace.slice(1) + 'columnselector' ); c.$table.addClass( c.namespace.slice(1) + 'columnselector' );
// build column selector/state array // build column selector/state array
colSel = c.selector = { $container : $(wo.columnSelector_container || '<div>') }; colSel = c.selector = { $container : $(wo.columnSelector_container || '<div>') };
colSel.$style = $('<style></style>').prop('disabled', true).appendTo('head'); colSel.$style = $('<style></style>').prop('disabled', true).appendTo('head');
colSel.$breakpoints = $('<style></style>').prop('disabled', true).appendTo('head'); colSel.$breakpoints = $('<style></style>').prop('disabled', true).appendTo('head');
colSel.isInitializing = true; colSel.isInitializing = true;
tsColSel.setupSelector(table, c, wo); tsColSel.setupSelector(table, c, wo);
if (wo.columnSelector_mediaquery) { if (wo.columnSelector_mediaquery) {
tsColSel.setupBreakpoints(c, wo); tsColSel.setupBreakpoints(c, wo);
} }
colSel.isInitializing = false; colSel.isInitializing = false;
if (colSel.$container.length) { if (colSel.$container.length) {
tsColSel.updateCols(c, wo); tsColSel.updateCols(c, wo);
} else if (c.debug) { } else if (c.debug) {
ts.log('ColumnSelector: >> container not found'); ts.log('ColumnSelector: >> container not found');
} }
c.$table c.$table
.off('refreshColumnSelector' + namespace) .off('refreshColumnSelector' + namespace)
.on('refreshColumnSelector' + namespace, function(e, opt){ .on('refreshColumnSelector' + namespace, function(e, opt){
// make sure we're using current config settings // make sure we're using current config settings
var i, var i,
isArry = $.isArray(opt), isArry = $.isArray(opt),
c = this.config, c = this.config,
wo = c.widgetOptions; wo = c.widgetOptions;
// see #798 // see #798
if (opt && c.selector.$container.length) { if (opt && c.selector.$container.length) {
if (isArry) { if (isArry) {
// make sure array contains numbers // make sure array contains numbers
$.each(opt, function(i,v){ $.each(opt, function(i, v){
opt[i] = parseInt(v, 10); opt[i] = parseInt(v, 10);
}); });
for (i = 0; i < c.columns; i++) { for (i = 0; i < c.columns; i++) {
c.selector.$container c.selector.$container
.find('input[data-column=' + i + ']') .find('input[data-column=' + i + ']')
.prop('checked', $.inArray( i, opt ) >= 0 ); .prop('checked', $.inArray( i, opt ) >= 0 );
}
} }
// if passing an array, set auto to false to allow manual column selection & update columns
tsColSel.updateAuto( c, wo, colSel.$container.find('input[data-column="auto"]').prop('checked', !isArry) );
} else {
tsColSel.updateBreakpoints(c, wo);
tsColSel.updateCols(c, wo);
} }
// if passing an array, set auto to false to allow manual column selection & update columns });
tsColSel.updateAuto( c, wo, colSel.$container.find('input[data-column="auto"]').prop('checked', !isArry) );
} else { },
tsColSel.updateBreakpoints(c, wo);
tsColSel.updateCols(c, wo); setupSelector: function(table, c, wo) {
var name,
colSel = c.selector,
$container = colSel.$container,
useStorage = wo.columnSelector_saveColumns && ts.storage,
// get stored column states
saved = useStorage ? ts.storage( table, 'tablesorter-columnSelector' ) : [],
state = useStorage ? ts.storage( table, 'tablesorter-columnSelector-auto') : {};
// initial states
colSel.auto = $.isEmptyObject(state) || $.type(state.auto) !== 'boolean' ? wo.columnSelector_mediaqueryState : state.auto;
colSel.states = [];
colSel.$column = [];
colSel.$wrapper = [];
colSel.$checkbox = [];
// populate the selector container
c.$table.children('thead').find('tr:first th', table).each(function() {
var $this = $(this),
// if no data-priority is assigned, default to 1, but don't remove it from the selector list
priority = $this.attr(wo.columnSelector_priority) || 1,
colId = $this.attr('data-column'),
state = ts.getData(this, c.headers[colId], 'columnSelector');
// if this column not hidable at all
// include getData check (includes 'columnSelector-false' class, data attribute, etc)
if ( isNaN(priority) && priority.length > 0 || state === 'disable' ||
( wo.columnSelector_columns[colId] && wo.columnSelector_columns[colId] === 'disable') ) {
return true; // goto next
}
// set default state; storage takes priority
colSel.states[colId] = saved && typeof saved[colId] !== 'undefined' ?
saved[colId] : typeof wo.columnSelector_columns[colId] !== 'undefined' ?
wo.columnSelector_columns[colId] : (state === 'true' || state !== 'false');
colSel.$column[colId] = $(this);
// set default col title
name = $this.attr(wo.columnSelector_name) || $this.text();
if ($container.length) {
colSel.$wrapper[colId] = $(wo.columnSelector_layout.replace(/\{name\}/g, name)).appendTo($container);
colSel.$checkbox[colId] = colSel.$wrapper[colId]
// input may not be wrapped within the layout template
.find('input').add( colSel.$wrapper[colId].filter('input') )
.attr('data-column', colId)
.toggleClass( wo.columnSelector_cssChecked, colSel.states[colId] )
.prop('checked', colSel.states[colId])
.on('change', function(){
colSel.states[colId] = this.checked;
tsColSel.updateCols(c, wo);
}).change();
} }
}); });
}, },
setupSelector: function(table, c, wo) { setupBreakpoints: function(c, wo){
var name, var colSel = c.selector;
colSel = c.selector,
$container = colSel.$container,
useStorage = wo.columnSelector_saveColumns && ts.storage,
// get stored column states
saved = useStorage ? ts.storage( table, 'tablesorter-columnSelector' ) : [],
state = useStorage ? ts.storage( table, 'tablesorter-columnSelector-auto') : {};
// initial states // add responsive breakpoints
colSel.auto = $.isEmptyObject(state) || $.type(state.auto) !== "boolean" ? wo.columnSelector_mediaqueryState : state.auto; if (wo.columnSelector_mediaquery) {
colSel.states = []; // used by window resize function
colSel.$column = []; colSel.lastIndex = -1;
colSel.$wrapper = []; tsColSel.updateBreakpoints(c, wo);
colSel.$checkbox = []; c.$table
// populate the selector container .off('updateAll' + namespace)
c.$table.children('thead').find('tr:first th', table).each(function() { .on('updateAll' + namespace, function(){
var $this = $(this), tsColSel.updateBreakpoints(c, wo);
// if no data-priority is assigned, default to 1, but don't remove it from the selector list
priority = $this.attr(wo.columnSelector_priority) || 1,
colId = $this.attr('data-column'),
state = ts.getData(this, c.headers[colId], 'columnSelector');
// if this column not hidable at all
// include getData check (includes "columnSelector-false" class, data attribute, etc)
if ( isNaN(priority) && priority.length > 0 || state === 'disable' ||
( wo.columnSelector_columns[colId] && wo.columnSelector_columns[colId] === 'disable') ) {
return true; // goto next
}
// set default state; storage takes priority
colSel.states[colId] = saved && typeof(saved[colId]) !== 'undefined' ?
saved[colId] : typeof(wo.columnSelector_columns[colId]) !== 'undefined' ?
wo.columnSelector_columns[colId] : (state === 'true' || state !== 'false');
colSel.$column[colId] = $(this);
// set default col title
name = $this.attr(wo.columnSelector_name) || $this.text();
if ($container.length) {
colSel.$wrapper[colId] = $(wo.columnSelector_layout.replace(/\{name\}/g, name)).appendTo($container);
colSel.$checkbox[colId] = colSel.$wrapper[colId]
// input may not be wrapped within the layout template
.find('input').add( colSel.$wrapper[colId].filter('input') )
.attr('data-column', colId)
.toggleClass( wo.columnSelector_cssChecked, colSel.states[colId] )
.prop('checked', colSel.states[colId])
.on('change', function(){
colSel.states[colId] = this.checked;
tsColSel.updateCols(c, wo); tsColSel.updateCols(c, wo);
}).change(); });
} }
});
}, if (colSel.$container.length) {
// Add media queries toggle
setupBreakpoints: function(c, wo){ if (wo.columnSelector_mediaquery) {
var colSel = c.selector; colSel.$auto = $( wo.columnSelector_layout.replace(/\{name\}/g, wo.columnSelector_mediaqueryName) ).prependTo(colSel.$container);
colSel.$auto
// add responsive breakpoints // needed in case the input in the layout is not wrapped
if (wo.columnSelector_mediaquery) { .find('input').add( colSel.$auto.filter('input') )
// used by window resize function .attr('data-column', 'auto')
colSel.lastIndex = -1; .prop('checked', colSel.auto)
tsColSel.updateBreakpoints(c, wo); .toggleClass( wo.columnSelector_cssChecked, colSel.auto )
c.$table .on('change', function(){
.off('updateAll' + namespace) tsColSel.updateAuto(c, wo, $(this));
.on('updateAll' + namespace, function(){ }).change();
tsColSel.updateBreakpoints(c, wo); }
// Add a bind on update to re-run col setup
c.$table.off('update' + namespace).on('update' + namespace, function() {
tsColSel.updateCols(c, wo); tsColSel.updateCols(c, wo);
}); });
} }
},
if (colSel.$container.length) { updateAuto: function(c, wo, $el) {
// Add media queries toggle var colSel = c.selector;
colSel.auto = $el.prop('checked') || false;
$.each( colSel.$checkbox, function(i, $cb){
if ($cb) {
$cb[0].disabled = colSel.auto;
colSel.$wrapper[i].toggleClass('disabled', colSel.auto);
}
});
if (wo.columnSelector_mediaquery) { if (wo.columnSelector_mediaquery) {
colSel.$auto = $( wo.columnSelector_layout.replace(/\{name\}/g, wo.columnSelector_mediaqueryName) ).prependTo(colSel.$container); tsColSel.updateBreakpoints(c, wo);
colSel.$auto
// needed in case the input in the layout is not wrapped
.find('input').add( colSel.$auto.filter('input') )
.attr('data-column', 'auto')
.prop('checked', colSel.auto)
.toggleClass( wo.columnSelector_cssChecked, colSel.auto )
.on('change', function(){
tsColSel.updateAuto(c, wo, $(this));
}).change();
} }
// Add a bind on update to re-run col setup tsColSel.updateCols(c, wo);
c.$table.off('update' + namespace).on('update' + namespace, function() { // copy the column selector to a popup/tooltip
tsColSel.updateCols(c, wo); if (c.selector.$popup) {
}); 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' ? colSel.auto : colSel.states[indx] );
});
}
if (wo.columnSelector_saveColumns && ts.storage) {
ts.storage( c.$table[0], 'tablesorter-columnSelector-auto', { auto : colSel.auto } );
}
// trigger columnUpdate if auto is true (it gets skipped in updateCols()
if (colSel.auto) {
c.$table.trigger('columnUpdate');
}
},
updateAuto: function(c, wo, $el) { updateBreakpoints: function(c, wo) {
var colSel = c.selector; var priority, column, breaks, temp,
colSel.auto = $el.prop('checked') || false; colSel = c.selector,
$.each( colSel.$checkbox, function(i, $cb){ prefix = c.namespace + 'columnselector',
if ($cb) { mediaAll = [],
$cb[0].disabled = colSel.auto; breakpts = '';
colSel.$wrapper[i].toggleClass('disabled', colSel.auto); if (wo.columnSelector_mediaquery && !colSel.auto) {
colSel.$breakpoints.prop('disabled', true);
colSel.$style.prop('disabled', false);
return;
} }
});
if (wo.columnSelector_mediaquery) { // only 6 breakpoints (same as jQuery Mobile)
tsColSel.updateBreakpoints(c, wo); for (priority = 0; priority < 6; priority++){
} /*jshint loopfunc:true */
tsColSel.updateCols(c, wo); breaks = [];
// copy the column selector to a popup/tooltip c.$headers.filter('[' + wo.columnSelector_priority + '=' + (priority + 1) + ']').each(function(){
if (c.selector.$popup) { column = parseInt($(this).attr('data-column'), 10) + 1;
c.selector.$popup.find('.tablesorter-column-selector') temp = ' col:nth-child(' + column + ')';
.html( colSel.$container.html() ) breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
.find('input').each(function(){ temp = ' tr th:nth-child(' + column + ')';
var indx = $(this).attr('data-column'); breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
$(this).prop( 'checked', indx === 'auto' ? colSel.auto : colSel.states[indx] ); temp = ' tr td:nth-child(' + column + ')';
breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
}); });
} if (breaks.length) {
if (wo.columnSelector_saveColumns && ts.storage) { mediaAll = mediaAll.concat( breaks );
ts.storage( c.$table[0], 'tablesorter-columnSelector-auto', { auto : colSel.auto } ); breakpts += tsColSel.queryBreak
} .replace(/\[size\]/g, wo.columnSelector_breakpoints[priority])
// trigger columnUpdate if auto is true (it gets skipped in updateCols() .replace(/\[columns\]/g, breaks.join(','));
if (colSel.auto) { }
}
if (colSel.$style) {
colSel.$style.prop('disabled', true);
}
if (mediaAll.length) {
colSel.$breakpoints
.prop('disabled', false)
.html( tsColSel.queryAll.replace(/\[columns\]/g, mediaAll.join(',')) + breakpts );
}
},
updateCols: function(c, wo) {
if (wo.columnSelector_mediaquery && c.selector.auto || c.selector.isInitializing) {
return;
}
var column, temp,
colSel = c.selector,
styles = [],
prefix = c.namespace + 'columnselector';
colSel.$container.find('input[data-column]').filter('[data-column!="auto"]').each(function(){
if (!this.checked) {
column = parseInt( $(this).attr('data-column'), 10 ) + 1;
temp = ' col:nth-child(' + column + ')';
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
temp = ' tr th:nth-child(' + column + ')';
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
temp = ' tr td:nth-child(' + column + ')';
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
}
$(this).toggleClass( wo.columnSelector_cssChecked, this.checked );
});
if (wo.columnSelector_mediaquery){
colSel.$breakpoints.prop('disabled', true);
}
if (colSel.$style) {
colSel.$style.prop('disabled', false).html( styles.length ? styles.join(',') + ' { display: none; }' : '' );
}
if (wo.columnSelector_saveColumns && ts.storage) {
ts.storage( c.$table[0], 'tablesorter-columnSelector', colSel.states );
}
c.$table.trigger('columnUpdate'); c.$table.trigger('columnUpdate');
} },
},
updateBreakpoints: function(c, wo) { attachTo : function(table, elm) {
var priority, column, breaks, temp, table = $(table)[0];
colSel = c.selector, var colSel, wo, indx,
prefix = c.namespace + 'columnselector', c = table.config,
mediaAll = [], $popup = $(elm);
breakpts = ''; if ($popup.length && c) {
if (wo.columnSelector_mediaquery && !colSel.auto) { if (!$popup.find('.tablesorter-column-selector').length) {
colSel.$breakpoints.prop('disabled', true); // add a wrapper to add the selector into, in case the popup has other content
colSel.$style.prop('disabled', false); $popup.append('<span class="tablesorter-column-selector"></span>');
return; }
} colSel = c.selector;
wo = c.widgetOptions;
// only 6 breakpoints (same as jQuery Mobile) $popup.find('.tablesorter-column-selector')
for (priority = 0; priority < 6; priority++){ .html( colSel.$container.html() )
/*jshint loopfunc:true */ .find('input').each(function(){
breaks = []; var indx = $(this).attr('data-column'),
c.$headers.filter('[' + wo.columnSelector_priority + '=' + (priority + 1) + ']').each(function(){ isChecked = indx === 'auto' ? colSel.auto : colSel.states[indx];
column = parseInt($(this).attr('data-column'), 10) + 1; $(this)
temp = ' col:nth-child(' + column + ')'; .toggleClass( wo.columnSelector_cssChecked, isChecked )
breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp); .prop( 'checked', isChecked );
temp = ' tr th:nth-child(' + column + ')'; });
breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp); colSel.$popup = $popup.on('change', 'input', function(){
temp = ' tr td:nth-child(' + column + ')'; // data input
breaks.push(prefix + temp + ',' + prefix + '_extra_table' + temp); indx = $(this).toggleClass( wo.columnSelector_cssChecked, this.checked ).attr('data-column');
}); // update original popup
if (breaks.length) { colSel.$container.find('input[data-column="' + indx + '"]')
mediaAll = mediaAll.concat( breaks ); .prop('checked', this.checked)
breakpts += tsColSel.queryBreak .trigger('change');
.replace(/\[size\]/g, wo.columnSelector_breakpoints[priority])
.replace(/\[columns\]/g, breaks.join(','));
}
}
if (colSel.$style) {
colSel.$style.prop('disabled', true);
}
if (mediaAll.length) {
colSel.$breakpoints
.prop('disabled', false)
.html( tsColSel.queryAll.replace(/\[columns\]/g, mediaAll.join(',')) + breakpts );
}
},
updateCols: function(c, wo) {
if (wo.columnSelector_mediaquery && c.selector.auto || c.selector.isInitializing) {
return;
}
var column, temp,
colSel = c.selector,
styles = [],
prefix = c.namespace + 'columnselector';
colSel.$container.find('input[data-column]').filter('[data-column!="auto"]').each(function(){
if (!this.checked) {
column = parseInt( $(this).attr('data-column'), 10 ) + 1;
temp = ' col:nth-child(' + column + ')';
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
temp = ' tr th:nth-child(' + column + ')';
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
temp = ' tr td:nth-child(' + column + ')';
styles.push(prefix + temp + ',' + prefix + '_extra_table' + temp);
}
$(this).toggleClass( wo.columnSelector_cssChecked, this.checked );
});
if (wo.columnSelector_mediaquery){
colSel.$breakpoints.prop('disabled', true);
}
if (colSel.$style) {
colSel.$style.prop('disabled', false).html( styles.length ? styles.join(',') + ' { display: none; }' : '' );
}
if (wo.columnSelector_saveColumns && ts.storage) {
ts.storage( c.$table[0], 'tablesorter-columnSelector', colSel.states );
}
c.$table.trigger('columnUpdate');
},
attachTo : function(table, elm) {
table = $(table)[0];
var colSel, wo, indx,
c = table.config,
$popup = $(elm);
if ($popup.length && c) {
if (!$popup.find('.tablesorter-column-selector').length) {
// add a wrapper to add the selector into, in case the popup has other content
$popup.append('<span class="tablesorter-column-selector"></span>');
}
colSel = c.selector;
wo = c.widgetOptions;
$popup.find('.tablesorter-column-selector')
.html( colSel.$container.html() )
.find('input').each(function(){
var indx = $(this).attr('data-column'),
isChecked = indx === 'auto' ? colSel.auto : colSel.states[indx];
$(this)
.toggleClass( wo.columnSelector_cssChecked, isChecked )
.prop( 'checked', isChecked );
}); });
colSel.$popup = $popup.on('change', 'input', function(){ }
// data input
indx = $(this).toggleClass( wo.columnSelector_cssChecked, this.checked ).attr('data-column');
// update original popup
colSel.$container.find('input[data-column="' + indx + '"]')
.prop('checked', this.checked)
.trigger('change');
});
} }
}
}; };
ts.addWidget({ ts.addWidget({
id: "columnSelector", id: 'columnSelector',
priority: 10, priority: 10,
options: { options: {
// target the column selector markup // target the column selector markup
columnSelector_container : null, columnSelector_container : null,
// column status, true = display, false = hide // column status, true = display, false = hide
// disable = do not display on list // disable = do not display on list
columnSelector_columns : {}, columnSelector_columns : {},
// remember selected columns // remember selected columns
columnSelector_saveColumns: true, columnSelector_saveColumns: true,
// container layout // container layout
columnSelector_layout : '<label><input type="checkbox">{name}</label>', columnSelector_layout : '<label><input type="checkbox">{name}</label>',
// data attribute containing column name to use in the selector container // data attribute containing column name to use in the selector container
columnSelector_name : 'data-selector-name', columnSelector_name : 'data-selector-name',
/* Responsive Media Query settings */ /* Responsive Media Query settings */
// enable/disable mediaquery breakpoints // enable/disable mediaquery breakpoints
columnSelector_mediaquery: true, columnSelector_mediaquery: true,
// toggle checkbox name // toggle checkbox name
columnSelector_mediaqueryName: 'Auto: ', columnSelector_mediaqueryName: 'Auto: ',
// breakpoints checkbox initial setting // breakpoints checkbox initial setting
columnSelector_mediaqueryState: true, columnSelector_mediaqueryState: true,
// responsive table hides columns with priority 1-6 at these breakpoints // responsive table hides columns with priority 1-6 at these breakpoints
// see http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/#Applyingapresetbreakpoint // see http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/#Applyingapresetbreakpoint
// *** set to false to disable *** // *** set to false to disable ***
columnSelector_breakpoints : [ '20em', '30em', '40em', '50em', '60em', '70em' ], columnSelector_breakpoints : [ '20em', '30em', '40em', '50em', '60em', '70em' ],
// data attribute containing column priority // data attribute containing column priority
// duplicates how jQuery mobile uses priorities: // duplicates how jQuery mobile uses priorities:
// http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/ // http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/
columnSelector_priority : 'data-priority', columnSelector_priority : 'data-priority',
// class name added to checked checkboxes - this fixes an issue with Chrome not updating FontAwesome // class name added to checked checkboxes - this fixes an issue with Chrome not updating FontAwesome
// applied icons; use this class name (input.checked) instead of input:checked // applied icons; use this class name (input.checked) instead of input:checked
columnSelector_cssChecked : 'checked' columnSelector_cssChecked : 'checked'
}, },
init: function(table, thisWidget, c, wo) { init: function(table, thisWidget, c, wo) {
tsColSel.init(table, c, wo); tsColSel.init(table, c, wo);
}, },
remove: function(table, c, wo, refreshing) { remove: function(table, c, wo, refreshing) {
if (refreshing) { return; } if (refreshing) { return; }
var csel = c.selector; var csel = c.selector;
csel.$container.empty(); csel.$container.empty();
if (csel.$popup) { csel.$popup.empty(); } if (csel.$popup) { csel.$popup.empty(); }
csel.$style.remove(); csel.$style.remove();
csel.$breakpoints.remove(); csel.$breakpoints.remove();
c.$table.off('updateAll' + namespace + ' update' + namespace); c.$table.off('updateAll' + namespace + ' update' + namespace);
} }
}); });
})(jQuery); })(jQuery);

View File

@ -1,78 +1,78 @@
/*! Widget: columns */ /*! Widget: columns */
;(function ($) { ;(function ($) {
'use strict'; 'use strict';
var ts = $.tablesorter || {}; var ts = $.tablesorter || {};
ts.addWidget({ ts.addWidget({
id: "columns", id: 'columns',
priority: 30, priority: 30,
options : { options : {
columns : [ "primary", "secondary", "tertiary" ] columns : [ 'primary', 'secondary', 'tertiary' ]
}, },
format: function(table, c, wo) { format: function(table, c, wo) {
var $tbody, tbodyIndex, $rows, rows, $row, $cells, remove, indx, var $tbody, tbodyIndex, $rows, rows, $row, $cells, remove, indx,
$table = c.$table, $table = c.$table,
$tbodies = c.$tbodies, $tbodies = c.$tbodies,
sortList = c.sortList, sortList = c.sortList,
len = sortList.length, len = sortList.length,
// removed c.widgetColumns support // removed c.widgetColumns support
css = wo && wo.columns || [ "primary", "secondary", "tertiary" ], css = wo && wo.columns || [ 'primary', 'secondary', 'tertiary' ],
last = css.length - 1; last = css.length - 1;
remove = css.join(' '); remove = css.join(' ');
// check if there is a sort (on initialization there may not be one) // check if there is a sort (on initialization there may not be one)
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // detach tbody $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // detach tbody
$rows = $tbody.children('tr'); $rows = $tbody.children('tr');
// loop through the visible rows // loop through the visible rows
$rows.each(function() { $rows.each(function() {
$row = $(this); $row = $(this);
if (this.style.display !== 'none') { if (this.style.display !== 'none') {
// remove all columns class names // remove all columns class names
$cells = $row.children().removeClass(remove); $cells = $row.children().removeClass(remove);
// add appropriate column class names // add appropriate column class names
if (sortList && sortList[0]) { if (sortList && sortList[0]) {
// primary sort column class // primary sort column class
$cells.eq(sortList[0][0]).addClass(css[0]); $cells.eq(sortList[0][0]).addClass(css[0]);
if (len > 1) { if (len > 1) {
for (indx = 1; indx < len; indx++) { for (indx = 1; indx < len; indx++) {
// secondary, tertiary, etc sort column classes // secondary, tertiary, etc sort column classes
$cells.eq(sortList[indx][0]).addClass( css[indx] || css[last] ); $cells.eq(sortList[indx][0]).addClass( css[indx] || css[last] );
}
} }
} }
} }
} });
}); ts.processTbody(table, $tbody, false);
ts.processTbody(table, $tbody, false); }
} // add classes to thead and tfoot
// add classes to thead and tfoot rows = wo.columns_thead !== false ? [ 'thead tr' ] : [];
rows = wo.columns_thead !== false ? ['thead tr'] : []; if (wo.columns_tfoot !== false) {
if (wo.columns_tfoot !== false) { rows.push('tfoot tr');
rows.push('tfoot tr'); }
} if (rows.length) {
if (rows.length) { $rows = $table.find( rows.join(',') ).children().removeClass(remove);
$rows = $table.find( rows.join(',') ).children().removeClass(remove); if (len) {
if (len) { for (indx = 0; indx < len; indx++) {
for (indx = 0; indx < len; indx++) { // add primary. secondary, tertiary, etc sort column classes
// add primary. secondary, tertiary, etc sort column classes $rows.filter('[data-column="' + sortList[indx][0] + '"]').addClass(css[indx] || css[last]);
$rows.filter('[data-column="' + sortList[indx][0] + '"]').addClass(css[indx] || css[last]); }
} }
} }
},
remove: function(table, c, wo) {
var tbodyIndex, $tbody,
$tbodies = c.$tbodies,
remove = (wo.columns || [ 'primary', 'secondary', 'tertiary' ]).join(' ');
c.$headers.removeClass(remove);
c.$table.children('tfoot').children('tr').children('th, td').removeClass(remove);
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody
$tbody.children('tr').each(function() {
$(this).children().removeClass(remove);
});
ts.processTbody(table, $tbody, false); // restore tbody
}
} }
}, });
remove: function(table, c, wo) {
var tbodyIndex, $tbody,
$tbodies = c.$tbodies,
remove = (wo.columns || [ "primary", "secondary", "tertiary" ]).join(' ');
c.$headers.removeClass(remove);
c.$table.children('tfoot').children('tr').children('th, td').removeClass(remove);
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody
$tbody.children('tr').each(function() {
$(this).children().removeClass(remove);
});
ts.processTbody(table, $tbody, false); // restore tbody
}
}
});
})(jQuery); })(jQuery);

View File

@ -7,254 +7,254 @@
;( function( $ ){ ;( function( $ ){
'use strict'; 'use strict';
var tse = $.tablesorter.editable = { var tse = $.tablesorter.editable = {
namespace : '.tseditable', namespace : '.tseditable',
// last edited class name // last edited class name
lastEdited: 'tseditable-last-edited-cell', lastEdited: 'tseditable-last-edited-cell',
editComplete: function( c, wo, $cell, refocus ) { editComplete: function( c, wo, $cell, refocus ) {
c.$table c.$table
.find( '.' + tse.lastEdited ) .find( '.' + tse.lastEdited )
.removeClass( tse.lastEdited ) .removeClass( tse.lastEdited )
.trigger( wo.editable_editComplete, [ c ] ); .trigger( wo.editable_editComplete, [ c ] );
// restore focus last cell after updating // restore focus last cell after updating
if ( refocus ) { if ( refocus ) {
setTimeout( function() {
$cell.focus();
}, 50 );
}
},
selectAll: function( cell ) {
setTimeout( function() { setTimeout( function() {
$cell.focus(); // select all text in contenteditable
}, 50 ); // see http://stackoverflow.com/a/6150060/145346
} var range, selection;
}, if ( document.body.createTextRange ) {
range = document.body.createTextRange();
selectAll: function( cell ) { range.moveToElementText( cell );
setTimeout( function() { range.select();
// select all text in contenteditable } else if ( window.getSelection ) {
// see http://stackoverflow.com/a/6150060/145346 selection = window.getSelection();
var range, selection; range = document.createRange();
if ( document.body.createTextRange ) { range.selectNodeContents( cell );
range = document.body.createTextRange(); selection.removeAllRanges();
range.moveToElementText( cell ); selection.addRange( range );
range.select();
} else if ( window.getSelection ) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents( cell );
selection.removeAllRanges();
selection.addRange( range );
}
}, 100 );
},
getColumns : function( c, wo ) {
var indx, tmp,
colIndex = [],
cols = [];
if ( !wo.editable_columnsArray && $.type( wo.editable_columns ) === 'string' && wo.editable_columns.indexOf( '-' ) >= 0 ) {
// editable_columns can contain a range string ( i.e. '2-4' )
tmp = wo.editable_columns.split( /\s*-\s*/ );
indx = parseInt( tmp[ 0 ], 10 ) || 0;
tmp = parseInt( tmp[ 1 ], 10 ) || ( c.columns - 1 );
if ( tmp > c.columns ) {
tmp = c.columns - 1;
}
for ( ; indx <= tmp; indx++ ) {
colIndex.push( indx );
cols.push( 'td:nth-child(' + ( indx + 1 ) + ')' );
}
} else if ( $.isArray( wo.editable_columns ) ) {
$.each( wo.editable_columnsArray || wo.editable_columns, function( i, col ) {
if ( col < c.columns ) {
colIndex.push( col );
cols.push( 'td:nth-child(' + ( col + 1 ) + ')' );
} }
}); }, 100 );
} },
if ( !wo.editable_columnsArray ) {
wo.editable_columnsArray = colIndex;
wo.editable_columnsArray.sort(function(a,b){ return a - b; });
}
return cols;
},
update: function( c, wo ) { getColumns : function( c, wo ) {
var $t, var indx, tmp,
tmp = $( '<div>' ).wrapInner( wo.editable_wrapContent ).children().length || $.isFunction( wo.editable_wrapContent ), colIndex = [],
cols = tse.getColumns( c, wo ).join( ',' ); cols = [];
if ( !wo.editable_columnsArray && $.type( wo.editable_columns ) === 'string' && wo.editable_columns.indexOf( '-' ) >= 0 ) {
// turn off contenteditable to allow dynamically setting the wo.editable_noEdit // editable_columns can contain a range string ( i.e. '2-4' )
// class on table cells - see issue #900 tmp = wo.editable_columns.split( /\s*-\s*/ );
c.$tbodies.find( cols ).find( '[contenteditable]' ).prop( 'contenteditable', false ); indx = parseInt( tmp[ 0 ], 10 ) || 0;
tmp = parseInt( tmp[ 1 ], 10 ) || ( c.columns - 1 );
// IE does not allow making TR/TH/TD cells directly editable ( issue #404 ) if ( tmp > c.columns ) {
// so add a div or span inside ( it's faster than using wrapInner() ) tmp = c.columns - 1;
c.$tbodies.find( cols ).not( '.' + wo.editable_noEdit ).each( function() { }
// test for children, if they exist, then make the children editable for ( ; indx <= tmp; indx++ ) {
$t = $( this ); colIndex.push( indx );
cols.push( 'td:nth-child(' + ( indx + 1 ) + ')' );
if ( tmp && $t.children( 'div, span' ).length === 0 ) { }
$t.wrapInner( wo.editable_wrapContent ); } else if ( $.isArray( wo.editable_columns ) ) {
$.each( wo.editable_columnsArray || wo.editable_columns, function( i, col ) {
if ( col < c.columns ) {
colIndex.push( col );
cols.push( 'td:nth-child(' + ( col + 1 ) + ')' );
}
});
} }
if ( $t.children( 'div, span' ).length ) { if ( !wo.editable_columnsArray ) {
// make div/span children content editable wo.editable_columnsArray = colIndex;
$t.children( 'div, span' ).not( '.' + wo.editable_noEdit ).each( function() { wo.editable_columnsArray.sort(function(a, b){ return a - b; });
var $this = $( this ); }
return cols;
},
update: function( c, wo ) {
var $t,
tmp = $( '<div>' ).wrapInner( wo.editable_wrapContent ).children().length || $.isFunction( wo.editable_wrapContent ),
cols = tse.getColumns( c, wo ).join( ',' );
// turn off contenteditable to allow dynamically setting the wo.editable_noEdit
// class on table cells - see issue #900
c.$tbodies.find( cols ).find( '[contenteditable]' ).prop( 'contenteditable', false );
// IE does not allow making TR/TH/TD cells directly editable ( issue #404 )
// so add a div or span inside ( it's faster than using wrapInner() )
c.$tbodies.find( cols ).not( '.' + wo.editable_noEdit ).each( function() {
// test for children, if they exist, then make the children editable
$t = $( this );
if ( tmp && $t.children( 'div, span' ).length === 0 ) {
$t.wrapInner( wo.editable_wrapContent );
}
if ( $t.children( 'div, span' ).length ) {
// make div/span children content editable
$t.children( 'div, span' ).not( '.' + wo.editable_noEdit ).each( function() {
var $this = $( this );
if ( wo.editable_trimContent ) {
$this.html( function( i, txt ) {
return $.trim( txt );
});
}
$this.prop( 'contenteditable', true );
});
} else {
if ( wo.editable_trimContent ) { if ( wo.editable_trimContent ) {
$this.html( function( i, txt ) { $t.html( function( i, txt ) {
return $.trim( txt ); return $.trim( txt );
}); });
} }
$this.prop( 'contenteditable', true ); $t.prop( 'contenteditable', true );
});
} else {
if ( wo.editable_trimContent ) {
$t.html( function( i, txt ) {
return $.trim( txt );
});
}
$t.prop( 'contenteditable', true );
}
});
},
bindEvents: function( c, wo ) {
var namespace = tse.namespace;
c.$table
.off( ( 'updateComplete pagerComplete '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' ) )
.on( 'updateComplete pagerComplete '.split( ' ' ).join( namespace + ' ' ), function() {
tse.update( c, c.widgetOptions );
})
// prevent sort initialized by user click on the header from changing the row indexing before
// updateCell can finish processing the change
.children( 'thead' )
.add( $( c.namespace + '_extra_table' ).children( 'thead' ) )
.off( 'mouseenter' + namespace )
.on( 'mouseenter' + namespace, function() {
if ( c.$table.data( 'contentFocused' ) ) {
// change to 'true' instead of element to allow focusout to process
c.$table.data( 'contentFocused', true );
$( ':focus' ).trigger( 'focusout' );
} }
}); });
},
c.$tbodies bindEvents: function( c, wo ) {
.off( ( 'focus blur focusout keydown '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' ) ) var namespace = tse.namespace;
.on( 'focus' + namespace, '[contenteditable]', function( e ) { c.$table
clearTimeout( $( this ).data( 'timer' ) ); .off( ( 'updateComplete pagerComplete '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' ) )
c.$table.data( 'contentFocused', e.target ); .on( 'updateComplete pagerComplete '.split( ' ' ).join( namespace + ' ' ), function() {
c.table.isUpdating = true; // prevent sorting while editing tse.update( c, c.widgetOptions );
var $this = $( this ), })
selAll = wo.editable_selectAll, // prevent sort initialized by user click on the header from changing the row indexing before
column = $this.closest( 'td' ).index(), // updateCell can finish processing the change
txt = $this.html(); .children( 'thead' )
if ( wo.editable_trimContent ) { .add( $( c.namespace + '_extra_table' ).children( 'thead' ) )
txt = $.trim( txt ); .off( 'mouseenter' + namespace )
} .on( 'mouseenter' + namespace, function() {
// prevent enter from adding into the content if ( c.$table.data( 'contentFocused' ) ) {
$this // change to 'true' instead of element to allow focusout to process
.off( 'keydown' + namespace ) c.$table.data( 'contentFocused', true );
.on( 'keydown' + namespace, function( e ){ $( ':focus' ).trigger( 'focusout' );
if ( wo.editable_enterToAccept && e.which === 13 && !e.shiftKey ) { }
e.preventDefault(); });
}
});
$this.data({ before : txt, original: txt });
if ( typeof wo.editable_focused === 'function' ) { c.$tbodies
wo.editable_focused( txt, column, $this ); .off( ( 'focus blur focusout keydown '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' ) )
} .on( 'focus' + namespace, '[contenteditable]', function( e ) {
clearTimeout( $( this ).data( 'timer' ) );
c.$table.data( 'contentFocused', e.target );
c.table.isUpdating = true; // prevent sorting while editing
var $this = $( this ),
selAll = wo.editable_selectAll,
column = $this.closest( 'td' ).index(),
txt = $this.html();
if ( wo.editable_trimContent ) {
txt = $.trim( txt );
}
// prevent enter from adding into the content
$this
.off( 'keydown' + namespace )
.on( 'keydown' + namespace, function( e ){
if ( wo.editable_enterToAccept && e.which === 13 && !e.shiftKey ) {
e.preventDefault();
}
});
$this.data({ before : txt, original: txt });
if ( selAll ) { if ( typeof wo.editable_focused === 'function' ) {
if ( typeof selAll === 'function' ) { wo.editable_focused( txt, column, $this );
if ( selAll( txt, column, $this ) ) { }
if ( selAll ) {
if ( typeof selAll === 'function' ) {
if ( selAll( txt, column, $this ) ) {
tse.selectAll( $this[0] );
}
} else {
tse.selectAll( $this[0] ); tse.selectAll( $this[0] );
} }
} else {
tse.selectAll( $this[0] );
} }
} })
}) .on( 'blur focusout keydown '.split( ' ' ).join( namespace + ' ' ), '[contenteditable]', function( e ) {
.on( 'blur focusout keydown '.split( ' ' ).join( namespace + ' ' ), '[contenteditable]', function( e ) { if ( !c.$table.data( 'contentFocused' ) ) { return; }
if ( !c.$table.data( 'contentFocused' ) ) { return; } var t, validate,
var t, validate, valid = false,
valid = false, $this = $( e.target ),
$this = $( e.target ), txt = $this.html(),
txt = $this.html(), column = $this.closest( 'td' ).index();
column = $this.closest( 'td' ).index(); if ( wo.editable_trimContent ) {
if ( wo.editable_trimContent ) { txt = $.trim( txt );
txt = $.trim( txt );
}
if ( e.which === 27 ) {
// user cancelled
$this.html( $this.data( 'original' ) ).trigger( 'blur' + namespace );
c.$table.data( 'contentFocused', false );
c.table.isUpdating = false;
return false;
}
// accept on enter ( if set ), alt-enter ( always ) or if autoAccept is set and element is blurred or unfocused
t = e.which === 13 && !e.shiftKey && ( wo.editable_enterToAccept || e.altKey ) || wo.editable_autoAccept && e.type !== 'keydown';
// change if new or user hits enter ( if option set )
if ( t && $this.data( 'before' ) !== txt ) {
validate = wo.editable_validate;
valid = txt;
if ( typeof( validate ) === 'function' ) {
valid = validate( txt, $this.data( 'original' ), column, $this );
} else if ( typeof ( validate = $.tablesorter.getColumnData( c.table, validate, column ) ) === 'function' ) {
valid = validate( txt, $this.data( 'original' ), column, $this );
} }
if ( e.which === 27 ) {
if ( t && valid !== false ) { // user cancelled
c.$table.find( '.' + tse.lastEdited ).removeClass( tse.lastEdited ); $this.html( $this.data( 'original' ) ).trigger( 'blur' + namespace );
$this c.$table.data( 'contentFocused', false );
.addClass( tse.lastEdited ) c.table.isUpdating = false;
.html( valid )
.data( 'before', valid )
.data( 'original', valid )
.trigger( 'change' );
c.$table.trigger( 'updateCell', [ $this.closest( 'td' ), false, function() {
if ( wo.editable_autoResort ) {
setTimeout( function() {
c.$table.trigger( 'sorton', [ c.sortList, function() {
tse.editComplete( c, wo, c.$table.data( 'contentFocused' ), true );
}, true ] );
}, 10 );
} else {
tse.editComplete( c, wo, c.$table.data( 'contentFocused' ) );
}
} ] );
return false; return false;
} }
} else if ( !valid && e.type !== 'keydown' ) { // accept on enter ( if set ), alt-enter ( always ) or if autoAccept is set and element is blurred or unfocused
clearTimeout( $this.data( 'timer' ) ); t = e.which === 13 && !e.shiftKey && ( wo.editable_enterToAccept || e.altKey ) || wo.editable_autoAccept && e.type !== 'keydown';
$this.data( 'timer', setTimeout( function() { // change if new or user hits enter ( if option set )
c.table.isUpdating = false; // clear flag or sorting will be disabled if ( t && $this.data( 'before' ) !== txt ) {
if ( $.isFunction( wo.editable_blur ) ) { validate = wo.editable_validate;
txt = $this.html(); valid = txt;
wo.editable_blur( wo.editable_trimContent ? $.trim( txt ) : txt, column, $this );
if ( typeof validate === 'function' ) {
valid = validate( txt, $this.data( 'original' ), column, $this );
} else if ( typeof ( validate = $.tablesorter.getColumnData( c.table, validate, column ) ) === 'function' ) {
valid = validate( txt, $this.data( 'original' ), column, $this );
} }
}, 100 ) );
// restore original content on blur
$this.html( $this.data( 'original' ) );
}
});
},
destroy : function( c, wo ) {
var namespace = tse.namespace,
cols = tse.getColumns( c, wo ),
tmp = ( 'updateComplete pagerComplete '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' ); if ( t && valid !== false ) {
c.$table.off( tmp ); c.$table.find( '.' + tse.lastEdited ).removeClass( tse.lastEdited );
$this
.addClass( tse.lastEdited )
.html( valid )
.data( 'before', valid )
.data( 'original', valid )
.trigger( 'change' );
c.$table.trigger( 'updateCell', [ $this.closest( 'td' ), false, function() {
if ( wo.editable_autoResort ) {
setTimeout( function() {
c.$table.trigger( 'sorton', [ c.sortList, function() {
tse.editComplete( c, wo, c.$table.data( 'contentFocused' ), true );
}, true ] );
}, 10 );
} else {
tse.editComplete( c, wo, c.$table.data( 'contentFocused' ) );
}
} ] );
return false;
}
} else if ( !valid && e.type !== 'keydown' ) {
clearTimeout( $this.data( 'timer' ) );
$this.data( 'timer', setTimeout( function() {
c.table.isUpdating = false; // clear flag or sorting will be disabled
tmp = ( 'focus blur focusout keydown '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' ); if ( $.isFunction( wo.editable_blur ) ) {
c.$tbodies txt = $this.html();
.off( tmp ) wo.editable_blur( wo.editable_trimContent ? $.trim( txt ) : txt, column, $this );
.find( cols.join( ',' ) ) }
.find( '[contenteditable]' ) }, 100 ) );
.prop( 'contenteditable', false ); // restore original content on blur
} $this.html( $this.data( 'original' ) );
}
});
},
destroy : function( c, wo ) {
var namespace = tse.namespace,
cols = tse.getColumns( c, wo ),
}; tmp = ( 'updateComplete pagerComplete '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' );
c.$table.off( tmp );
tmp = ( 'focus blur focusout keydown '.split( ' ' ).join( namespace + ' ' ) ).replace( /\s+/g, ' ' );
c.$tbodies
.off( tmp )
.find( cols.join( ',' ) )
.find( '[contenteditable]' )
.prop( 'contenteditable', false );
}
};
$.tablesorter.addWidget({ $.tablesorter.addWidget({
id: 'editable', id: 'editable',

View File

@ -8,422 +8,421 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter || {}, var ts = $.tablesorter || {},
// compare option selector class name (jQuery selector) // compare option selector class name (jQuery selector)
compareSelect = '.compare-select', compareSelect = '.compare-select',
tsff = ts.filterFormatter = $.extend( {}, ts.filterFormatter, {
tsff = ts.filterFormatter = $.extend( {}, ts.filterFormatter, { addCompare: function($cell, indx, options){
if (options.compare && $.isArray(options.compare) && options.compare.length > 1) {
addCompare: function($cell, indx, options){ var opt = '',
if (options.compare && $.isArray(options.compare) && options.compare.length > 1) { compareSelectClass = [ compareSelect.slice(1), ' ' + compareSelect.slice(1), '' ],
var opt = '', txt = options.cellText ? '<label class="' + compareSelectClass.join('-label') + indx + '">' + options.cellText + '</label>' : '';
compareSelectClass = [ compareSelect.slice(1), ' ' + compareSelect.slice(1), '' ], $.each(options.compare, function(i, c){
txt = options.cellText ? '<label class="' + compareSelectClass.join('-label') + indx + '">' + options.cellText + '</label>' : ''; opt += '<option ' + (options.selected === i ? 'selected' : '') + '>' + c + '</option>';
$.each(options.compare, function(i, c){ });
opt += '<option ' + (options.selected === i ? 'selected' : '') + '>' + c + '</option>'; $cell
}); .wrapInner('<div class="' + compareSelectClass.join('-wrapper') + indx + '" />')
$cell .prepend( txt + '<select class="' + compareSelectClass.join('') + indx + '" />' )
.wrapInner('<div class="' + compareSelectClass.join('-wrapper') + indx + '" />') .find('select')
.prepend( txt + '<select class="' + compareSelectClass.join('') + indx + '" />' ) .append(opt);
.find('select')
.append(opt);
}
},
updateCompare : function($cell, $input, o) {
var val = $input.val() || '',
num = val.replace(/\s*?[><=]\s*?/g, ''),
compare = val.match(/[><=]/g) || '';
if (o.compare) {
if ($.isArray(o.compare)){
compare = (compare || []).join('') || o.compare[o.selected || 0];
} }
$cell.find(compareSelect).val( compare ); },
}
return [ val, num ];
},
/**********************\ updateCompare : function($cell, $input, o) {
HTML5 Number (spinner) var val = $input.val() || '',
\**********************/ num = val.replace(/\s*?[><=]\s*?/g, ''),
html5Number : function($cell, indx, def5Num) { compare = val.match(/[><=]/g) || '';
var t, o = $.extend({ if (o.compare) {
value : 0, if ($.isArray(o.compare)){
min : 0, compare = (compare || []).join('') || o.compare[o.selected || 0];
max : 100,
step : 1,
delayed : true,
disabled : false,
addToggle : false,
exactMatch : false,
cellText : '',
compare : '',
skipTest: false
}, def5Num),
$input,
// test browser for HTML5 range support
$number = $('<input type="number" style="visibility:hidden;" value="test">').appendTo($cell),
// test if HTML5 number is supported - from Modernizr
numberSupported = o.skipTest || $number.attr('type') === 'number' && $number.val() !== 'test',
$shcell = [],
c = $cell.closest('table')[0].config,
updateNumber = function(delayed, notrigger){
var chkd = o.addToggle ? $cell.find('.toggle').is(':checked') : true,
v = $cell.find('.number').val(),
compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '',
searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) || '' : true;
$input
// add equal to the beginning, so we filter exact numbers
.val( !o.addToggle || chkd ? (compare ? compare : o.exactMatch ? '=' : '') + v : '' )
.trigger( notrigger ? '' : 'search', searchType ).end()
.find('.number').val(v);
if ($cell.find('.number').length) {
$cell.find('.number')[0].disabled = (o.disabled || !chkd);
}
// update sticky header cell
if ($shcell.length) {
$shcell.find('.number').val(v)[0].disabled = (o.disabled || !chkd);
$shcell.find(compareSelect).val(compare);
if (o.addToggle) {
$shcell.find('.toggle')[0].checked = chkd;
} }
$cell.find(compareSelect).val( compare );
} }
}; return [ val, num ];
$number.remove(); },
if (numberSupported) { /**********************\
t = o.addToggle ? '<div class="button"><input id="html5button' + indx + '" type="checkbox" class="toggle" />' + HTML5 Number (spinner)
'<label for="html5button' + indx + '"></label></div>' : ''; \**********************/
t += '<input class="number" type="number" min="' + o.min + '" max="' + o.max + '" value="' + html5Number : function($cell, indx, def5Num) {
o.value + '" step="' + o.step + '" />'; var t, o = $.extend({
// add HTML5 number (spinner) value : 0,
$cell min : 0,
.append(t + '<input type="hidden" />') max : 100,
.find('.toggle, .number').bind('change', function(){ step : 1,
updateNumber(); delayed : true,
}) disabled : false,
.closest('thead').find('th[data-column=' + indx + ']') addToggle : false,
.addClass('filter-parsed') // get exact numbers from column exactMatch : false,
// on reset cellText : '',
.closest('table').bind('filterReset', function(){ compare : '',
if ($.isArray(o.compare)) { skipTest: false
$cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); }, def5Num),
}
// turn off the toggle checkbox $input,
// test browser for HTML5 range support
$number = $('<input type="number" style="visibility:hidden;" value="test">').appendTo($cell),
// test if HTML5 number is supported - from Modernizr
numberSupported = o.skipTest || $number.attr('type') === 'number' && $number.val() !== 'test',
$shcell = [],
c = $cell.closest('table')[0].config,
updateNumber = function(delayed, notrigger){
var chkd = o.addToggle ? $cell.find('.toggle').is(':checked') : true,
v = $cell.find('.number').val(),
compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '',
searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) || '' : true;
$input
// add equal to the beginning, so we filter exact numbers
.val( !o.addToggle || chkd ? (compare ? compare : o.exactMatch ? '=' : '') + v : '' )
.trigger( notrigger ? '' : 'search', searchType ).end()
.find('.number').val(v);
if ($cell.find('.number').length) {
$cell.find('.number')[0].disabled = (o.disabled || !chkd);
}
// update sticky header cell
if ($shcell.length) {
$shcell.find('.number').val(v)[0].disabled = (o.disabled || !chkd);
$shcell.find(compareSelect).val(compare);
if (o.addToggle) { if (o.addToggle) {
$cell.find('.toggle')[0].checked = false; $shcell.find('.toggle')[0].checked = chkd;
if ($shcell.length) {
$shcell.find('.toggle')[0].checked = false;
}
} }
$cell.find('.number').val( o.value ); }
setTimeout(function(){ };
$number.remove();
if (numberSupported) {
t = o.addToggle ? '<div class="button"><input id="html5button' + indx + '" type="checkbox" class="toggle" />' +
'<label for="html5button' + indx + '"></label></div>' : '';
t += '<input class="number" type="number" min="' + o.min + '" max="' + o.max + '" value="' +
o.value + '" step="' + o.step + '" />';
// add HTML5 number (spinner)
$cell
.append(t + '<input type="hidden" />')
.find('.toggle, .number').bind('change', function(){
updateNumber(); updateNumber();
}, 0); })
}); .closest('thead').find('th[data-column=' + indx + ']')
$input = $cell.find('input[type=hidden]').bind('change', function(){ .addClass('filter-parsed') // get exact numbers from column
$cell.find('.number').val( this.value ); // on reset
updateNumber(); .closest('table').bind('filterReset', function(){
}); if ($.isArray(o.compare)) {
$cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] );
// update slider from hidden input, in case of saved filters }
c.$table.bind('filterFomatterUpdate', function(){ // turn off the toggle checkbox
var val = tsff.updateCompare($cell, $input, o)[0] || o.value; if (o.addToggle) {
$cell.find('.number').val( ((val || '') + '').replace(/[><=]/g,'') ); $cell.find('.toggle')[0].checked = false;
updateNumber(false, true); if ($shcell.length) {
ts.filter.formatterUpdated($cell, indx); $shcell.find('.toggle')[0].checked = false;
}); }
}
if (o.compare) { $cell.find('.number').val( o.value );
// add compare select setTimeout(function(){
tsff.addCompare($cell, indx, o); updateNumber();
$cell.find(compareSelect).bind('change', function(){ }, 0);
});
$input = $cell.find('input[type=hidden]').bind('change', function(){
$cell.find('.number').val( this.value );
updateNumber(); updateNumber();
}); });
}
// has sticky headers? // update slider from hidden input, in case of saved filters
c.$table.bind('stickyHeadersInit', function(){ c.$table.bind('filterFomatterUpdate', function(){
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); var val = tsff.updateCompare($cell, $input, o)[0] || o.value;
$shcell $cell.find('.number').val( ((val || '') + '').replace(/[><=]/g, '') );
.append(t) updateNumber(false, true);
.find('.toggle, .number').bind('change', function(){ ts.filter.formatterUpdated($cell, indx);
$cell.find('.number').val( $(this).val() ); });
updateNumber();
});
if (o.compare) { if (o.compare) {
// add compare select // add compare select
tsff.addCompare($shcell, indx, o); tsff.addCompare($cell, indx, o);
$shcell.find(compareSelect).bind('change', function(){ $cell.find(compareSelect).bind('change', function(){
$cell.find(compareSelect).val( $(this).val() );
updateNumber(); updateNumber();
}); });
} }
// has sticky headers?
c.$table.bind('stickyHeadersInit', function(){
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
$shcell
.append(t)
.find('.toggle, .number').bind('change', function(){
$cell.find('.number').val( $(this).val() );
updateNumber();
});
if (o.compare) {
// add compare select
tsff.addCompare($shcell, indx, o);
$shcell.find(compareSelect).bind('change', function(){
$cell.find(compareSelect).val( $(this).val() );
updateNumber();
});
}
updateNumber();
});
updateNumber(); updateNumber();
});
updateNumber();
}
return numberSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
},
/**********************\
HTML5 range slider
\**********************/
html5Range : function($cell, indx, def5Range) {
var o = $.extend({
value : 0,
min : 0,
max : 100,
step : 1,
delayed : true,
valueToHeader : true,
exactMatch : true,
cellText : '',
compare : '',
allText : 'all',
skipTest : false
}, def5Range),
$input,
// test browser for HTML5 range support
$range = $('<input type="range" style="visibility:hidden;" value="test">').appendTo($cell),
// test if HTML5 range is supported - from Modernizr (but I left out the method to detect in Safari 2-4)
// see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/inputtypes.js
rangeSupported = o.skipTest || $range.attr('type') === 'range' && $range.val() !== 'test',
$shcell = [],
c = $cell.closest('table')[0].config,
updateRange = function(v, delayed, notrigger){
/*jshint eqeqeq:false */
// hidden input changes may include compare symbols
v = ( typeof v === "undefined" ? $input.val() : v ).toString().replace(/[<>=]/g,'') || o.value;
var compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '',
t = ' (' + (compare ? compare + v : v == o.min ? o.allText : v) + ')',
searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) || '' : true;
$cell.find('input[type=hidden]')
// add equal to the beginning, so we filter exact numbers
.val( ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ) )
//( val == o.min ? '' : val + (o.exactMatch ? '=' : ''))
.trigger( notrigger ? '' : 'search', searchType ).end()
.find('.range').val(v);
// or add current value to the header cell, if desired
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t);
// update sticky header cell
if ($shcell.length) {
$shcell
.find('.range').val(v).end()
.find(compareSelect).val( compare );
$shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t);
} }
};
$range.remove();
if (rangeSupported) { return numberSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
// add HTML5 range },
$cell
.html('<input type="hidden"><input class="range" type="range" min="' + o.min + '" max="' + o.max + '" value="' + o.value + '" />') /**********************\
.closest('thead').find('th[data-column=' + indx + ']') HTML5 range slider
.addClass('filter-parsed') // get exact numbers from column \**********************/
// add span to header for the current slider value html5Range : function($cell, indx, def5Range) {
.find('.tablesorter-header-inner').append('<span class="curvalue" />'); var o = $.extend({
// hidden filter update namespace trigger by filter widget value : 0,
$input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){ min : 0,
max : 100,
step : 1,
delayed : true,
valueToHeader : true,
exactMatch : true,
cellText : '',
compare : '',
allText : 'all',
skipTest : false
}, def5Range),
$input,
// test browser for HTML5 range support
$range = $('<input type="range" style="visibility:hidden;" value="test">').appendTo($cell),
// test if HTML5 range is supported - from Modernizr (but I left out the method to detect in Safari 2-4)
// see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/inputtypes.js
rangeSupported = o.skipTest || $range.attr('type') === 'range' && $range.val() !== 'test',
$shcell = [],
c = $cell.closest('table')[0].config,
updateRange = function(v, delayed, notrigger){
/*jshint eqeqeq:false */ /*jshint eqeqeq:false */
var v = this.value, // hidden input changes may include compare symbols
compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || ''; v = ( typeof v === 'undefined' ? $input.val() : v ).toString().replace(/[<>=]/g, '') || o.value;
if (v !== this.lastValue) { var compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '',
this.lastValue = ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ); t = ' (' + (compare ? compare + v : v == o.min ? o.allText : v) + ')',
this.value = this.lastValue; searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) || '' : true;
updateRange( v ); $cell.find('input[type=hidden]')
// add equal to the beginning, so we filter exact numbers
.val( ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ) )
// ( val == o.min ? '' : val + (o.exactMatch ? '=' : ''))
.trigger( notrigger ? '' : 'search', searchType ).end()
.find('.range').val(v);
// or add current value to the header cell, if desired
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t);
// update sticky header cell
if ($shcell.length) {
$shcell
.find('.range').val(v).end()
.find(compareSelect).val( compare );
$shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t);
} }
}); };
$range.remove();
$cell.find('.range').bind('change', function(){ if (rangeSupported) {
updateRange( this.value ); // add HTML5 range
}); $cell
.html('<input type="hidden"><input class="range" type="range" min="' + o.min + '" max="' + o.max + '" value="' + o.value + '" />')
// update spinner from hidden input, in case of saved filters .closest('thead').find('th[data-column=' + indx + ']')
c.$table.bind('filterFomatterUpdate', function(){ .addClass('filter-parsed') // get exact numbers from column
var val = tsff.updateCompare($cell, $input, o)[0]; // add span to header for the current slider value
$cell.find('.range').val( val ); .find('.tablesorter-header-inner').append('<span class="curvalue" />');
updateRange(val, false, true); // hidden filter update namespace trigger by filter widget
ts.filter.formatterUpdated($cell, indx); $input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){
}); /*jshint eqeqeq:false */
var v = this.value,
if (o.compare) { compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '';
// add compare select if (v !== this.lastValue) {
tsff.addCompare($cell, indx, o); this.lastValue = ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) );
$cell.find(compareSelect).bind('change', function(){ this.value = this.lastValue;
updateRange(); updateRange( v );
}
}); });
}
// has sticky headers? $cell.find('.range').bind('change', function(){
c.$table.bind('stickyHeadersInit', function(){ updateRange( this.value );
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); });
$shcell
.html('<input class="range" type="range" min="' + o.min + '" max="' + o.max + '" value="' + o.value + '" />') // update spinner from hidden input, in case of saved filters
.find('.range').bind('change', function(){ c.$table.bind('filterFomatterUpdate', function(){
updateRange( $shcell.find('.range').val() ); var val = tsff.updateCompare($cell, $input, o)[0];
}); $cell.find('.range').val( val );
updateRange(); updateRange(val, false, true);
ts.filter.formatterUpdated($cell, indx);
});
if (o.compare) { if (o.compare) {
// add compare select // add compare select
tsff.addCompare($shcell, indx, o); tsff.addCompare($cell, indx, o);
$shcell.find(compareSelect).bind('change', function(){ $cell.find(compareSelect).bind('change', function(){
$cell.find(compareSelect).val( $(this).val() );
updateRange(); updateRange();
}); });
} }
}); // has sticky headers?
c.$table.bind('stickyHeadersInit', function(){
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
$shcell
.html('<input class="range" type="range" min="' + o.min + '" max="' + o.max + '" value="' + o.value + '" />')
.find('.range').bind('change', function(){
updateRange( $shcell.find('.range').val() );
});
updateRange();
// on reset if (o.compare) {
$cell.closest('table').bind('filterReset', function(){ // add compare select
if ($.isArray(o.compare)) { tsff.addCompare($shcell, indx, o);
$cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); $shcell.find(compareSelect).bind('change', function(){
} $cell.find(compareSelect).val( $(this).val() );
setTimeout(function(){ updateRange();
updateRange(o.value, false, true); });
}, 0); }
});
updateRange();
} });
return rangeSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">'); // on reset
}, $cell.closest('table').bind('filterReset', function(){
if ($.isArray(o.compare)) {
$cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] );
}
setTimeout(function(){
updateRange(o.value, false, true);
}, 0);
});
updateRange();
/**********************\
HTML5 Color picker
\**********************/
html5Color: function($cell, indx, defColor) {
var t, o = $.extend({
value : '#000000',
disabled : false,
addToggle : true,
exactMatch : true,
valueToHeader : false,
skipTest : false
}, defColor),
$input,
// Add a hidden input to hold the range values
$color = $('<input type="color" style="visibility:hidden;" value="test">').appendTo($cell),
// test if HTML5 color is supported - from Modernizr
colorSupported = o.skipTest || $color.attr('type') === 'color' && $color.val() !== 'test',
$shcell = [],
c = $cell.closest('table')[0].config,
updateColor = function(v, notrigger){
v = ( typeof v === "undefined" ? $input.val() : v ).toString().replace('=','') || o.value;
var chkd = true,
t = ' (' + v + ')';
if (o.addToggle) {
chkd = $cell.find('.toggle').is(':checked');
}
if ($cell.find('.colorpicker').length) {
$cell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd);
} }
$input return rangeSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
.val( chkd ? v + (o.exactMatch ? '=' : '') : '' ) },
.trigger( !c.$table[0].hasInitialized || notrigger ? '' : 'search' );
if (o.valueToHeader) {
// add current color to the header cell
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t);
} else {
// current color to span in cell
$cell.find('.currentColor').html(t);
}
// update sticky header cell /**********************\
if ($shcell.length) { HTML5 Color picker
$shcell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd); \**********************/
html5Color: function($cell, indx, defColor) {
var t, o = $.extend({
value : '#000000',
disabled : false,
addToggle : true,
exactMatch : true,
valueToHeader : false,
skipTest : false
}, defColor),
$input,
// Add a hidden input to hold the range values
$color = $('<input type="color" style="visibility:hidden;" value="test">').appendTo($cell),
// test if HTML5 color is supported - from Modernizr
colorSupported = o.skipTest || $color.attr('type') === 'color' && $color.val() !== 'test',
$shcell = [],
c = $cell.closest('table')[0].config,
updateColor = function(v, notrigger) {
v = ( typeof v === 'undefined' ? $input.val() : v ).toString().replace('=', '') || o.value;
var chkd = true,
t = ' (' + v + ')';
if (o.addToggle) { if (o.addToggle) {
$shcell.find('.toggle')[0].checked = chkd; chkd = $cell.find('.toggle').is(':checked');
} }
if ($cell.find('.colorpicker').length) {
$cell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd);
}
$input
.val( chkd ? v + (o.exactMatch ? '=' : '') : '' )
.trigger( !c.$table[0].hasInitialized || notrigger ? '' : 'search' );
if (o.valueToHeader) { if (o.valueToHeader) {
// add current color to the header cell // add current color to the header cell
$shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t); $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t);
} else { } else {
// current color to span in cell // current color to span in cell
$shcell.find('.currentColor').html(t); $cell.find('.currentColor').html(t);
} }
}
};
$color.remove();
if (colorSupported) { // update sticky header cell
t = '' + indx + Math.round(Math.random() * 100); if ($shcell.length) {
// add HTML5 color picker $shcell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd);
t = '<div class="color-controls-wrapper">' + if (o.addToggle) {
(o.addToggle ? '<div class="button"><input id="colorbutton' + t + '" type="checkbox" class="toggle" /><label for="colorbutton' + $shcell.find('.toggle')[0].checked = chkd;
t + '"></label></div>' : '') + }
'<input type="hidden"><input class="colorpicker" type="color" />' + if (o.valueToHeader) {
(o.valueToHeader ? '' : '<span class="currentColor">(#000000)</span>') + '</div>'; // add current color to the header cell
$cell.html(t); $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t);
// add span to header for the current color value - only works if the line in the updateColor() function is also un-commented out } else {
if (o.valueToHeader) { // current color to span in cell
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append('<span class="curcolor" />'); $shcell.find('.currentColor').html(t);
} }
$cell.find('.toggle, .colorpicker').bind('change', function(){
updateColor( $cell.find('.colorpicker').val() );
});
// hidden filter update namespace trigger by filter widget
$input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){
updateColor( this.value );
});
// update slider from hidden input, in case of saved filters
c.$table.bind('filterFomatterUpdate', function(){
updateColor( $input.val(), true );
ts.filter.formatterUpdated($cell, indx);
});
// on reset
$cell.closest('table').bind('filterReset', function(){
// just turn off the colorpicker
if (o.addToggle) {
$cell.find('.toggle')[0].checked = false;
} }
// delay needed because default color needs to be set in the filter };
// there is no compare option here, so if addToggle = false, $color.remove();
// default color is #000000 (even with no value set)
setTimeout(function(){
updateColor();
}, 0);
});
// has sticky headers? if (colorSupported) {
c.$table.bind('stickyHeadersInit', function(){ t = '' + indx + Math.round(Math.random() * 100);
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx); // add HTML5 color picker
$shcell t = '<div class="color-controls-wrapper">' +
.html(t) (o.addToggle ? '<div class="button"><input id="colorbutton' + t + '" type="checkbox" class="toggle" /><label for="colorbutton' +
.find('.toggle, .colorpicker').bind('change', function(){ t + '"></label></div>' : '') +
updateColor( $shcell.find('.colorpicker').val() ); '<input type="hidden"><input class="colorpicker" type="color" />' +
}); (o.valueToHeader ? '' : '<span class="currentColor">(#000000)</span>') + '</div>';
updateColor( $shcell.find('.colorpicker').val() ); $cell.html(t);
}); // add span to header for the current color value - only works if the line in the updateColor() function is also un-commented out
if (o.valueToHeader) {
$cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append('<span class="curcolor" />');
}
updateColor( o.value ); $cell.find('.toggle, .colorpicker').bind('change', function(){
updateColor( $cell.find('.colorpicker').val() );
});
// hidden filter update namespace trigger by filter widget
$input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){
updateColor( this.value );
});
// update slider from hidden input, in case of saved filters
c.$table.bind('filterFomatterUpdate', function(){
updateColor( $input.val(), true );
ts.filter.formatterUpdated($cell, indx);
});
// on reset
$cell.closest('table').bind('filterReset', function(){
// just turn off the colorpicker
if (o.addToggle) {
$cell.find('.toggle')[0].checked = false;
}
// delay needed because default color needs to be set in the filter
// there is no compare option here, so if addToggle = false,
// default color is #000000 (even with no value set)
setTimeout(function(){
updateColor();
}, 0);
});
// has sticky headers?
c.$table.bind('stickyHeadersInit', function(){
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx);
$shcell
.html(t)
.find('.toggle, .colorpicker').bind('change', function(){
updateColor( $shcell.find('.colorpicker').val() );
});
updateColor( $shcell.find('.colorpicker').val() );
});
updateColor( o.value );
}
return colorSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
} }
return colorSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
}
}); });
})(jQuery); })(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -4,146 +4,146 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter || {}; var ts = $.tablesorter || {};
ts.filterFormatter = ts.filterFormatter || {}; ts.filterFormatter = ts.filterFormatter || {};
/************************\ /************************\
Select2 Filter Formatter Select2 Filter Formatter
\************************/ \************************/
ts.filterFormatter.select2 = function($cell, indx, select2Def) { ts.filterFormatter.select2 = function($cell, indx, select2Def) {
var o = $.extend({ var o = $.extend({
// select2 filter formatter options // select2 filter formatter options
cellText : '', // Text (wrapped in a label element) cellText : '', // Text (wrapped in a label element)
match : true, // adds "filter-match" to header match : true, // adds 'filter-match' to header
value : '', value : '',
// include ANY select2 options below // include ANY select2 options below
multiple : true, multiple : true,
width : '100%' width : '100%'
}, select2Def ), }, select2Def ),
arry, data, arry, data,
c = $cell.closest('table')[0].config, c = $cell.closest('table')[0].config,
wo = c.widgetOptions, wo = c.widgetOptions,
// Add a hidden input to hold the range values // Add a hidden input to hold the range values
$input = $('<input class="filter" type="hidden">') $input = $('<input class="filter" type="hidden">')
.appendTo($cell) .appendTo($cell)
// hidden filter update namespace trigger by filter widget // hidden filter update namespace trigger by filter widget
.bind('change' + c.namespace + 'filter', function(){ .bind('change' + c.namespace + 'filter', function(){
var val = this.value; var val = this.value;
val = val.replace(/[/()$^]/g, '').split('|'); val = val.replace(/[/()$^]/g, '').split('|');
$cell.find('.select2').select2('val', val); $cell.find('.select2').select2('val', val);
updateSelect2(); updateSelect2();
}), }),
$header = c.$headerIndexed[indx], $header = c.$headerIndexed[indx],
onlyAvail = $header.hasClass(wo.filter_onlyAvail), onlyAvail = $header.hasClass(wo.filter_onlyAvail),
$shcell = [], $shcell = [],
matchPrefix = o.match ? '' : '^', matchPrefix = o.match ? '' : '^',
matchSuffix = o.match ? '' : '$', matchSuffix = o.match ? '' : '$',
// this function updates the hidden input and adds the current values to the header cell text // this function updates the hidden input and adds the current values to the header cell text
updateSelect2 = function() { updateSelect2 = function() {
var arry = false, var arry = false,
v = $cell.find('.select2').select2('val') || o.value || ''; v = $cell.find('.select2').select2('val') || o.value || '';
// convert array to string // convert array to string
if ($.isArray(v)) { if ($.isArray(v)) {
arry = true; arry = true;
v = v.join('\u0000'); v = v.join('\u0000');
} }
// escape special regex characters (http://stackoverflow.com/a/9310752/145346) // escape special regex characters (http://stackoverflow.com/a/9310752/145346)
v = v.replace(/[-[\]{}()*+?.,/\\^$|#\s]/g, '\\$&'); v = v.replace(/[-[\]{}()*+?.,/\\^$|#\s]/g, '\\$&');
// convert string back into an array // convert string back into an array
if (arry) { if (arry) {
v = v.split('\u0000'); v = v.split('\u0000');
} }
$input $input
// add regex, so we filter exact numbers // add regex, so we filter exact numbers
.val( $.isArray(v) && v.length && v.join('') !== '' ? '/(' + matchPrefix + (v || []).join(matchSuffix + '|' + matchPrefix) + matchSuffix + ')/' : '' ) .val( $.isArray(v) && v.length && v.join('') !== '' ? '/(' + matchPrefix + (v || []).join(matchSuffix + '|' + matchPrefix) + matchSuffix + ')/' : '' )
.trigger('search').end() .trigger('search').end()
.find('.select2').select2('val', v); .find('.select2').select2('val', v);
// update sticky header cell // update sticky header cell
if ($shcell.length) { if ($shcell.length) {
$shcell.find('.select2').select2('val', v); $shcell.find('.select2').select2('val', v);
} }
}, },
// get options from table cell content or filter_selectSource (v2.16) // get options from table cell content or filter_selectSource (v2.16)
updateOptions = function(){ updateOptions = function(){
data = []; data = [];
arry = ts.filter.getOptionSource(c.$table[0], indx, onlyAvail) || []; arry = ts.filter.getOptionSource(c.$table[0], indx, onlyAvail) || [];
// build select2 data option // build select2 data option
$.each(arry, function(i,v){ $.each(arry, function(i, v){
data.push({id: v, text: v}); data.push({id: v, text: v});
});
o.data = data;
};
// get filter-match class from option
$header.toggleClass('filter-match', o.match);
if (o.cellText) {
$cell.prepend('<label>' + o.cellText + '</label>');
}
// don't add default in table options if either ajax or
// data options are already defined
if (!(o.ajax && !$.isEmptyObject(o.ajax)) && !o.data) {
updateOptions();
if (onlyAvail) {
c.$table.bind('filterEnd', function(){
updateOptions();
$cell.add($shcell).find('.select2').select2(o);
}); });
o.data = data;
};
// get filter-match class from option
$header.toggleClass('filter-match', o.match);
if (o.cellText) {
$cell.prepend('<label>' + o.cellText + '</label>');
} }
}
// add a select2 hidden input! // don't add default in table options if either ajax or
$('<input class="select2 select2-' + indx + '" type="hidden" />') // data options are already defined
.val(o.value) if (!(o.ajax && !$.isEmptyObject(o.ajax)) && !o.data) {
.appendTo($cell) updateOptions();
.select2(o) if (onlyAvail) {
.bind('change', function(){ c.$table.bind('filterEnd', function(){
updateSelect2(); updateOptions();
}); $cell.add($shcell).find('.select2').select2(o);
});
}
}
// update select2 from filter hidden input, in case of saved filters // add a select2 hidden input!
c.$table.bind('filterFomatterUpdate', function(){ $('<input class="select2 select2-' + indx + '" type="hidden" />')
// value = '/(^x$|^y$)/' => 'x,y'
var val = c.$table.data('lastSearch')[indx] || '';
val = val.replace(/^\/\(\^?/,'').replace(/\$\|\^/g, '|').replace(/\$?\)\/$/g,'').split('|');
$cell.find('.select2').select2('val', val);
updateSelect2();
ts.filter.formatterUpdated($cell, indx);
});
// has sticky headers?
c.$table.bind('stickyHeadersInit', function(){
$shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
// add a select2!
$('<input class="select2 select2-' + indx + '" type="hidden">')
.val(o.value) .val(o.value)
.appendTo($shcell) .appendTo($cell)
.select2(o) .select2(o)
.bind('change', function(){ .bind('change', function(){
$cell.find('.select2').select2('val', $shcell.find('.select2').select2('val') );
updateSelect2(); updateSelect2();
}); });
if (o.cellText) {
$shcell.prepend('<label>' + o.cellText + '</label>');
}
}); // update select2 from filter hidden input, in case of saved filters
c.$table.bind('filterFomatterUpdate', function(){
// on reset // value = '/(^x$|^y$)/' => 'x,y'
c.$table.bind('filterReset', function(){ var val = c.$table.data('lastSearch')[indx] || '';
$cell.find('.select2').select2('val', o.value || ''); val = val.replace(/^\/\(\^?/, '').replace(/\$\|\^/g, '|').replace(/\$?\)\/$/g, '').split('|');
setTimeout(function(){ $cell.find('.select2').select2('val', val);
updateSelect2(); updateSelect2();
}, 0); ts.filter.formatterUpdated($cell, indx);
}); });
updateSelect2(); // has sticky headers?
return $input; c.$table.bind('stickyHeadersInit', function(){
}; $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
// add a select2!
$('<input class="select2 select2-' + indx + '" type="hidden">')
.val(o.value)
.appendTo($shcell)
.select2(o)
.bind('change', function(){
$cell.find('.select2').select2('val', $shcell.find('.select2').select2('val') );
updateSelect2();
});
if (o.cellText) {
$shcell.prepend('<label>' + o.cellText + '</label>');
}
});
// on reset
c.$table.bind('filterReset', function(){
$cell.find('.select2').select2('val', o.value || '');
setTimeout(function(){
updateSelect2();
}, 0);
});
updateSelect2();
return $input;
};
})(jQuery); })(jQuery);

View File

@ -1,6 +1,6 @@
/*! Widget: filter, insideRange filter type - updated 2/23/2015 (v2.21.0) */ /*! Widget: filter, insideRange filter type - updated 2/23/2015 (v2.21.0) */
;(function($){ ;(function($){
'use strict'; 'use strict';
// Add insideRange filter type // Add insideRange filter type
// ============================ // ============================

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
'use strict'; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.formatter = { ts.formatter = {

View File

@ -5,246 +5,246 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.grouping = { ts.grouping = {
types : { types : {
number : function(c, $column, txt, num, group){ number : function(c, $column, txt, num, group){
var value, word; var value, word;
if (num > 1 && txt !== '') { if (num > 1 && txt !== '') {
if ($column.hasClass(ts.css.sortAsc)) { if ($column.hasClass(ts.css.sortAsc)) {
value = Math.floor(parseFloat(txt)/num) * num; value = Math.floor(parseFloat(txt) / num) * num;
return value > parseFloat(group || 0) ? value : parseFloat(group || 0); return value > parseFloat(group || 0) ? value : parseFloat(group || 0);
} else {
value = Math.ceil(parseFloat(txt) / num) * num;
return value < parseFloat(group || num) - value ? parseFloat(group || num) - value : value;
}
} else { } else {
value = Math.ceil(parseFloat(txt)/num) * num; word = (txt + '').match(/\d+/g);
return value < parseFloat(group || num) - value ? parseFloat(group || num) - value : value; return word && word.length >= num ? word[num - 1] : txt || '';
} }
} else { },
word = (txt + '').match(/\d+/g); separator : function(c, $column, txt, num){
var word = (txt + '').split(c.widgetOptions.group_separator);
return $.trim(word && num > 0 && word.length >= num ? word[(num || 1) - 1] : '');
},
word : function(c, $column, txt, num){
var word = (txt + ' ').match(/\w+/g);
return word && word.length >= num ? word[num - 1] : txt || ''; return word && word.length >= num ? word[num - 1] : txt || '';
},
letter : function(c, $column, txt, num){
return txt ? (txt + ' ').substring(0, num) : '';
},
date : function(c, $column, txt, part, group){
var wo = c.widgetOptions,
time = new Date(txt || ''),
hours = time.getHours();
return part === 'year' ? time.getFullYear() :
part === 'month' ? wo.group_months[time.getMonth()] :
part === 'monthyear' ? wo.group_months[time.getMonth()] + ' ' + time.getFullYear() :
part === 'day' ? wo.group_months[time.getMonth()] + ' ' + time.getDate() :
part === 'week' ? wo.group_week[time.getDay()] :
part === 'time' ? ('00' + (hours > 12 ? hours - 12 : hours === 0 ? hours + 12 : hours)).slice(-2) + ':' +
('00' + time.getMinutes()).slice(-2) + ' ' + ('00' + wo.group_time[hours >= 12 ? 1 : 0]).slice(-2) :
wo.group_dateString(time);
} }
}, },
separator : function(c, $column, txt, num){
var word = (txt + '').split(c.widgetOptions.group_separator);
return $.trim(word && num > 0 && word.length >= num ? word[(num || 1) - 1] : '');
},
word : function(c, $column, txt, num){
var word = (txt + ' ').match(/\w+/g);
return word && word.length >= num ? word[num - 1] : txt || '';
},
letter : function(c, $column, txt, num){
return txt ? (txt + ' ').substring(0, num) : '';
},
date : function(c, $column, txt, part, group){
var wo = c.widgetOptions,
time = new Date(txt || ''),
hours = time.getHours();
return part === 'year' ? time.getFullYear() :
part === 'month' ? wo.group_months[time.getMonth()] :
part === 'monthyear' ? wo.group_months[time.getMonth()] + ' ' + time.getFullYear() :
part === 'day' ? wo.group_months[time.getMonth()] + ' ' + time.getDate() :
part === 'week' ? wo.group_week[time.getDay()] :
part === 'time' ? ('00' + (hours > 12 ? hours - 12 : hours === 0 ? hours + 12 : hours)).slice(-2) + ':' +
('00' + time.getMinutes()).slice(-2) + ' ' + ('00' + wo.group_time[hours >= 12 ? 1 : 0]).slice(-2) :
wo.group_dateString(time);
}
},
update : function(table, c, wo){ update : function(table, c, wo){
if ($.isEmptyObject(c.cache)) { return; } if ($.isEmptyObject(c.cache)) { return; }
var rowIndex, tbodyIndex, currentGroup, $rows, groupClass, grouping, norm_rows, saveName, direction, var rowIndex, tbodyIndex, currentGroup, $rows, groupClass, grouping, norm_rows, saveName, direction,
lang = wo.grouping_language, lang = wo.grouping_language,
group = '', group = '',
savedGroup = false, savedGroup = false,
column = c.sortList[0] ? c.sortList[0][0] : -1; column = c.sortList[0] ? c.sortList[0][0] : -1;
c.$table c.$table
.find('tr.group-hidden').removeClass('group-hidden').end() .find('tr.group-hidden').removeClass('group-hidden').end()
.find('tr.group-header').remove(); .find('tr.group-header').remove();
if (wo.group_collapsible) { if (wo.group_collapsible) {
// clear pager saved spacer height (in case the rows are collapsed) // clear pager saved spacer height (in case the rows are collapsed)
c.$table.data('pagerSavedHeight', 0); c.$table.data('pagerSavedHeight', 0);
} }
if (column >= 0 && !c.$headerIndexed[column].hasClass('group-false')) { if (column >= 0 && !c.$headerIndexed[column].hasClass('group-false')) {
wo.group_currentGroup = ''; // save current groups wo.group_currentGroup = ''; // save current groups
wo.group_currentGroups = {}; wo.group_currentGroups = {};
// group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}" // group class finds 'group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}'
groupClass = (c.$headerIndexed[column].attr('class') || '').match(/(group-\w+(-\w+)?)/g); groupClass = (c.$headerIndexed[column].attr('class') || '').match(/(group-\w+(-\w+)?)/g);
// grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ] // 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 grouping = groupClass ? groupClass[0].split('-') : [ 'group', 'letter', 1 ]; // default to letter 1
// save current grouping // save current grouping
if (wo.group_collapsible && wo.group_saveGroups && ts.storage) { if (wo.group_collapsible && wo.group_saveGroups && ts.storage) {
wo.group_currentGroups = ts.storage( table, 'tablesorter-groups' ) || {}; wo.group_currentGroups = ts.storage( table, 'tablesorter-groups' ) || {};
// include direction when grouping numbers > 1 (reversed direction shows different range values) // include direction when grouping numbers > 1 (reversed direction shows different range values)
direction = (grouping[1] === 'number' && grouping[2] > 1) ? 'dir' + c.sortList[0][1] : ''; direction = (grouping[1] === 'number' && grouping[2] > 1) ? 'dir' + c.sortList[0][1] : '';
// combine column, sort direction & grouping as save key // combine column, sort direction & grouping as save key
saveName = wo.group_currentGroup = '' + column + direction + grouping.join(''); saveName = wo.group_currentGroup = '' + column + direction + grouping.join('');
if (!wo.group_currentGroups[saveName]) { if (!wo.group_currentGroups[saveName]) {
wo.group_currentGroups[saveName] = []; wo.group_currentGroups[saveName] = [];
} else { } else {
savedGroup = true; savedGroup = true;
}
} }
} for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) {
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) { norm_rows = c.cache[tbodyIndex].normalized;
norm_rows = c.cache[tbodyIndex].normalized; group = ''; // clear grouping across tbodies
group = ''; // clear grouping across tbodies $rows = c.$tbodies.eq(tbodyIndex).children('tr').not('.' + c.cssChildRow);
$rows = c.$tbodies.eq(tbodyIndex).children('tr').not('.' + c.cssChildRow); for (rowIndex = 0; rowIndex < $rows.length; rowIndex++) {
for (rowIndex = 0; rowIndex < $rows.length; rowIndex++) { if ( $rows.eq(rowIndex).is(':visible') ) {
if ( $rows.eq(rowIndex).is(':visible') ) { // fixes #438
// fixes #438 if (ts.grouping.types[grouping[1]]) {
if (ts.grouping.types[grouping[1]]) { currentGroup = norm_rows[rowIndex] ?
currentGroup = norm_rows[rowIndex] ? ts.grouping.types[grouping[1]]( c, c.$headerIndexed[column], norm_rows[rowIndex][column], /date/.test(groupClass) ?
ts.grouping.types[grouping[1]]( c, c.$headerIndexed[column], norm_rows[rowIndex][column], /date/.test(groupClass) ? grouping[2] : parseInt(grouping[2] || 1, 10) || 1, group, lang ) : currentGroup;
grouping[2] : parseInt(grouping[2] || 1, 10) || 1, group, lang ) : currentGroup; if (group !== currentGroup) {
if (group !== currentGroup) { group = currentGroup;
group = currentGroup; // show range if number > 1
// show range if number > 1 if (grouping[1] === 'number' && grouping[2] > 1 && currentGroup !== '') {
if (grouping[1] === 'number' && grouping[2] > 1 && currentGroup !== '') { currentGroup += ' - ' + (parseInt(currentGroup, 10) +
currentGroup += ' - ' + (parseInt(currentGroup, 10) + ((parseInt(grouping[2], 10) - 1) * (c.$headerIndexed[column].hasClass(ts.css.sortAsc) ? 1 : -1)));
((parseInt(grouping[2],10) - 1) * (c.$headerIndexed[column].hasClass(ts.css.sortAsc) ? 1 : -1))); }
} if ($.isFunction(wo.group_formatter)) {
if ($.isFunction(wo.group_formatter)) { currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup;
currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup; }
} $rows.eq(rowIndex).before('<tr class="group-header ' + c.selectorRemove.slice(1) +
$rows.eq(rowIndex).before('<tr class="group-header ' + c.selectorRemove.slice(1) + '" unselectable="on"' + ( c.tabIndex ? ' tabindex="0"' : '' ) + '><td colspan="' +
'" unselectable="on"' + ( c.tabIndex ? ' tabindex="0"' : '' ) + '><td colspan="' + c.columns + '">' + (wo.group_collapsible ? '<i/>' : '') + '<span class="group-name">' +
c.columns + '">' + (wo.group_collapsible ? '<i/>' : '') + '<span class="group-name">' + currentGroup + '</span><span class="group-count"></span></td></tr>');
currentGroup + '</span><span class="group-count"></span></td></tr>'); if (wo.group_saveGroups && !savedGroup && wo.group_collapsed && wo.group_collapsible) {
if (wo.group_saveGroups && !savedGroup && wo.group_collapsed && wo.group_collapsible) { // all groups start collapsed
// all groups start collapsed wo.group_currentGroups[wo.group_currentGroup].push(currentGroup);
wo.group_currentGroups[wo.group_currentGroup].push(currentGroup); }
} }
} }
} }
} }
} }
c.$table.find('tr.group-header')
.bind('selectstart', false)
.each(function(){
var isHidden, $label, name,
$row = $(this),
$rows = $row.nextUntil('tr.group-header').filter(':visible');
if (wo.group_count || $.isFunction(wo.group_callback)) {
$label = $row.find('.group-count');
if ($label.length) {
if (wo.group_count) {
$label.html( wo.group_count.replace(/\{num\}/g, $rows.length) );
}
if ($.isFunction(wo.group_callback)) {
wo.group_callback($row.find('td'), $rows, column, table);
}
}
}
if (wo.group_saveGroups && wo.group_currentGroups.length && wo.group_currentGroups[wo.group_currentGroup].length) {
name = $row.find('.group-name').text().toLowerCase();
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) {
$row.addClass('collapsed');
$rows.addClass('group-hidden');
}
});
c.$table.trigger(wo.group_complete);
} }
c.$table.find('tr.group-header') },
.bind('selectstart', false)
.each(function(){
var isHidden, $label, name,
$row = $(this),
$rows = $row.nextUntil('tr.group-header').filter(':visible');
if (wo.group_count || $.isFunction(wo.group_callback)) {
$label = $row.find('.group-count');
if ($label.length) {
if (wo.group_count) {
$label.html( wo.group_count.replace(/\{num\}/g, $rows.length) );
}
if ($.isFunction(wo.group_callback)) {
wo.group_callback($row.find('td'), $rows, column, table);
}
}
}
if (wo.group_saveGroups && wo.group_currentGroups.length && wo.group_currentGroups[wo.group_currentGroup].length) {
name = $row.find('.group-name').text().toLowerCase();
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) {
$row.addClass('collapsed');
$rows.addClass('group-hidden');
}
});
c.$table.trigger(wo.group_complete);
}
},
bindEvents : function(table, c, wo){ bindEvents : function(table, c, wo){
if (wo.group_collapsible) { if (wo.group_collapsible) {
wo.group_currentGroups = []; wo.group_currentGroups = [];
// .on() requires jQuery 1.7+ // .on() requires jQuery 1.7+
c.$table.on('click toggleGroup keyup', 'tr.group-header', function(event){ c.$table.on('click toggleGroup keyup', 'tr.group-header', function(event){
event.stopPropagation(); event.stopPropagation();
// pressing enter will toggle the group // pressing enter will toggle the group
if (event.type === 'keyup' && event.which !== 13) { return; } if (event.type === 'keyup' && event.which !== 13) { return; }
var isCollapsed, $groups, indx, var isCollapsed, $groups, indx,
$this = $(this), $this = $(this),
name = $this.find('.group-name').text().toLowerCase(); name = $this.find('.group-name').text().toLowerCase();
// use shift-click to toggle ALL groups // use shift-click to toggle ALL groups
if (event.shiftKey && (event.type === 'click' || event.type ==='keyup')) { if (event.shiftKey && (event.type === 'click' || event.type === 'keyup')) {
$this.siblings('.group-header').trigger('toggleGroup'); $this.siblings('.group-header').trigger('toggleGroup');
}
$this.toggleClass('collapsed');
// nextUntil requires jQuery 1.4+
$this.nextUntil('tr.group-header').toggleClass('group-hidden', $this.hasClass('collapsed') );
// save collapsed groups
if (wo.group_saveGroups && ts.storage) {
$groups = c.$table.find('.group-header');
isCollapsed = $this.hasClass('collapsed');
if (!wo.group_currentGroups[wo.group_currentGroup]) {
wo.group_currentGroups[wo.group_currentGroup] = [];
} }
if (isCollapsed && wo.group_currentGroup) { $this.toggleClass('collapsed');
wo.group_currentGroups[wo.group_currentGroup].push( name ); // nextUntil requires jQuery 1.4+
} else if (wo.group_currentGroup) { $this.nextUntil('tr.group-header').toggleClass('group-hidden', $this.hasClass('collapsed') );
indx = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] ); // save collapsed groups
if (indx > -1) { if (wo.group_saveGroups && ts.storage) {
wo.group_currentGroups[wo.group_currentGroup].splice( indx, 1 ); $groups = c.$table.find('.group-header');
isCollapsed = $this.hasClass('collapsed');
if (!wo.group_currentGroups[wo.group_currentGroup]) {
wo.group_currentGroups[wo.group_currentGroup] = [];
} }
if (isCollapsed && wo.group_currentGroup) {
wo.group_currentGroups[wo.group_currentGroup].push( name );
} else if (wo.group_currentGroup) {
indx = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] );
if (indx > -1) {
wo.group_currentGroups[wo.group_currentGroup].splice( indx, 1 );
}
}
ts.storage( table, 'tablesorter-groups', wo.group_currentGroups );
} }
ts.storage( table, 'tablesorter-groups', wo.group_currentGroups ); });
} }
$(wo.group_saveReset).on('click', function(){
ts.grouping.clearSavedGroups(table);
}); });
c.$table.on('pagerChange.tsgrouping', function(){
ts.grouping.update(table, c, wo);
});
},
clearSavedGroups: function(table){
if (table && ts.storage) {
ts.storage(table, 'tablesorter-groups', '');
ts.grouping.update(table, table.config, table.config.widgetOptions);
}
} }
$(wo.group_saveReset).on('click', function(){
ts.grouping.clearSavedGroups(table); };
});
c.$table.on('pagerChange.tsgrouping', function(){ ts.addWidget({
id: 'group',
priority: 100,
options: {
group_collapsible : true, // make the group header clickable and collapse the rows below it.
group_collapsed : false, // start with all groups collapsed
group_saveGroups : true, // remember collapsed groups
group_saveReset : null, // element to clear saved collapsed groups
group_count : ' ({num})', // if not false, the '{num}' string is replaced with the number of rows in the group
group_separator : '-', // group name separator; used when group-separator-# class is used.
group_formatter : null, // function(txt, column, table, c, wo) { return txt; }
group_callback : null, // function($cell, $rows, column, table){}, callback allowing modification of the group header labels
group_complete : 'groupingComplete', // event triggered on the table when the grouping widget has finished work
// checkbox parser text used for checked/unchecked values
group_checkbox : [ 'checked', 'unchecked' ],
// change these default date names based on your language preferences
group_months : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
group_week : [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
group_time : [ 'AM', 'PM' ],
// this function is used when 'group-date' is set to create the date string
// you can just return date, date.toLocaleString(), date.toLocaleDateString() or d.toLocaleTimeString()
// reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Conversion_getter
group_dateString : function(date) { return date.toLocaleString(); }
},
init: function(table, thisWidget, c, wo){
ts.grouping.bindEvents(table, c, wo);
},
format: function(table, c, wo) {
ts.grouping.update(table, c, wo); ts.grouping.update(table, c, wo);
}); },
}, remove : function(table, c, wo){
c.$table
clearSavedGroups: function(table){ .off('click', 'tr.group-header')
if (table && ts.storage) { .off('pagerChange.tsgrouping')
ts.storage(table, 'tablesorter-groups', ''); .find('.group-hidden').removeClass('group-hidden').end()
ts.grouping.update(table, table.config, table.config.widgetOptions); .find('tr.group-header').remove();
} }
} });
};
ts.addWidget({
id: 'group',
priority: 100,
options: {
group_collapsible : true, // make the group header clickable and collapse the rows below it.
group_collapsed : false, // start with all groups collapsed
group_saveGroups : true, // remember collapsed groups
group_saveReset : null, // element to clear saved collapsed groups
group_count : ' ({num})', // if not false, the "{num}" string is replaced with the number of rows in the group
group_separator : '-', // group name separator; used when group-separator-# class is used.
group_formatter : null, // function(txt, column, table, c, wo) { return txt; }
group_callback : null, // function($cell, $rows, column, table){}, callback allowing modification of the group header labels
group_complete : 'groupingComplete', // event triggered on the table when the grouping widget has finished work
// checkbox parser text used for checked/unchecked values
group_checkbox : [ 'checked', 'unchecked' ],
// change these default date names based on your language preferences
group_months : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
group_week : [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
group_time : [ 'AM', 'PM' ],
// this function is used when "group-date" is set to create the date string
// you can just return date, date.toLocaleString(), date.toLocaleDateString() or d.toLocaleTimeString()
// reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Conversion_getter
group_dateString : function(date) { return date.toLocaleString(); }
},
init: function(table, thisWidget, c, wo){
ts.grouping.bindEvents(table, c, wo);
},
format: function(table, c, wo) {
ts.grouping.update(table, c, wo);
},
remove : function(table, c, wo){
c.$table
.off('click', 'tr.group-header')
.off('pagerChange.tsgrouping')
.find('.group-hidden').removeClass('group-hidden').end()
.find('tr.group-header').remove();
}
});
})(jQuery); })(jQuery);

View File

@ -5,14 +5,14 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.addWidget({ ts.addWidget({
id: 'headerTitles', id: 'headerTitles',
options: { options: {
// use aria-label text // use aria-label text
// e.g. "First Name: Ascending sort applied, activate to apply a descending sort" // e.g. 'First Name: Ascending sort applied, activate to apply a descending sort'
headerTitle_useAria : false, headerTitle_useAria : false,
// add tooltip class // add tooltip class
headerTitle_tooltip : '', headerTitle_tooltip : '',

View File

@ -5,7 +5,7 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($) { ;(function($) {
"use strict"; 'use strict';
var ts = $.tablesorter, var ts = $.tablesorter,
@ -28,10 +28,10 @@
arry = $cells.not($el).map(function(){ arry = $cells.not($el).map(function(){
$t = $(this); $t = $(this);
txt = $t.attr(c.textAttribute); txt = $t.attr(c.textAttribute);
if (typeof txt === "undefined") { if (typeof txt === 'undefined') {
txt = this.textContent || $t.text(); txt = this.textContent || $t.text();
} }
txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0; txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ''), table) || 0;
return isNaN(txt) ? 0 : txt; return isNaN(txt) ? 0 : txt;
}).get(); }).get();
} }
@ -57,15 +57,15 @@
mathAbove = $t.filter('[' + dataAttrib + '^=above]').length; mathAbove = $t.filter('[' + dataAttrib + '^=above]').length;
// ignore filtered rows & rows with data-math="ignore" (and starting row) // ignore filtered rows & rows with data-math="ignore" (and starting row)
if ( ( !$rows.eq(i).hasClass(filtered) && $rows.eq(i).not('[' + dataAttrib + '=ignore]').length && i !== len ) || mathAbove && i !== len ) { if ( ( !$rows.eq(i).hasClass(filtered) && $rows.eq(i).not('[' + dataAttrib + '=ignore]').length && i !== len ) || mathAbove && i !== len ) {
// stop calculating "above", when encountering another "above" // stop calculating 'above', when encountering another 'above'
if (mathAbove) { if (mathAbove) {
i = 0; i = 0;
} else if ($t.length) { } else if ($t.length) {
txt = $t.attr(c.textAttribute); txt = $t.attr(c.textAttribute);
if (typeof txt === "undefined") { if (typeof txt === 'undefined') {
txt = $t[0].textContent || $t.text(); txt = $t[0].textContent || $t.text();
} }
txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0; txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ''), table) || 0;
arry.push(isNaN(txt) ? 0 : txt); arry.push(isNaN(txt) ? 0 : txt);
} }
} }
@ -76,11 +76,11 @@
$t = $(this).children().filter('[data-column=' + cIndex + ']'); $t = $(this).children().filter('[data-column=' + cIndex + ']');
if (!$(this).hasClass(filtered) && $t.not('[' + dataAttrib + '^=above],[' + dataAttrib + '^=col]').length && !$t.is($el)) { if (!$(this).hasClass(filtered) && $t.not('[' + dataAttrib + '^=above],[' + dataAttrib + '^=col]').length && !$t.is($el)) {
txt = $t.attr(c.textAttribute); txt = $t.attr(c.textAttribute);
if (typeof txt === "undefined") { if (typeof txt === 'undefined') {
txt = ($t[0] ? $t[0].textContent : '') || $t.text(); txt = ($t[0] ? $t[0].textContent : '') || $t.text();
} }
// isNaN('') => false // isNaN('') => false
txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0; txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ''), table) || 0;
arry.push(isNaN(txt) ? 0 : txt); arry.push(isNaN(txt) ? 0 : txt);
} }
}); });
@ -102,10 +102,10 @@
col = parseInt( $t.attr('data-column'), 10); col = parseInt( $t.attr('data-column'), 10);
if (!$t.filter('[' + dataAttrib + ']').length && $.inArray(col, wo.math_ignore) < 0) { if (!$t.filter('[' + dataAttrib + ']').length && $.inArray(col, wo.math_ignore) < 0) {
txt = $t.attr(c.textAttribute); txt = $t.attr(c.textAttribute);
if (typeof txt === "undefined") { if (typeof txt === 'undefined') {
txt = ($t[0] ? $t[0].textContent : '') || $t.text(); txt = ($t[0] ? $t[0].textContent : '') || $t.text();
} }
txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0; txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ''), table) || 0;
arry.push(isNaN(txt) ? 0 : txt); arry.push(isNaN(txt) ? 0 : txt);
} }
}); });
@ -133,8 +133,8 @@
$mathCells = c.$table.find('.' + c.cssInfoBlock + ', tfoot').find('[' + dataAttrib + ']'); $mathCells = c.$table.find('.' + c.cssInfoBlock + ', tfoot').find('[' + dataAttrib + ']');
math.mathType( table, wo, $mathCells, wo.math_priority, dataAttrib ); math.mathType( table, wo, $mathCells, wo.math_priority, dataAttrib );
// find the "all" total // find the 'all' total
math.mathType( table, wo, c.$table.find('[' + dataAttrib + '^=all]'), ['all'], dataAttrib ); math.mathType( table, wo, c.$table.find('[' + dataAttrib + '^=all]'), [ 'all' ], dataAttrib );
wo.math_isUpdating = true; wo.math_isUpdating = true;
c.$table.trigger('update'); c.$table.trigger('update');
@ -153,8 +153,8 @@
$cells.filter('[' + dataAttrib + '^=' + type + ']').each(function(){ $cells.filter('[' + dataAttrib + '^=' + type + ']').each(function(){
$t = $(this); $t = $(this);
formula = ($t.attr(dataAttrib) || '').replace(type + '-', ''); formula = ($t.attr(dataAttrib) || '').replace(type + '-', '');
arry = (type === "row") ? math.getRow(table, wo, $t, dataAttrib) : arry = (type === 'row') ? math.getRow(table, wo, $t, dataAttrib) :
(type === "all") ? getAll : math.getColumn(table, wo, $t, type, dataAttrib); (type === 'all') ? getAll : math.getColumn(table, wo, $t, type, dataAttrib);
if (eq[formula]) { if (eq[formula]) {
t = eq[formula](arry); t = eq[formula](arry);
if (table.config.debug && console && console.log) { if (table.config.debug && console && console.log) {
@ -232,7 +232,7 @@
// search for separator for grp & decimal, anything not digit, not +/- sign, not #. // search for separator for grp & decimal, anything not digit, not +/- sign, not #.
result = m.match( /[^\d\-\+#]/g ); result = m.match( /[^\d\-\+#]/g );
decimal = ( result && result[result.length-1] ) || '.'; // treat the right most symbol as decimal decimal = ( result && result[result.length - 1] ) || '.'; // treat the right most symbol as decimal
group = ( result && result[1] && result[0] ) || ','; // treat the left most symbol as group separator group = ( result && result[1] && result[0] ) || ','; // treat the left most symbol as group separator
// split the decimal for the format string if any. // split the decimal for the format string if any.
@ -282,7 +282,7 @@
v[0] = str; v[0] = str;
} }
v[1] = ( m[1] && v[1] ) ? decimal + v[1] : ""; v[1] = ( m[1] && v[1] ) ? decimal + v[1] : '';
// put back any negation, combine integer and fraction, and add back prefix & suffix // put back any negation, combine integer and fraction, and add back prefix & suffix
return prefix + ( ( isNegative ? '-' : '' ) + v[0] + v[1] ) + suffix; return prefix + ( ( isNegative ? '-' : '' ) + v[0] + v[1] ) + suffix;
}; };
@ -304,7 +304,7 @@
}, },
median : function(arry) { median : function(arry) {
// https://gist.github.com/caseyjustus/1166258 // https://gist.github.com/caseyjustus/1166258
arry.sort( function(a,b){ return a - b; } ); arry.sort( function(a, b){ return a - b; } );
var half = Math.floor( arry.length / 2 ); var half = Math.floor( arry.length / 2 );
return (arry.length % 2) ? arry[half] : ( arry[half - 1] + arry[half] ) / 2.0; return (arry.length % 2) ? arry[half] : ( arry[half - 1] + arry[half] ) / 2.0;
}, },
@ -314,12 +314,12 @@
var i, el, var i, el,
modeMap = {}, modeMap = {},
maxCount = 1, maxCount = 1,
modes = [arry[0]]; modes = [ arry[0] ];
for (i = 0; i < arry.length; i++) { for (i = 0; i < arry.length; i++) {
el = arry[i]; el = arry[i];
modeMap[el] = modeMap[el] ? modeMap[el] + 1 : 1; modeMap[el] = modeMap[el] ? modeMap[el] + 1 : 1;
if ( modeMap[el] > maxCount ) { if ( modeMap[el] > maxCount ) {
modes = [el]; modes = [ el ];
maxCount = modeMap[el]; maxCount = modeMap[el];
} else if (modeMap[el] === maxCount) { } else if (modeMap[el] === maxCount) {
modes.push(el); modes.push(el);
@ -327,7 +327,7 @@
} }
} }
// returns arry of modes if there is a tie // returns arry of modes if there is a tie
return modes.sort( function(a,b){ return a - b; } ); return modes.sort( function(a, b){ return a - b; } );
}, },
max : function(arry) { max : function(arry) {
return Math.max.apply( Math, arry ); return Math.max.apply( Math, arry );
@ -336,7 +336,7 @@
return Math.min.apply( Math, arry ); return Math.min.apply( Math, arry );
}, },
range: function(arry) { range: function(arry) {
var v = arry.sort(function(a,b){ return a - b; }); var v = arry.sort(function(a, b){ return a - b; });
return v[ arry.length - 1 ] - v[0]; return v[ arry.length - 1 ] - v[0];
}, },
// common variance equation // common variance equation
@ -374,7 +374,7 @@
// add new widget called repeatHeaders // add new widget called repeatHeaders
// ************************************ // ************************************
ts.addWidget({ ts.addWidget({
id: "math", id: 'math',
priority: 100, priority: 100,
options: { options: {
math_data : 'math', math_data : 'math',
@ -384,7 +384,7 @@
math_mask : '#,##0.00', math_mask : '#,##0.00',
// complete executed after each fucntion // complete executed after each fucntion
math_complete : null, // function($cell, wo, result, value, arry){ return result; }, math_complete : null, // function($cell, wo, result, value, arry){ return result; },
// order of calculation; "all" is last // order of calculation; 'all' is last
math_priority : [ 'row', 'above', 'col' ], math_priority : [ 'row', 'above', 'col' ],
// template for or just prepend the mask prefix & suffix with this HTML // template for or just prepend the mask prefix & suffix with this HTML
// e.g. '<span class="red">{content}</span>' // e.g. '<span class="red">{content}</span>'

View File

@ -7,365 +7,365 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter, var ts = $.tablesorter,
output = ts.output = { output = ts.output = {
event : 'outputTable', event : 'outputTable',
// wrap line breaks & tabs in quotes // wrap line breaks & tabs in quotes
regexQuote : /([\n\t\x09\x0d\x0a]|<[^<]+>)/, // test if cell needs wrapping quotes regexQuote : /([\n\t\x09\x0d\x0a]|<[^<]+>)/, // test if cell needs wrapping quotes
regexBR : /(<br([\s\/])?>|\n)/g, // replace regexBR : /(<br([\s\/])?>|\n)/g, // replace
regexIMG : /<img[^>]+alt\s*=\s*['"]([^'"]+)['"][^>]*>/i, // match regexIMG : /<img[^>]+alt\s*=\s*['"]([^'"]+)['"][^>]*>/i, // match
regexHTML : /<[^<]+>/g, // replace regexHTML : /<[^<]+>/g, // replace
replaceCR : '\x0d\x0a', replaceCR : '\x0d\x0a',
replaceTab : '\x09', replaceTab : '\x09',
popupTitle : 'Output', popupTitle : 'Output',
popupStyle : 'width:100%;height:100%;', // for textarea popupStyle : 'width:100%;height:100%;', // for textarea
message : 'Your device does not support downloading. Please try again in desktop browser.', message : 'Your device does not support downloading. Please try again in desktop browser.',
init : function(c) { init : function(c) {
c.$table c.$table
.off(output.event) .off(output.event)
.on(output.event, function( e ) { .on(output.event, function( e ) {
e.stopPropagation(); e.stopPropagation();
// explicitly use table.config.widgetOptions because we want // explicitly use table.config.widgetOptions because we want
// the most up-to-date values; not the "wo" from initialization // the most up-to-date values; not the 'wo' from initialization
output.process(c, c.widgetOptions); output.process(c, c.widgetOptions);
}); });
}, },
processRow: function(c, $rows, isHeader, isJSON) { processRow: function(c, $rows, isHeader, isJSON) {
var $cell, $cells, cellsLen, rowIndex, row, col, indx, rowspanLen, colspanLen, txt, var $cell, $cells, cellsLen, rowIndex, row, col, indx, rowspanLen, colspanLen, txt,
wo = c.widgetOptions, wo = c.widgetOptions,
tmpRow = [], tmpRow = [],
dupe = wo.output_duplicateSpans, dupe = wo.output_duplicateSpans,
addSpanIndex = isHeader && isJSON && wo.output_headerRows && $.isFunction(wo.output_callbackJSON), addSpanIndex = isHeader && isJSON && wo.output_headerRows && $.isFunction(wo.output_callbackJSON),
cellIndex = 0, cellIndex = 0,
rowsLength = $rows.length; rowsLength = $rows.length;
for ( rowIndex = 0; rowIndex < rowsLength; rowIndex++ ) { for ( rowIndex = 0; rowIndex < rowsLength; rowIndex++ ) {
if (!tmpRow[rowIndex]) { tmpRow[rowIndex] = []; } if (!tmpRow[rowIndex]) { tmpRow[rowIndex] = []; }
cellIndex = 0; cellIndex = 0;
$cells = $rows.eq( rowIndex ).children(); $cells = $rows.eq( rowIndex ).children();
cellsLen = $cells.length; cellsLen = $cells.length;
for ( indx = 0; indx < cellsLen; indx++ ) { for ( indx = 0; indx < cellsLen; indx++ ) {
$cell = $cells.eq( indx ); $cell = $cells.eq( indx );
// process rowspans // process rowspans
if ($cell.filter('[rowspan]').length) { if ($cell.filter('[rowspan]').length) {
rowspanLen = parseInt( $cell.attr('rowspan'), 10) - 1; rowspanLen = parseInt( $cell.attr('rowspan'), 10) - 1;
txt = output.formatData( c, wo, $cell, isHeader ); txt = output.formatData( c, wo, $cell, isHeader );
for (row = 1; row <= rowspanLen; row++) { for (row = 1; row <= rowspanLen; row++) {
if (!tmpRow[rowIndex + row]) { tmpRow[rowIndex + row] = []; } if (!tmpRow[rowIndex + row]) { tmpRow[rowIndex + row] = []; }
tmpRow[rowIndex + row][cellIndex] = isHeader ? txt : dupe ? txt : ''; tmpRow[rowIndex + row][cellIndex] = isHeader ? txt : dupe ? txt : '';
}
} }
} // process colspans
// process colspans if ($cell.filter('[colspan]').length) {
if ($cell.filter('[colspan]').length) { colspanLen = parseInt( $cell.attr('colspan'), 10) - 1;
colspanLen = parseInt( $cell.attr('colspan'), 10) - 1; // allow data-attribute to be an empty string
// allow data-attribute to be an empty string txt = output.formatData( c, wo, $cell, isHeader );
txt = output.formatData( c, wo, $cell, isHeader ); for (col = 1; col <= colspanLen; col++) {
for (col = 1; col <= colspanLen; col++) { // if we're processing the header & making JSON, the header names need to be unique
// if we're processing the header & making JSON, the header names need to be unique if ($cell.filter('[rowspan]').length) {
if ($cell.filter('[rowspan]').length) { rowspanLen = parseInt( $cell.attr('rowspan'), 10);
rowspanLen = parseInt( $cell.attr('rowspan'), 10); for (row = 0; row < rowspanLen; row++) {
for (row = 0; row < rowspanLen; row++) { if (!tmpRow[rowIndex + row]) { tmpRow[rowIndex + row] = []; }
if (!tmpRow[rowIndex + row]) { tmpRow[rowIndex + row] = []; } tmpRow[rowIndex + row][cellIndex + col] = addSpanIndex ?
tmpRow[rowIndex + row][cellIndex + col] = addSpanIndex ? wo.output_callbackJSON($cell, txt, cellIndex + col) ||
txt + '(' + (cellIndex + col) + ')' : isHeader ? txt : dupe ? txt : '';
}
} else {
tmpRow[rowIndex][cellIndex + col] = addSpanIndex ?
wo.output_callbackJSON($cell, txt, cellIndex + col) || wo.output_callbackJSON($cell, txt, cellIndex + col) ||
txt + '(' + (cellIndex + col) + ')' : isHeader ? txt : dupe ? txt : ''; txt + '(' + (cellIndex + col) + ')' : isHeader ? txt : dupe ? txt : '';
} }
} else {
tmpRow[rowIndex][cellIndex + col] = addSpanIndex ?
wo.output_callbackJSON($cell, txt, cellIndex + col) ||
txt + '(' + (cellIndex + col) + ')' : isHeader ? txt : dupe ? txt : '';
} }
} }
}
// skip column if already defined // skip column if already defined
while (typeof tmpRow[rowIndex][cellIndex] !== 'undefined') { cellIndex++; } while (typeof tmpRow[rowIndex][cellIndex] !== 'undefined') { cellIndex++; }
tmpRow[rowIndex][cellIndex] = tmpRow[rowIndex][cellIndex] || tmpRow[rowIndex][cellIndex] = tmpRow[rowIndex][cellIndex] ||
output.formatData( c, wo, $cell, isHeader ); output.formatData( c, wo, $cell, isHeader );
cellIndex++; cellIndex++;
}
}
return ts.output.removeColumns( c, wo, tmpRow );
},
// remove hidden/ignored columns
removeColumns : function( c, wo, arry ) {
var rowIndex, row, colIndex,
data = [],
len = arry.length;
for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
row = arry[ rowIndex ];
data[ rowIndex ] = [];
for ( colIndex = 0; colIndex < c.columns; colIndex++ ) {
if ( !wo.output_hiddenColumnArray[ colIndex ] ) {
data[ rowIndex ].push( row[ colIndex ] );
} }
} }
} return ts.output.removeColumns( c, wo, tmpRow );
return data; },
},
process : function(c, wo) { // remove hidden/ignored columns
var mydata, $this, $rows, headers, csvData, len, rowsLen, tmp, removeColumns : function( c, wo, arry ) {
hasStringify = window.JSON && JSON.hasOwnProperty('stringify'), var rowIndex, row, colIndex,
indx = 0, data = [],
tmpData = (wo.output_separator || ',').toLowerCase(), len = arry.length;
outputJSON = tmpData === 'json', for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
outputArray = tmpData === 'array', row = arry[ rowIndex ];
separator = outputJSON || outputArray ? ',' : wo.output_separator, data[ rowIndex ] = [];
saveRows = wo.output_saveRows, for ( colIndex = 0; colIndex < c.columns; colIndex++ ) {
$el = c.$table; if ( !wo.output_hiddenColumnArray[ colIndex ] ) {
// regex to look for the set separator or HTML data[ rowIndex ].push( row[ colIndex ] );
wo.output_regex = new RegExp('(' + (/\\/.test(separator) ? '\\' : '' ) + separator + ')' ); }
}
}
return data;
},
// make a list of hidden columns process : function(c, wo) {
wo.output_hiddenColumnArray = []; var mydata, $this, $rows, headers, csvData, len, rowsLen, tmp,
for ( indx = 0; indx < c.columns; indx++ ) { hasStringify = window.JSON && JSON.hasOwnProperty('stringify'),
wo.output_hiddenColumnArray[ indx ] = $.inArray( indx, wo.output_ignoreColumns ) > -1 || indx = 0,
c.$headerIndexed[ indx ].css( 'display' ) === 'none'; tmpData = (wo.output_separator || ',').toLowerCase(),
} outputJSON = tmpData === 'json',
outputArray = tmpData === 'array',
separator = outputJSON || outputArray ? ',' : wo.output_separator,
saveRows = wo.output_saveRows,
$el = c.$table;
// regex to look for the set separator or HTML
wo.output_regex = new RegExp('(' + (/\\/.test(separator) ? '\\' : '' ) + separator + ')' );
// get header cells // make a list of hidden columns
$this = $el.find('thead tr:visible').not('.' + (ts.css.filterRow || 'tablesorter-filter-row') ); wo.output_hiddenColumnArray = [];
headers = output.processRow(c, $this, true, outputJSON); for ( indx = 0; indx < c.columns; indx++ ) {
wo.output_hiddenColumnArray[ indx ] = $.inArray( indx, wo.output_ignoreColumns ) > -1 ||
// all tbody rows c.$headerIndexed[ indx ].css( 'display' ) === 'none';
$rows = $el.children('tbody').children('tr');
// get (f)iltered, (v)isible, all rows (look for the first letter only), or jQuery filter selector
$rows = /^f/.test(saveRows) ? $rows.not('.' + (wo.filter_filteredRow || 'filtered') ) :
/^v/.test(saveRows) ? $rows.filter(':visible') :
// look for '.' (class selector), '#' (id selector),
// ':' (basic filters, e.g. ':not()') or '[' (attribute selector start)
/^[.#:\[]/.test(saveRows) ? $rows.filter(saveRows) :
// default to all rows
$rows;
// process to array of arrays
csvData = output.processRow(c, $rows);
if (wo.output_includeFooter) {
// clone, to force the tfoot rows to the end of this selection of rows
// otherwise they appear after the thead (the order in the HTML)
csvData = csvData.concat( output.processRow( c, $el.children('tfoot').children('tr:visible') ) );
}
len = headers.length;
if (outputJSON) {
tmpData = [];
rowsLen = csvData.length;
for ( indx = 0; indx < rowsLen; indx++ ) {
// multiple header rows & output_headerRows = true, pick the last row...
tmp = headers[ ( len > 1 && wo.output_headerRows ) ? indx % len : len - 1 ];
tmpData.push( output.row2Hash( tmp, csvData[ indx ] ) );
} }
// requires JSON stringify; if it doesn't exist, the output will show [object Object],... in the output window // get header cells
mydata = hasStringify ? JSON.stringify(tmpData) : tmpData; $this = $el.find('thead tr:visible').not('.' + (ts.css.filterRow || 'tablesorter-filter-row') );
} else { headers = output.processRow(c, $this, true, outputJSON);
tmp = [ headers[ ( len > 1 && wo.output_headerRows ) ? indx % len : len - 1 ] ];
tmpData = output.row2CSV(wo, wo.output_headerRows ? headers : tmp, outputArray)
.concat( output.row2CSV(wo, csvData, outputArray) );
// stringify the array; if stringify doesn't exist the array will be flattened // all tbody rows
mydata = outputArray && hasStringify ? JSON.stringify(tmpData) : tmpData.join('\n'); $rows = $el.children('tbody').children('tr');
}
// callback; if true returned, continue processing // get (f)iltered, (v)isible, all rows (look for the first letter only), or jQuery filter selector
if ($.isFunction(wo.output_callback) && !wo.output_callback(c, mydata)) { return; } $rows = /^f/.test(saveRows) ? $rows.not('.' + (wo.filter_filteredRow || 'filtered') ) :
/^v/.test(saveRows) ? $rows.filter(':visible') :
// look for '.' (class selector), '#' (id selector),
// ':' (basic filters, e.g. ':not()') or '[' (attribute selector start)
/^[.#:\[]/.test(saveRows) ? $rows.filter(saveRows) :
// default to all rows
$rows;
if ( /p/i.test( wo.output_delivery || '' ) ) { // process to array of arrays
output.popup(mydata, wo.output_popupStyle, outputJSON || outputArray); csvData = output.processRow(c, $rows);
} else {
output.download(wo, mydata);
}
}, // end process if (wo.output_includeFooter) {
// clone, to force the tfoot rows to the end of this selection of rows
row2CSV : function(wo, tmpRow, outputArray) { // otherwise they appear after the thead (the order in the HTML)
var tmp, rowIndex, csvData = csvData.concat( output.processRow( c, $el.children('tfoot').children('tr:visible') ) );
csvData = [],
rowLen = tmpRow.length;
for (rowIndex = 0; rowIndex < rowLen; rowIndex++) {
// remove any blank rows
tmp = ( tmpRow[rowIndex] || [] ).join('').replace(/\"/g,'');
if ( ( tmpRow[rowIndex] || [] ).length > 0 && tmp !== '' ) {
csvData[csvData.length] = outputArray ? tmpRow[rowIndex] : tmpRow[rowIndex].join(wo.output_separator);
} }
}
return csvData;
},
row2Hash : function( keys, values ) { len = headers.length;
var indx,
json = {},
len = values.length;
for ( indx = 0; indx < len; indx++ ) {
if ( indx < keys.length ) {
json[ keys[ indx ] ] = values[ indx ];
}
}
return json;
},
formatData : function(c, wo, $el, isHeader) { if (outputJSON) {
var attr = $el.attr(wo.output_dataAttrib), tmpData = [];
txt = typeof attr !== 'undefined' ? attr : $el.html(), rowsLen = csvData.length;
quotes = (wo.output_separator || ',').toLowerCase(), for ( indx = 0; indx < rowsLen; indx++ ) {
separator = quotes === 'json' || quotes === 'array', // multiple header rows & output_headerRows = true, pick the last row...
// replace " with “ if undefined tmp = headers[ ( len > 1 && wo.output_headerRows ) ? indx % len : len - 1 ];
result = txt.replace(/\"/g, wo.output_replaceQuote || '\u201c'); tmpData.push( output.row2Hash( tmp, csvData[ indx ] ) );
// replace line breaks with \\n & tabs with \\t }
if (!wo.output_trimSpaces) {
result = result.replace(output.regexBR, output.replaceCR).replace(/\t/g, output.replaceTab);
} else {
result = result.replace(output.regexBR, '');
}
// extract img alt text
txt = result.match(output.regexIMG);
if (!wo.output_includeHTML && txt !== null) {
result = txt[1];
}
// replace/remove html
result = wo.output_includeHTML && !isHeader ? result : result.replace(output.regexHTML, '');
result = wo.output_trimSpaces || isHeader ? $.trim(result) : result;
// JSON & array outputs don't need quotes
quotes = separator ? false : wo.output_wrapQuotes || wo.output_regex.test(result) || output.regexQuote.test(result);
result = quotes ? '"' + result + '"' : result;
// formatting callback - added v2.22.4 // requires JSON stringify; if it doesn't exist, the output will show [object Object],... in the output window
if ( typeof wo.output_formatContent === 'function' ) { mydata = hasStringify ? JSON.stringify(tmpData) : tmpData;
return wo.output_formatContent( c, wo, {
isHeader : isHeader,
$cell : $el,
content : result
});
}
return result;
},
popup : function(data, style, wrap) {
var generator = window.open('', output.popupTitle, style);
generator.document.write(
'<html><head><title>' + output.popupTitle + '</title></head><body>' +
'<textarea wrap="' + (wrap ? 'on' : 'off') + '" style="' + output.popupStyle + '">' + data + '\n</textarea>' +
'</body></html>'
);
generator.document.close();
generator.focus();
// select all text and focus within the textarea in the popup
// $(generator.document).find('textarea').select().focus();
return true;
},
// modified from https://github.com/PixelsCommander/Download-File-JS
// & http://html5-demos.appspot.com/static/a.download.html
download : function (wo, data){
var e, blob, gotBlob,
nav = window.navigator,
link = document.createElement('a');
// iOS devices do not support downloading. We have to inform user about this.
if (/(iP)/g.test(nav.userAgent)) {
alert(output.message);
return false;
}
// test for blob support
try {
gotBlob = !!new Blob();
} catch (err) {
gotBlob = false;
}
// Use HTML5 Blob if browser supports it
if ( gotBlob ) {
window.URL = window.URL || window.webkitURL;
// prepend BOM for utf-8 encoding - see https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js#L140
blob = new Blob( [ '\ufeff', data ], { type: wo.output_encoding } );
if (nav.msSaveBlob) {
// IE 10+
nav.msSaveBlob(blob, wo.output_saveFileName);
} else { } else {
// all other browsers tmp = [ headers[ ( len > 1 && wo.output_headerRows ) ? indx % len : len - 1 ] ];
link.href = window.URL.createObjectURL(blob); tmpData = output.row2CSV(wo, wo.output_headerRows ? headers : tmp, outputArray)
link.download = wo.output_saveFileName; .concat( output.row2CSV(wo, csvData, outputArray) );
// Dispatching click event; using $(link).trigger() won't work
if (document.createEvent) { // stringify the array; if stringify doesn't exist the array will be flattened
e = document.createEvent('MouseEvents'); mydata = outputArray && hasStringify ? JSON.stringify(tmpData) : tmpData.join('\n');
// event.initMouseEvent(type, canBubble, cancelable, view, detail, screenX, screenY, clientX, clientY, }
// ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); // callback; if true returned, continue processing
link.dispatchEvent(e); if ($.isFunction(wo.output_callback) && !wo.output_callback(c, mydata)) { return; }
if ( /p/i.test( wo.output_delivery || '' ) ) {
output.popup(mydata, wo.output_popupStyle, outputJSON || outputArray);
} else {
output.download(wo, mydata);
}
}, // end process
row2CSV : function(wo, tmpRow, outputArray) {
var tmp, rowIndex,
csvData = [],
rowLen = tmpRow.length;
for (rowIndex = 0; rowIndex < rowLen; rowIndex++) {
// remove any blank rows
tmp = ( tmpRow[rowIndex] || [] ).join('').replace(/\"/g, '');
if ( ( tmpRow[rowIndex] || [] ).length > 0 && tmp !== '' ) {
csvData[csvData.length] = outputArray ? tmpRow[rowIndex] : tmpRow[rowIndex].join(wo.output_separator);
} }
} }
return false; return csvData;
},
row2Hash : function( keys, values ) {
var indx,
json = {},
len = values.length;
for ( indx = 0; indx < len; indx++ ) {
if ( indx < keys.length ) {
json[ keys[ indx ] ] = values[ indx ];
}
}
return json;
},
formatData : function(c, wo, $el, isHeader) {
var attr = $el.attr(wo.output_dataAttrib),
txt = typeof attr !== 'undefined' ? attr : $el.html(),
quotes = (wo.output_separator || ',').toLowerCase(),
separator = quotes === 'json' || quotes === 'array',
// replace " with “ if undefined
result = txt.replace(/\"/g, wo.output_replaceQuote || '\u201c');
// replace line breaks with \\n & tabs with \\t
if (!wo.output_trimSpaces) {
result = result.replace(output.regexBR, output.replaceCR).replace(/\t/g, output.replaceTab);
} else {
result = result.replace(output.regexBR, '');
}
// extract img alt text
txt = result.match(output.regexIMG);
if (!wo.output_includeHTML && txt !== null) {
result = txt[1];
}
// replace/remove html
result = wo.output_includeHTML && !isHeader ? result : result.replace(output.regexHTML, '');
result = wo.output_trimSpaces || isHeader ? $.trim(result) : result;
// JSON & array outputs don't need quotes
quotes = separator ? false : wo.output_wrapQuotes || wo.output_regex.test(result) || output.regexQuote.test(result);
result = quotes ? '"' + result + '"' : result;
// formatting callback - added v2.22.4
if ( typeof wo.output_formatContent === 'function' ) {
return wo.output_formatContent( c, wo, {
isHeader : isHeader,
$cell : $el,
content : result
});
}
return result;
},
popup : function(data, style, wrap) {
var generator = window.open('', output.popupTitle, style);
generator.document.write(
'<html><head><title>' + output.popupTitle + '</title></head><body>' +
'<textarea wrap="' + (wrap ? 'on' : 'off') + '" style="' + output.popupStyle + '">' + data + '\n</textarea>' +
'</body></html>'
);
generator.document.close();
generator.focus();
// select all text and focus within the textarea in the popup
// $(generator.document).find('textarea').select().focus();
return true;
},
// modified from https://github.com/PixelsCommander/Download-File-JS
// & http://html5-demos.appspot.com/static/a.download.html
download : function (wo, data){
var e, blob, gotBlob,
nav = window.navigator,
link = document.createElement('a');
// iOS devices do not support downloading. We have to inform user about this.
if (/(iP)/g.test(nav.userAgent)) {
alert(output.message);
return false;
}
// test for blob support
try {
gotBlob = !!new Blob();
} catch (err) {
gotBlob = false;
}
// Use HTML5 Blob if browser supports it
if ( gotBlob ) {
window.URL = window.URL || window.webkitURL;
// prepend BOM for utf-8 encoding - see https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js#L140
blob = new Blob( [ '\ufeff', data ], { type: wo.output_encoding } );
if (nav.msSaveBlob) {
// IE 10+
nav.msSaveBlob(blob, wo.output_saveFileName);
} else {
// all other browsers
link.href = window.URL.createObjectURL(blob);
link.download = wo.output_saveFileName;
// Dispatching click event; using $(link).trigger() won't work
if (document.createEvent) {
e = document.createEvent('MouseEvents');
// event.initMouseEvent(type, canBubble, cancelable, view, detail, screenX, screenY, clientX, clientY,
// ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);
e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(e);
}
}
return false;
}
// fallback to force file download (whether supported by server).
// not sure if this actually works in IE9 and older...
window.open( wo.output_encoding + encodeURIComponent(data) + '?download', '_self');
return true;
},
remove : function(c) {
c.$table.off(output.event);
} }
// fallback to force file download (whether supported by server). };
// not sure if this actually works in IE9 and older...
window.open( wo.output_encoding + encodeURIComponent(data) + '?download' , '_self');
return true;
}, ts.addWidget({
id: 'output',
options: {
output_separator : ',', // set to 'json', 'array' or any separator
output_ignoreColumns : [], // columns to ignore [0, 1,... ] (zero-based index)
output_hiddenColumns : false, // include hidden columns in the output
output_includeFooter : false, // include footer rows in the output
output_dataAttrib : 'data-name', // header attrib containing modified header name
output_headerRows : false, // if true, include multiple header rows (JSON only)
output_delivery : 'popup', // popup, download
output_saveRows : 'filtered', // (a)ll, (v)isible, (f)iltered or jQuery filter selector
output_duplicateSpans: true, // duplicate output data in tbody colspan/rowspan
output_replaceQuote : '\u201c;', // left double quote
output_includeHTML : false,
output_trimSpaces : true,
output_wrapQuotes : false,
output_popupStyle : 'width=500,height=300',
output_saveFileName : 'mytable.csv',
// format $cell content callback
output_formatContent : null, // function(config, data){ return data.content; }
// callback executed when processing completes
// return true to continue download/output
// return false to stop delivery & do something else with the data
output_callback : function(config, data){ return true; },
// JSON callback executed when a colspan is encountered in the header
output_callbackJSON : function($cell, txt, cellIndex) { return txt + '(' + (cellIndex) + ')'; },
// the need to modify this for Excel no longer exists
output_encoding : 'data:application/octet-stream;charset=utf8,'
},
init: function(table, thisWidget, c) {
output.init(c);
},
remove: function(table, c){
output.remove(c);
}
remove : function(c) { });
c.$table.off(output.event);
}
};
ts.addWidget({
id: "output",
options: {
output_separator : ',', // set to "json", "array" or any separator
output_ignoreColumns : [], // columns to ignore [0, 1,... ] (zero-based index)
output_hiddenColumns : false, // include hidden columns in the output
output_includeFooter : false, // include footer rows in the output
output_dataAttrib : 'data-name', // header attrib containing modified header name
output_headerRows : false, // if true, include multiple header rows (JSON only)
output_delivery : 'popup', // popup, download
output_saveRows : 'filtered', // (a)ll, (v)isible, (f)iltered or jQuery filter selector
output_duplicateSpans: true, // duplicate output data in tbody colspan/rowspan
output_replaceQuote : '\u201c;', // left double quote
output_includeHTML : false,
output_trimSpaces : true,
output_wrapQuotes : false,
output_popupStyle : 'width=500,height=300',
output_saveFileName : 'mytable.csv',
// format $cell content callback
output_formatContent : null, // function(config, data){ return data.content; }
// callback executed when processing completes
// return true to continue download/output
// return false to stop delivery & do something else with the data
output_callback : function(config, data){ return true; },
// JSON callback executed when a colspan is encountered in the header
output_callbackJSON : function($cell, txt, cellIndex) { return txt + '(' + (cellIndex) + ')'; },
// the need to modify this for Excel no longer exists
output_encoding : 'data:application/octet-stream;charset=utf8,'
},
init: function(table, thisWidget, c) {
output.init(c);
},
remove: function(table, c){
output.remove(c);
}
});
})(jQuery); })(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -4,120 +4,120 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter, var ts = $.tablesorter,
printTable = ts.printTable = { printTable = ts.printTable = {
event : 'printTable', event : 'printTable',
basicStyle : 'table, tr, td, th { border : solid 1px black; border-collapse : collapse; } td, th { padding: 2px; }', basicStyle : 'table, tr, td, th { border : solid 1px black; border-collapse : collapse; } td, th { padding: 2px; }',
init : function(c) { init : function(c) {
c.$table c.$table
.unbind(printTable.event) .unbind(printTable.event)
.bind(printTable.event, function(){ .bind(printTable.event, function(){
// explicitly use table.config.widgetOptions because we want // explicitly use table.config.widgetOptions because we want
// the most up-to-date values; not the "wo" from initialization // the most up-to-date values; not the 'wo' from initialization
printTable.process(c, c.widgetOptions); printTable.process(c, c.widgetOptions);
});
},
process : function(c, wo) {
var $this,
$table = $('<div/>').append(c.$table.clone()),
printStyle = printTable.basicStyle + 'table { width: 100% }' +
// hide filter row
'.tablesorter-filter-row { display: none }' +
// hide sort arrows
'.tablesorter-header { background-image: none !important; }';
// replace content with data-attribute content
$table.find('[' + wo.print_dataAttrib + ']').each(function(){
$this = $(this);
$this.text( $this.attr(wo.print_dataAttrib) );
}); });
},
process : function(c, wo) { // === rows ===
var $this, // Assume 'visible' means rows hidden by the pager (rows set to 'display:none')
$table = $('<div/>').append(c.$table.clone()), // or hidden by a class name which is added to the wo.print_extraCSS definition
printStyle = printTable.basicStyle + 'table { width: 100% }' + if (/a/i.test(wo.print_rows)) {
// hide filter row // force show of all rows
'.tablesorter-filter-row { display: none }' + printStyle += 'tbody tr { display: table-row !important; }';
// hide sort arrows } else if (/f/i.test(wo.print_rows)) {
'.tablesorter-header { background-image: none !important; }'; // add definition to show all non-filtered rows (cells hidden by the pager)
printStyle += 'tbody tr:not(.' + (wo.filter_filteredRow || 'filtered') + ') { display: table-row !important; }';
}
// replace content with data-attribute content // === columns ===
$table.find('[' + wo.print_dataAttrib + ']').each(function(){ // columnSelector -> c.selector.$style
$this = $(this); // Assume 'visible' means hidden columns have a 'display:none' style, or a class name
$this.text( $this.attr(wo.print_dataAttrib) ); // add the definition to the wo.print_extraCSS option
}); if (/s/i.test(wo.print_columns) && c.selector && c.widgets.indexOf('columnSelector') >= 0) {
// show selected (visible) columns; make a copy of the columnSelector widget css (not media queries)
printStyle += wo.columnSelector_mediaquery && c.selector.auto ? '' : c.selector.$style.text();
} else if (/a/i.test(wo.print_columns)) {
// force show all cells
printStyle += 'td, th { display: table-cell !important; }';
}
// === rows === printStyle += wo.print_extraCSS;
// Assume "visible" means rows hidden by the pager (rows set to "display:none")
// or hidden by a class name which is added to the wo.print_extraCSS definition // callback function
if (/a/i.test(wo.print_rows)) { if ( $.isFunction(wo.print_callback) ) {
// force show of all rows wo.print_callback( c, $table, printStyle );
printStyle += 'tbody tr { display: table-row !important; }'; } else {
} else if (/f/i.test(wo.print_rows)) { printTable.printOutput(c, $table.html(), printStyle);
// add definition to show all non-filtered rows (cells hidden by the pager) }
printStyle += 'tbody tr:not(.' + (wo.filter_filteredRow || 'filtered') + ') { display: table-row !important; }';
}, // end process
printOutput : function(c, data, style) {
var wo = c.widgetOptions,
generator = window.open('', wo.print_title, 'width=500,height=300'),
t = wo.print_title || c.$table.find('caption').text() || c.$table[0].id || document.title || 'table';
generator.document.write(
'<html><head><title>' + t + '</title>' +
( wo.print_styleSheet ? '<link rel="stylesheet" href="' + wo.print_styleSheet + '">' : '' ) +
'<style>' + style + '</style>' +
'</head><body>' + data + '</body></html>'
);
generator.document.close();
generator.print();
generator.close();
return true;
},
remove : function(c) {
c.$table.off(printTable.event);
} }
// === columns === };
// columnSelector -> c.selector.$style
// Assume "visible" means hidden columns have a "display:none" style, or a class name ts.addWidget({
// add the definition to the wo.print_extraCSS option id: 'print',
if (/s/i.test(wo.print_columns) && c.selector && c.widgets.indexOf('columnSelector') >= 0) { options: {
// show selected (visible) columns; make a copy of the columnSelector widget css (not media queries) print_title : '', // this option > caption > table id > 'table'
printStyle += wo.columnSelector_mediaquery && c.selector.auto ? '' : c.selector.$style.text(); print_dataAttrib : 'data-name', // header attrib containing modified header name
} else if (/a/i.test(wo.print_columns)) { print_rows : 'filtered', // (a)ll, (v)isible or (f)iltered
// force show all cells print_columns : 'selected', // (a)ll or (s)elected (if columnSelector widget is added)
printStyle += 'td, th { display: table-cell !important; }'; print_extraCSS : '', // add any extra css definitions for the popup window here
print_styleSheet : '', // add the url of your print stylesheet
// callback executed when processing completes
// to continue printing, use the following function:
// function( config, $table, printStyle ) {
// // do something to the table or printStyle string
// $.tablesorter.printTable.printOutput( config, $table.html(), printStyle );
// }
print_callback : null
},
init: function(table, thisWidget, c) {
printTable.init(c);
},
remove: function(table, c){
printTable.remove(c);
} }
printStyle += wo.print_extraCSS; });
// callback function
if ( $.isFunction(wo.print_callback) ) {
wo.print_callback( c, $table, printStyle );
} else {
printTable.printOutput(c, $table.html(), printStyle);
}
}, // end process
printOutput : function(c, data, style) {
var wo = c.widgetOptions,
generator = window.open('', wo.print_title, 'width=500,height=300'),
t = wo.print_title || c.$table.find('caption').text() || c.$table[0].id || document.title || 'table';
generator.document.write(
'<html><head><title>' + t + '</title>' +
( wo.print_styleSheet ? '<link rel="stylesheet" href="' + wo.print_styleSheet + '">' : '' ) +
'<style>' + style + '</style>' +
'</head><body>' + data + '</body></html>'
);
generator.document.close();
generator.print();
generator.close();
return true;
},
remove : function(c) {
c.$table.off(printTable.event);
}
};
ts.addWidget({
id: 'print',
options: {
print_title : '', // this option > caption > table id > "table"
print_dataAttrib : 'data-name', // header attrib containing modified header name
print_rows : 'filtered', // (a)ll, (v)isible or (f)iltered
print_columns : 'selected', // (a)ll or (s)elected (if columnSelector widget is added)
print_extraCSS : '', // add any extra css definitions for the popup window here
print_styleSheet : '', // add the url of your print stylesheet
// callback executed when processing completes
// to continue printing, use the following function:
// function( config, $table, printStyle ) {
// // do something to the table or printStyle string
// $.tablesorter.printTable.printOutput( config, $table.html(), printStyle );
// }
print_callback : null
},
init: function(table, thisWidget, c) {
printTable.init(c);
},
remove: function(table, c){
printTable.remove(c);
}
});
})(jQuery); })(jQuery);

View File

@ -50,131 +50,130 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter, var ts = $.tablesorter,
tablereflow = { tablereflow = {
// simple reflow // simple reflow
// add data-attribute to each cell which shows when media query is active // add data-attribute to each cell which shows when media query is active
// this widget DOES NOT WORK on a table with multiple thead rows // this widget DOES NOT WORK on a table with multiple thead rows
init : function(table, c, wo) { init : function(table, c, wo) {
var $this, var $this,
title = wo.reflow_dataAttrib, title = wo.reflow_dataAttrib,
header = wo.reflow_headerAttrib, header = wo.reflow_headerAttrib,
headers = []; headers = [];
c.$table c.$table
.addClass(wo.reflow_className) .addClass(wo.reflow_className)
.off('refresh.tsreflow updateComplete.tsreflow2') .off('refresh.tsreflow updateComplete.tsreflow2')
// emulate jQuery Mobile refresh // emulate jQuery Mobile refresh
// https://api.jquerymobile.com/table-reflow/#method-refresh // https://api.jquerymobile.com/table-reflow/#method-refresh
.on('refresh.tsreflow updateComplete.tsreflow2', function(){ .on('refresh.tsreflow updateComplete.tsreflow2', function(){
tablereflow.init(table, c, wo); tablereflow.init(table, c, wo);
});
c.$headers.each(function(){
$this = $(this);
headers.push( $.trim( $this.attr(header) || $this.text() ) );
}); });
c.$headers.each(function(){ c.$tbodies.children().each(function(){
$this = $(this); $(this).children().each(function(i){
headers.push( $.trim( $this.attr(header) || $this.text() ) ); $(this).attr(title, headers[i]);
}); });
c.$tbodies.children().each(function(){
$(this).children().each(function(i){
$(this).attr(title, headers[i]);
});
});
},
init2: function(table, c, wo) {
var $this, $tbody, i, $hdr, txt, len,
cols = c.columns,
header = wo.reflow2_headerAttrib,
headers = [];
c.$table
.addClass(wo.reflow2_className)
.off('refresh.tsreflow2 updateComplete.tsreflow2')
// emulate jQuery Mobile refresh
// https://api.jquerymobile.com/table-reflow/#method-refresh
.on('refresh.tsreflow2 updateComplete.tsreflow2', function(){
tablereflow.init2(table, c, wo);
}); });
},
init2: function(table, c, wo) {
var $this, $tbody, i, $hdr, txt, len,
cols = c.columns,
header = wo.reflow2_headerAttrib,
headers = [];
c.$table
.addClass(wo.reflow2_className)
.off('refresh.tsreflow2 updateComplete.tsreflow2')
// emulate jQuery Mobile refresh
// https://api.jquerymobile.com/table-reflow/#method-refresh
.on('refresh.tsreflow2 updateComplete.tsreflow2', function(){
tablereflow.init2(table, c, wo);
});
// add <b> to every table cell with thead cell contents // add <b> to every table cell with thead cell contents
for (i = 0; i < cols; i++) { for (i = 0; i < cols; i++) {
$hdr = c.$headers.filter('[data-column="' + i + '"]'); $hdr = c.$headers.filter('[data-column="' + i + '"]');
if ($hdr.length > 1) { if ($hdr.length > 1) {
txt = []; txt = [];
/*jshint loopfunc:true */ /*jshint loopfunc:true */
$hdr.each(function(){ $hdr.each(function(){
$this = $(this);
if (!$this.hasClass(wo.reflow2_classIgnore)) {
txt.push( $this.attr(header) || $this.text() );
}
});
} else {
txt = [ $hdr.attr(header) || $hdr.text() ];
}
headers.push( txt );
}
// include 'remove-me' class so these additional elements are removed before updating
txt = '<b class="' + c.selectorRemove.slice(1) + ' ' + wo.reflow2_labelClass;
c.$tbodies.children().each(function(){
$tbody = ts.processTbody(table, $(this), true);
$tbody.children().each(function(j){
$this = $(this); $this = $(this);
if (!$this.hasClass(wo.reflow2_classIgnore)) { len = headers[j].length;
txt.push( $this.attr(header) || $this.text() ); i = len - 1;
while (i >= 0) {
$this.prepend(txt + (i === 0 && len > 1 ? ' ' + wo.reflow2_labelTop : '') + '">' + headers[j][i] + '</b>');
i--;
} }
}); });
} else { ts.processTbody(table, $tbody, false);
txt = [ $hdr.attr(header) || $hdr.text() ];
}
headers.push( txt );
}
// include "remove-me" class so these additional elements are removed before updating
txt = '<b class="' + c.selectorRemove.slice(1) + ' ' + wo.reflow2_labelClass;
c.$tbodies.children().each(function(){
$tbody = ts.processTbody(table, $(this), true);
$tbody.children().each(function(j){
$this = $(this);
len = headers[j].length;
i = len - 1;
while (i >= 0) {
$this.prepend(txt + (i === 0 && len > 1 ? ' ' + wo.reflow2_labelTop : '') + '">' + headers[j][i] + '</b>');
i--;
}
}); });
ts.processTbody(table, $tbody, false); },
}); remove : function(table, c, wo) {
}, c.$table.removeClass(wo.reflow_className);
remove : function(table, c, wo) { },
c.$table.removeClass(wo.reflow_className); remove2 : function(table, c, wo) {
}, c.$table.removeClass(wo.reflow2_className);
remove2 : function(table, c, wo) { }
c.$table.removeClass(wo.reflow2_className); };
}
};
ts.addWidget({ ts.addWidget({
id: "reflow", id: 'reflow',
options: { options: {
// class name added to make it responsive (class name within media query) // class name added to make it responsive (class name within media query)
reflow_className : 'ui-table-reflow', reflow_className : 'ui-table-reflow',
// header attribute containing modified header name // header attribute containing modified header name
reflow_headerAttrib : 'data-name', reflow_headerAttrib : 'data-name',
// data attribute added to each tbody cell // data attribute added to each tbody cell
reflow_dataAttrib : 'data-title' reflow_dataAttrib : 'data-title'
}, },
init: function(table, thisWidget, c, wo) { init: function(table, thisWidget, c, wo) {
tablereflow.init(table, c, wo); tablereflow.init(table, c, wo);
}, },
remove: function(table, c, wo){ remove: function(table, c, wo){
tablereflow.remove(table, c, wo); tablereflow.remove(table, c, wo);
} }
}); });
ts.addWidget({
id: "reflow2",
options: {
// class name added to make it responsive (class name within media query)
reflow2_className : 'ui-table-reflow',
// ignore header cell content with this class name
reflow2_classIgnore : 'ui-table-reflow-ignore',
// header attribute containing modified header name
reflow2_headerAttrib : 'data-name',
// class name applied to thead labels
reflow2_labelClass : 'ui-table-cell-label',
// class name applied to first row thead label
reflow2_labelTop : 'ui-table-cell-label-top'
},
init: function(table, thisWidget, c, wo) {
tablereflow.init2(table, c, wo);
},
remove: function(table, c, wo){
tablereflow.remove2(table, c, wo);
}
});
ts.addWidget({
id: 'reflow2',
options: {
// class name added to make it responsive (class name within media query)
reflow2_className : 'ui-table-reflow',
// ignore header cell content with this class name
reflow2_classIgnore : 'ui-table-reflow-ignore',
// header attribute containing modified header name
reflow2_headerAttrib : 'data-name',
// class name applied to thead labels
reflow2_labelClass : 'ui-table-cell-label',
// class name applied to first row thead label
reflow2_labelTop : 'ui-table-cell-label-top'
},
init: function(table, thisWidget, c, wo) {
tablereflow.init2(table, c, wo);
},
remove: function(table, c, wo){
tablereflow.remove2(table, c, wo);
}
});
})(jQuery); })(jQuery);

View File

@ -1,393 +1,394 @@
/*! Widget: resizable - updated 6/26/2015 (v2.22.2) */ /*! Widget: resizable - updated 6/26/2015 (v2.22.2) */
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
;(function ($, window) { ;(function ($, window) {
'use strict'; 'use strict';
var ts = $.tablesorter || {}; var ts = $.tablesorter || {};
$.extend(ts.css, { $.extend(ts.css, {
resizableContainer : 'tablesorter-resizable-container', resizableContainer : 'tablesorter-resizable-container',
resizableHandle : 'tablesorter-resizable-handle', resizableHandle : 'tablesorter-resizable-handle',
resizableNoSelect : 'tablesorter-disableSelection', resizableNoSelect : 'tablesorter-disableSelection',
resizableStorage : 'tablesorter-resizable' resizableStorage : 'tablesorter-resizable'
}); });
// Add extra scroller css // Add extra scroller css
$(function(){ $(function(){
var s = '<style>' + var s = '<style>' +
'body.' + ts.css.resizableNoSelect + ' { -ms-user-select: none; -moz-user-select: -moz-none;' + 'body.' + ts.css.resizableNoSelect + ' { -ms-user-select: none; -moz-user-select: -moz-none;' +
'-khtml-user-select: none; -webkit-user-select: none; user-select: none; }' + '-khtml-user-select: none; -webkit-user-select: none; user-select: none; }' +
'.' + ts.css.resizableContainer + ' { position: relative; height: 1px; }' + '.' + ts.css.resizableContainer + ' { position: relative; height: 1px; }' +
// make handle z-index > than stickyHeader z-index, so the handle stays above sticky header // make handle z-index > than stickyHeader z-index, so the handle stays above sticky header
'.' + ts.css.resizableHandle + ' { position: absolute; display: inline-block; width: 8px;' + '.' + ts.css.resizableHandle + ' { position: absolute; display: inline-block; width: 8px;' +
'top: 1px; cursor: ew-resize; z-index: 3; user-select: none; -moz-user-select: none; }' + 'top: 1px; cursor: ew-resize; z-index: 3; user-select: none; -moz-user-select: none; }' +
'</style>'; '</style>';
$(s).appendTo('body'); $(s).appendTo('body');
}); });
ts.resizable = { ts.resizable = {
init : function( c, wo ) { init : function( c, wo ) {
if ( c.$table.hasClass( 'hasResizable' ) ) { return; } if ( c.$table.hasClass( 'hasResizable' ) ) { return; }
c.$table.addClass( 'hasResizable' ); c.$table.addClass( 'hasResizable' );
var noResize, $header, column, storedSizes, tmp, var noResize, $header, column, storedSizes, tmp,
$table = c.$table, $table = c.$table,
$parent = $table.parent(), $parent = $table.parent(),
marginTop = parseInt( $table.css( 'margin-top' ), 10 ), marginTop = parseInt( $table.css( 'margin-top' ), 10 ),
// internal variables // internal variables
vars = wo.resizable_ = { vars = wo.resizable_vars = {
useStorage : ts.storage && wo.resizable !== false, useStorage : ts.storage && wo.resizable !== false,
$wrap : $parent, $wrap : $parent,
mouseXPosition : 0, mouseXPosition : 0,
$target : null, $target : null,
$next : null, $next : null,
overflow : $parent.css('overflow') === 'auto' || overflow : $parent.css('overflow') === 'auto' ||
$parent.css('overflow') === 'scroll' || $parent.css('overflow') === 'scroll' ||
$parent.css('overflow-x') === 'auto' || $parent.css('overflow-x') === 'auto' ||
$parent.css('overflow-x') === 'scroll', $parent.css('overflow-x') === 'scroll',
storedSizes : [] storedSizes : []
}; };
// set default widths // set default widths
ts.resizableReset( c.table, true ); ts.resizableReset( c.table, true );
// now get measurements! // now get measurements!
vars.tableWidth = $table.width(); vars.tableWidth = $table.width();
// attempt to autodetect // attempt to autodetect
vars.fullWidth = Math.abs( $parent.width() - vars.tableWidth ) < 20; vars.fullWidth = Math.abs( $parent.width() - vars.tableWidth ) < 20;
/* /*
// Hacky method to determine if table width is set to "auto" // Hacky method to determine if table width is set to 'auto'
// http://stackoverflow.com/a/20892048/145346 // http://stackoverflow.com/a/20892048/145346
if ( !vars.fullWidth ) { if ( !vars.fullWidth ) {
tmp = $table.width(); tmp = $table.width();
$header = $table.wrap('<span>').parent(); // temp variable $header = $table.wrap('<span>').parent(); // temp variable
storedSizes = parseInt( $table.css( 'margin-left' ), 10 ) || 0; storedSizes = parseInt( $table.css( 'margin-left' ), 10 ) || 0;
$table.css( 'margin-left', storedSizes + 50 ); $table.css( 'margin-left', storedSizes + 50 );
vars.tableWidth = $header.width() > tmp ? 'auto' : tmp; vars.tableWidth = $header.width() > tmp ? 'auto' : tmp;
$table.css( 'margin-left', storedSizes ? storedSizes : '' ); $table.css( 'margin-left', storedSizes ? storedSizes : '' );
$header = null; $header = null;
$table.unwrap('<span>'); $table.unwrap('<span>');
}
*/
if ( vars.useStorage && vars.overflow ) {
// save table width
ts.storage( c.table, 'tablesorter-table-original-css-width', vars.tableWidth );
tmp = ts.storage( c.table, 'tablesorter-table-resized-width' ) || 'auto';
ts.resizable.setWidth( $table, tmp, true );
}
wo.resizable_.storedSizes = storedSizes = ( vars.useStorage ?
ts.storage( c.table, ts.css.resizableStorage ) :
[] ) || [];
ts.resizable.setWidths( c, wo, storedSizes );
ts.resizable.updateStoredSizes( c, wo );
wo.$resizable_container = $( '<div class="' + ts.css.resizableContainer + '">' )
.css({ top : marginTop })
.insertBefore( $table );
// add container
for ( column = 0; column < c.columns; column++ ) {
$header = c.$headerIndexed[ column ];
tmp = ts.getColumnData( c.table, c.headers, column );
noResize = ts.getData( $header, tmp, 'resizable' ) === 'false';
if ( !noResize ) {
$( '<div class="' + ts.css.resizableHandle + '">' )
.appendTo( wo.$resizable_container )
.attr({
'data-column' : column,
'unselectable' : 'on'
})
.data( 'header', $header )
.bind( 'selectstart', false );
} }
} */
$table.one('tablesorter-initialized', function() {
ts.resizable.setHandlePosition( c, wo );
ts.resizable.bindings( this.config, this.config.widgetOptions );
});
},
updateStoredSizes : function( c, wo ) { if ( vars.useStorage && vars.overflow ) {
var column, $header, // save table width
len = c.columns, ts.storage( c.table, 'tablesorter-table-original-css-width', vars.tableWidth );
vars = wo.resizable_; tmp = ts.storage( c.table, 'tablesorter-table-resized-width' ) || 'auto';
vars.storedSizes = []; ts.resizable.setWidth( $table, tmp, true );
for ( column = 0; column < len; column++ ) { }
$header = c.$headerIndexed[ column ]; wo.resizable_vars.storedSizes = storedSizes = ( vars.useStorage ?
vars.storedSizes[ column ] = $header.is(':visible') ? $header.width() : 0; ts.storage( c.table, ts.css.resizableStorage ) :
} [] ) || [];
}, ts.resizable.setWidths( c, wo, storedSizes );
ts.resizable.updateStoredSizes( c, wo );
setWidth : function( $el, width, overflow ) { wo.$resizable_container = $( '<div class="' + ts.css.resizableContainer + '">' )
// overflow tables need min & max width set as well .css({ top : marginTop })
$el.css({ .insertBefore( $table );
'width' : width, // add container
'min-width' : overflow ? width : '',
'max-width' : overflow ? width : ''
});
},
setWidths : function( c, wo, storedSizes ) {
var column, $temp,
vars = wo.resizable_,
$extra = $( c.namespace + '_extra_headers' ),
$col = c.$table.children( 'colgroup' ).children( 'col' );
storedSizes = storedSizes || vars.storedSizes || [];
// process only if table ID or url match
if ( storedSizes.length ) {
for ( column = 0; column < c.columns; column++ ) { for ( column = 0; column < c.columns; column++ ) {
// set saved resizable widths $header = c.$headerIndexed[ column ];
ts.resizable.setWidth( c.$headerIndexed[ column ], storedSizes[ column ], vars.overflow ); tmp = ts.getColumnData( c.table, c.headers, column );
if ( $extra.length ) { noResize = ts.getData( $header, tmp, 'resizable' ) === 'false';
// stickyHeaders needs to modify min & max width as well if ( !noResize ) {
$temp = $extra.eq( column ).add( $col.eq( column ) ); $( '<div class="' + ts.css.resizableHandle + '">' )
ts.resizable.setWidth( $temp, storedSizes[ column ], vars.overflow ); .appendTo( wo.$resizable_container )
.attr({
'data-column' : column,
'unselectable' : 'on'
})
.data( 'header', $header )
.bind( 'selectstart', false );
} }
} }
$temp = $( c.namespace + '_extra_table' ); $table.one('tablesorter-initialized', function() {
if ( $temp.length && !ts.hasWidget( c.table, 'scroller' ) ) { ts.resizable.setHandlePosition( c, wo );
ts.resizable.setWidth( $temp, c.$table.outerWidth(), vars.overflow ); ts.resizable.bindings( this.config, this.config.widgetOptions );
}
}
},
setHandlePosition : function( c, wo ) {
var startPosition,
hasScroller = ts.hasWidget( c.table, 'scroller' ),
tableHeight = c.$table.height(),
$handles = wo.$resizable_container.children(),
handleCenter = Math.floor( $handles.width() / 2 );
if ( hasScroller ) {
tableHeight = 0;
c.$table.closest( '.' + ts.css.scrollerWrap ).children().each(function(){
var $this = $(this);
// center table has a max-height set
tableHeight += $this.filter('[style*="height"]').length ? $this.height() : $this.children('table').height();
}); });
} },
// subtract out table left position from resizable handles. Fixes #864
startPosition = c.$table.position().left; updateStoredSizes : function( c, wo ) {
$handles.each( function() { var column, $header,
var $this = $(this), len = c.columns,
column = parseInt( $this.attr( 'data-column' ), 10 ), vars = wo.resizable_vars;
columns = c.columns - 1, vars.storedSizes = [];
$header = $this.data( 'header' ); for ( column = 0; column < len; column++ ) {
if ( !$header ) { return; } // see #859 $header = c.$headerIndexed[ column ];
if ( !$header.is(':visible') ) { vars.storedSizes[ column ] = $header.is(':visible') ? $header.width() : 0;
$this.hide(); }
} else if ( column < columns || column === columns && wo.resizable_addLastColumn ) { },
$this.css({
display: 'inline-block', setWidth : function( $el, width, overflow ) {
height : tableHeight, // overflow tables need min & max width set as well
left : $header.position().left - startPosition + $header.outerWidth() - handleCenter $el.css({
'width' : width,
'min-width' : overflow ? width : '',
'max-width' : overflow ? width : ''
});
},
setWidths : function( c, wo, storedSizes ) {
var column, $temp,
vars = wo.resizable_vars,
$extra = $( c.namespace + '_extra_headers' ),
$col = c.$table.children( 'colgroup' ).children( 'col' );
storedSizes = storedSizes || vars.storedSizes || [];
// process only if table ID or url match
if ( storedSizes.length ) {
for ( column = 0; column < c.columns; column++ ) {
// set saved resizable widths
ts.resizable.setWidth( c.$headerIndexed[ column ], storedSizes[ column ], vars.overflow );
if ( $extra.length ) {
// stickyHeaders needs to modify min & max width as well
$temp = $extra.eq( column ).add( $col.eq( column ) );
ts.resizable.setWidth( $temp, storedSizes[ column ], vars.overflow );
}
}
$temp = $( c.namespace + '_extra_table' );
if ( $temp.length && !ts.hasWidget( c.table, 'scroller' ) ) {
ts.resizable.setWidth( $temp, c.$table.outerWidth(), vars.overflow );
}
}
},
setHandlePosition : function( c, wo ) {
var startPosition,
hasScroller = ts.hasWidget( c.table, 'scroller' ),
tableHeight = c.$table.height(),
$handles = wo.$resizable_container.children(),
handleCenter = Math.floor( $handles.width() / 2 );
if ( hasScroller ) {
tableHeight = 0;
c.$table.closest( '.' + ts.css.scrollerWrap ).children().each(function(){
var $this = $(this);
// center table has a max-height set
tableHeight += $this.filter('[style*="height"]').length ? $this.height() : $this.children('table').height();
}); });
} }
}); // subtract out table left position from resizable handles. Fixes #864
}, startPosition = c.$table.position().left;
$handles.each( function() {
// prevent text selection while dragging resize bar var $this = $(this),
toggleTextSelection : function( c, toggle ) { column = parseInt( $this.attr( 'data-column' ), 10 ),
var namespace = c.namespace + 'tsresize'; columns = c.columns - 1,
c.widgetOptions.resizable_.disabled = toggle; $header = $this.data( 'header' );
$( 'body' ).toggleClass( ts.css.resizableNoSelect, toggle ); if ( !$header ) { return; } // see #859
if ( toggle ) { if ( !$header.is(':visible') ) {
$( 'body' ) $this.hide();
.attr( 'unselectable', 'on' ) } else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
.bind( 'selectstart' + namespace, false ); $this.css({
} else { display: 'inline-block',
$( 'body' ) height : tableHeight,
.removeAttr( 'unselectable' ) left : $header.position().left - startPosition + $header.outerWidth() - handleCenter
.unbind( 'selectstart' + namespace ); });
}
},
bindings : function( c, wo ) {
var namespace = c.namespace + 'tsresize';
wo.$resizable_container.children().bind( 'mousedown', function( event ) {
// save header cell and mouse position
var column,
vars = wo.resizable_,
$extras = $( c.namespace + '_extra_headers' ),
$header = $( event.target ).data( 'header' );
column = parseInt( $header.attr( 'data-column' ), 10 );
vars.$target = $header = $header.add( $extras.filter('[data-column="' + column + '"]') );
vars.target = column;
// if table is not as wide as it's parent, then resize the table
vars.$next = event.shiftKey || wo.resizable_targetLast ?
$header.parent().children().not( '.resizable-false' ).filter( ':last' ) :
$header.nextAll( ':not(.resizable-false)' ).eq( 0 );
column = parseInt( vars.$next.attr( 'data-column' ), 10 );
vars.$next = vars.$next.add( $extras.filter('[data-column="' + column + '"]') );
vars.next = column;
vars.mouseXPosition = event.pageX;
ts.resizable.updateStoredSizes( c, wo );
ts.resizable.toggleTextSelection( c, true );
});
$( document )
.bind( 'mousemove' + namespace, function( event ) {
var vars = wo.resizable_;
// ignore mousemove if no mousedown
if ( !vars.disabled || vars.mouseXPosition === 0 || !vars.$target ) { return; }
if ( wo.resizable_throttle ) {
clearTimeout( vars.timer );
vars.timer = setTimeout( function() {
ts.resizable.mouseMove( c, wo, event );
}, isNaN( wo.resizable_throttle ) ? 5 : wo.resizable_throttle );
} else {
ts.resizable.mouseMove( c, wo, event );
} }
})
.bind( 'mouseup' + namespace, function() {
if (!wo.resizable_.disabled) { return; }
ts.resizable.toggleTextSelection( c, false );
ts.resizable.stopResize( c, wo );
ts.resizable.setHandlePosition( c, wo );
}); });
},
// resizeEnd event triggered by scroller widget // prevent text selection while dragging resize bar
$( window ).bind( 'resize' + namespace + ' resizeEnd' + namespace, function() { toggleTextSelection : function( c, toggle ) {
ts.resizable.setHandlePosition( c, wo );
});
// right click to reset columns to default widths
c.$table
.bind( 'columnUpdate' + namespace, function() {
ts.resizable.setHandlePosition( c, wo );
})
.find( 'thead:first' )
.add( $( c.namespace + '_extra_table' ).find( 'thead:first' ) )
.bind( 'contextmenu' + namespace, function() {
// $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset
var allowClick = wo.resizable_.storedSizes.length === 0;
ts.resizableReset( c.table );
ts.resizable.setHandlePosition( c, wo );
wo.resizable_.storedSizes = [];
return allowClick;
});
},
mouseMove : function( c, wo, event ) {
if ( wo.resizable_.mouseXPosition === 0 || !wo.resizable_.$target ) { return; }
// resize columns
var column,
total = 0,
vars = wo.resizable_,
$next = vars.$next,
tar = vars.storedSizes[ vars.target ],
leftEdge = event.pageX - vars.mouseXPosition;
if ( vars.overflow ) {
if ( tar + leftEdge > 0 ) {
vars.storedSizes[ vars.target ] += leftEdge;
ts.resizable.setWidth( vars.$target, vars.storedSizes[ vars.target ], true );
// update the entire table width
for ( column = 0; column < c.columns; column++ ) {
total += vars.storedSizes[ column ];
}
ts.resizable.setWidth( c.$table.add( $( c.namespace + '_extra_table' ) ), total );
}
if ( !$next.length ) {
// if expanding right-most column, scroll the wrapper
vars.$wrap[0].scrollLeft = c.$table.width();
}
} else if ( vars.fullWidth ) {
vars.storedSizes[ vars.target ] += leftEdge;
vars.storedSizes[ vars.next ] -= leftEdge;
ts.resizable.setWidths( c, wo );
} else {
vars.storedSizes[ vars.target ] += leftEdge;
ts.resizable.setWidths( c, wo );
}
vars.mouseXPosition = event.pageX;
// dynamically update sticky header widths
c.$table.trigger('stickyHeadersUpdate');
},
stopResize : function( c, wo ) {
var vars = wo.resizable_;
ts.resizable.updateStoredSizes( c, wo );
if ( vars.useStorage ) {
// save all column widths
ts.storage( c.table, ts.css.resizableStorage, vars.storedSizes );
ts.storage( c.table, 'tablesorter-table-resized-width', c.$table.width() );
}
vars.mouseXPosition = 0;
vars.$target = vars.$next = null;
// will update stickyHeaders, just in case, see #912
c.$table.trigger('stickyHeadersUpdate');
}
};
// this widget saves the column widths if
// $.tablesorter.storage function is included
// **************************
ts.addWidget({
id: "resizable",
priority: 40,
options: {
resizable : true, // save column widths to storage
resizable_addLastColumn : false,
resizable_widths : [],
resizable_throttle : false, // set to true (5ms) or any number 0-10 range
resizable_targetLast : false,
resizable_fullWidth : null
},
init: function(table, thisWidget, c, wo) {
ts.resizable.init( c, wo );
},
remove: function( table, c, wo, refreshing ) {
if (wo.$resizable_container) {
var namespace = c.namespace + 'tsresize'; var namespace = c.namespace + 'tsresize';
c.$table.add( $( c.namespace + '_extra_table' ) ) c.widgetOptions.resizable_vars.disabled = toggle;
.removeClass('hasResizable') $( 'body' ).toggleClass( ts.css.resizableNoSelect, toggle );
.children( 'thead' ).unbind( 'contextmenu' + namespace ); if ( toggle ) {
$( 'body' )
.attr( 'unselectable', 'on' )
.bind( 'selectstart' + namespace, false );
} else {
$( 'body' )
.removeAttr( 'unselectable' )
.unbind( 'selectstart' + namespace );
}
},
bindings : function( c, wo ) {
var namespace = c.namespace + 'tsresize';
wo.$resizable_container.children().bind( 'mousedown', function( event ) {
// save header cell and mouse position
var column,
vars = wo.resizable_vars,
$extras = $( c.namespace + '_extra_headers' ),
$header = $( event.target ).data( 'header' );
column = parseInt( $header.attr( 'data-column' ), 10 );
vars.$target = $header = $header.add( $extras.filter('[data-column="' + column + '"]') );
vars.target = column;
// if table is not as wide as it's parent, then resize the table
vars.$next = event.shiftKey || wo.resizable_targetLast ?
$header.parent().children().not( '.resizable-false' ).filter( ':last' ) :
$header.nextAll( ':not(.resizable-false)' ).eq( 0 );
column = parseInt( vars.$next.attr( 'data-column' ), 10 );
vars.$next = vars.$next.add( $extras.filter('[data-column="' + column + '"]') );
vars.next = column;
vars.mouseXPosition = event.pageX;
ts.resizable.updateStoredSizes( c, wo );
ts.resizable.toggleTextSelection( c, true );
});
$( document )
.bind( 'mousemove' + namespace, function( event ) {
var vars = wo.resizable_vars;
// ignore mousemove if no mousedown
if ( !vars.disabled || vars.mouseXPosition === 0 || !vars.$target ) { return; }
if ( wo.resizable_throttle ) {
clearTimeout( vars.timer );
vars.timer = setTimeout( function() {
ts.resizable.mouseMove( c, wo, event );
}, isNaN( wo.resizable_throttle ) ? 5 : wo.resizable_throttle );
} else {
ts.resizable.mouseMove( c, wo, event );
}
})
.bind( 'mouseup' + namespace, function() {
if (!wo.resizable_vars.disabled) { return; }
ts.resizable.toggleTextSelection( c, false );
ts.resizable.stopResize( c, wo );
ts.resizable.setHandlePosition( c, wo );
});
// resizeEnd event triggered by scroller widget
$( window ).bind( 'resize' + namespace + ' resizeEnd' + namespace, function() {
ts.resizable.setHandlePosition( c, wo );
});
// right click to reset columns to default widths
c.$table
.bind( 'columnUpdate' + namespace, function() {
ts.resizable.setHandlePosition( c, wo );
})
.find( 'thead:first' )
.add( $( c.namespace + '_extra_table' ).find( 'thead:first' ) )
.bind( 'contextmenu' + namespace, function() {
// $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset
var allowClick = wo.resizable_vars.storedSizes.length === 0;
ts.resizableReset( c.table );
ts.resizable.setHandlePosition( c, wo );
wo.resizable_vars.storedSizes = [];
return allowClick;
});
},
mouseMove : function( c, wo, event ) {
if ( wo.resizable_vars.mouseXPosition === 0 || !wo.resizable_vars.$target ) { return; }
// resize columns
var column,
total = 0,
vars = wo.resizable_vars,
$next = vars.$next,
tar = vars.storedSizes[ vars.target ],
leftEdge = event.pageX - vars.mouseXPosition;
if ( vars.overflow ) {
if ( tar + leftEdge > 0 ) {
vars.storedSizes[ vars.target ] += leftEdge;
ts.resizable.setWidth( vars.$target, vars.storedSizes[ vars.target ], true );
// update the entire table width
for ( column = 0; column < c.columns; column++ ) {
total += vars.storedSizes[ column ];
}
ts.resizable.setWidth( c.$table.add( $( c.namespace + '_extra_table' ) ), total );
}
if ( !$next.length ) {
// if expanding right-most column, scroll the wrapper
vars.$wrap[0].scrollLeft = c.$table.width();
}
} else if ( vars.fullWidth ) {
vars.storedSizes[ vars.target ] += leftEdge;
vars.storedSizes[ vars.next ] -= leftEdge;
ts.resizable.setWidths( c, wo );
} else {
vars.storedSizes[ vars.target ] += leftEdge;
ts.resizable.setWidths( c, wo );
}
vars.mouseXPosition = event.pageX;
// dynamically update sticky header widths
c.$table.trigger('stickyHeadersUpdate');
},
stopResize : function( c, wo ) {
var vars = wo.resizable_vars;
ts.resizable.updateStoredSizes( c, wo );
if ( vars.useStorage ) {
// save all column widths
ts.storage( c.table, ts.css.resizableStorage, vars.storedSizes );
ts.storage( c.table, 'tablesorter-table-resized-width', c.$table.width() );
}
vars.mouseXPosition = 0;
vars.$target = vars.$next = null;
// will update stickyHeaders, just in case, see #912
c.$table.trigger('stickyHeadersUpdate');
}
};
// this widget saves the column widths if
// $.tablesorter.storage function is included
// **************************
ts.addWidget({
id: 'resizable',
priority: 40,
options: {
resizable : true, // save column widths to storage
resizable_addLastColumn : false,
resizable_widths : [],
resizable_throttle : false, // set to true (5ms) or any number 0-10 range
resizable_targetLast : false,
resizable_fullWidth : null
},
init: function(table, thisWidget, c, wo) {
ts.resizable.init( c, wo );
},
remove: function( table, c, wo, refreshing ) {
if (wo.$resizable_container) {
var namespace = c.namespace + 'tsresize';
c.$table.add( $( c.namespace + '_extra_table' ) )
.removeClass('hasResizable')
.children( 'thead' )
.unbind( 'contextmenu' + namespace );
wo.$resizable_container.remove(); wo.$resizable_container.remove();
ts.resizable.toggleTextSelection( c, false ); ts.resizable.toggleTextSelection( c, false );
ts.resizableReset( table, refreshing ); ts.resizableReset( table, refreshing );
$( document ).unbind( 'mousemove' + namespace + ' mouseup' + namespace ); $( document ).unbind( 'mousemove' + namespace + ' mouseup' + namespace );
}
}
});
ts.resizableReset = function( table, refreshing ) {
$( table ).each(function(){
var index, $t,
c = this.config,
wo = c && c.widgetOptions,
vars = wo.resizable_;
if ( table && c && c.$headerIndexed.length ) {
// restore the initial table width
if ( vars.overflow && vars.tableWidth ) {
ts.resizable.setWidth( c.$table, vars.tableWidth, true );
if ( vars.useStorage ) {
ts.storage( table, 'tablesorter-table-resized-width', 'auto' );
}
}
for ( index = 0; index < c.columns; index++ ) {
$t = c.$headerIndexed[ index ];
if ( wo.resizable_widths && wo.resizable_widths[ index ] ) {
ts.resizable.setWidth( $t, wo.resizable_widths[ index ], vars.overflow );
} else if ( !$t.hasClass( 'resizable-false' ) ) {
// don't clear the width of any column that is not resizable
ts.resizable.setWidth( $t, '', vars.overflow );
}
}
// reset stickyHeader widths
c.$table.trigger( 'stickyHeadersUpdate' );
if ( ts.storage && !refreshing ) {
ts.storage( this, ts.css.resizableStorage, {} );
} }
} }
}); });
};
ts.resizableReset = function( table, refreshing ) {
$( table ).each(function(){
var index, $t,
c = this.config,
wo = c && c.widgetOptions,
vars = wo.resizable_vars;
if ( table && c && c.$headerIndexed.length ) {
// restore the initial table width
if ( vars.overflow && vars.tableWidth ) {
ts.resizable.setWidth( c.$table, vars.tableWidth, true );
if ( vars.useStorage ) {
ts.storage( table, 'tablesorter-table-resized-width', 'auto' );
}
}
for ( index = 0; index < c.columns; index++ ) {
$t = c.$headerIndexed[ index ];
if ( wo.resizable_widths && wo.resizable_widths[ index ] ) {
ts.resizable.setWidth( $t, wo.resizable_widths[ index ], vars.overflow );
} else if ( !$t.hasClass( 'resizable-false' ) ) {
// don't clear the width of any column that is not resizable
ts.resizable.setWidth( $t, '', vars.overflow );
}
}
// reset stickyHeader widths
c.$table.trigger( 'stickyHeadersUpdate' );
if ( ts.storage && !refreshing ) {
ts.storage( this, ts.css.resizableStorage, {} );
}
}
});
};
})( jQuery, window ); })( jQuery, window );

View File

@ -1,68 +1,68 @@
/*! Widget: saveSort */ /*! Widget: saveSort */
;(function ($) { ;(function ($) {
'use strict'; 'use strict';
var ts = $.tablesorter || {}; var ts = $.tablesorter || {};
// this widget saves the last sort only if the // this widget saves the last sort only if the
// saveSort widget option is true AND the // saveSort widget option is true AND the
// $.tablesorter.storage function is included // $.tablesorter.storage function is included
// ************************** // **************************
ts.addWidget({ ts.addWidget({
id: 'saveSort', id: 'saveSort',
priority: 20, priority: 20,
options: { options: {
saveSort : true saveSort : true
}, },
init: function(table, thisWidget, c, wo) { init: function(table, thisWidget, c, wo) {
// run widget format before all other widgets are applied to the table // run widget format before all other widgets are applied to the table
thisWidget.format(table, c, wo, true); thisWidget.format(table, c, wo, true);
}, },
format: function(table, c, wo, init) { format: function(table, c, wo, init) {
var stored, time, var stored, time,
$table = c.$table, $table = c.$table,
saveSort = wo.saveSort !== false, // make saveSort active/inactive; default to true saveSort = wo.saveSort !== false, // make saveSort active/inactive; default to true
sortList = { "sortList" : c.sortList }; sortList = { 'sortList' : c.sortList };
if (c.debug) { if (c.debug) {
time = new Date(); time = new Date();
} }
if ($table.hasClass('hasSaveSort')) { if ($table.hasClass('hasSaveSort')) {
if (saveSort && table.hasInitialized && ts.storage) { if (saveSort && table.hasInitialized && ts.storage) {
ts.storage( table, 'tablesorter-savesort', sortList ); ts.storage( table, 'tablesorter-savesort', sortList );
if (c.debug) { if (c.debug) {
ts.benchmark('saveSort widget: Saving last sort: ' + c.sortList, time); ts.benchmark('saveSort widget: Saving last sort: ' + c.sortList, time);
}
}
} else {
// set table sort on initial run of the widget
$table.addClass('hasSaveSort');
sortList = '';
// get data
if (ts.storage) {
stored = ts.storage( table, 'tablesorter-savesort' );
sortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : '';
if (c.debug) {
ts.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time);
}
$table.bind('saveSortReset', function(event) {
event.stopPropagation();
ts.storage( table, 'tablesorter-savesort', '' );
});
}
// init is true when widget init is run, this will run this widget before all other widgets have initialized
// this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice.
if (init && sortList && sortList.length > 0) {
c.sortList = sortList;
} else if (table.hasInitialized && sortList && sortList.length > 0) {
// update sort change
$table.trigger('sorton', [ sortList ]);
} }
} }
} else { },
// set table sort on initial run of the widget remove: function(table, c) {
$table.addClass('hasSaveSort'); c.$table.removeClass('hasSaveSort');
sortList = ''; // clear storage
// get data if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); }
if (ts.storage) {
stored = ts.storage( table, 'tablesorter-savesort' );
sortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : '';
if (c.debug) {
ts.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time);
}
$table.bind('saveSortReset', function(event) {
event.stopPropagation();
ts.storage( table, 'tablesorter-savesort', '' );
});
}
// init is true when widget init is run, this will run this widget before all other widgets have initialized
// this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice.
if (init && sortList && sortList.length > 0) {
c.sortList = sortList;
} else if (table.hasInitialized && sortList && sortList.length > 0) {
// update sort change
$table.trigger('sorton', [sortList]);
}
} }
}, });
remove: function(table, c) {
c.$table.removeClass('hasSaveSort');
// clear storage
if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); }
}
});
})(jQuery); })(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -1,128 +1,128 @@
/*! Widget: sort2Hash - updated 7/21/2015 (v2.22.4) */ /*! Widget: sort2Hash - updated 7/21/2015 (v2.22.4) */
;( function( $ ) { ;( function( $ ) {
'use strict'; 'use strict';
var ts = $.tablesorter || {}, var ts = $.tablesorter || {},
s2h = { s2h = {
init : function( c, wo ) { init : function( c, wo ) {
var hasSaveSort = ts.hasWidget( c.table, 'saveSort' ), var hasSaveSort = ts.hasWidget( c.table, 'saveSort' ),
sort = s2h.getSort( c, wo ); sort = s2h.getSort( c, wo );
if ( ( sort && !hasSaveSort ) || ( sort && hasSaveSort && wo.sort2Hash_overrideSaveSort ) ) { if ( ( sort && !hasSaveSort ) || ( sort && hasSaveSort && wo.sort2Hash_overrideSaveSort ) ) {
s2h.processHash( c, wo, sort ); s2h.processHash( c, wo, sort );
}
c.$table.on( 'sortEnd.sort2hash', function() {
s2h.setHash( c, wo );
});
},
getTableId : function( c, wo ) {
// option > table id > table index on page
return wo.sort2Hash_tableId ||
c.table.id ||
'table' + $( 'table' ).index( c.$table );
},
getSort : function( c, wo, clean ) {
// modified original code from http://www.netlobo.com/url_query_string_javascript.html
var value,
name = s2h.getTableId( c, wo ).replace( /[\[]/, '\\[' ).replace( /[\]]/, '\\]' ),
sort = ( new RegExp( '[\\#&]' + name + '=([^&]*)' ) ).exec( window.location.hash );
if ( sort === null ) {
return '';
} else {
value = s2h.processSort( c, wo, sort[ 1 ] );
if ( clean ) {
window.location.hash = window.location.hash.replace( '&' + name + '=' + sort[ 1 ], '' );
return value;
} }
return sort[ 1 ]; c.$table.on( 'sortEnd.sort2hash', function() {
} s2h.setHash( c, wo );
}, });
// convert 'first%20name,asc,last%20name,desc' into [[0,0], [1,1]] },
processHash : function( c, wo, sortHash ) { getTableId : function( c, wo ) {
var regex, column, direction, temp, // option > table id > table index on page
arry = decodeURI( sortHash || '' ).split( wo.sort2Hash_separator ), return wo.sort2Hash_tableId ||
indx = 0, c.table.id ||
len = arry.length, 'table' + $( 'table' ).index( c.$table );
sort = []; },
while ( indx < len ) { getSort : function( c, wo, clean ) {
// column index or text // modified original code from http://www.netlobo.com/url_query_string_javascript.html
column = arry[ indx++ ]; var value,
temp = parseInt( column, 10 ); name = s2h.getTableId( c, wo ).replace( /[\[]/, '\\[' ).replace( /[\]]/, '\\]' ),
// ignore wo.sort2Hash_useHeaderText setting & sort = ( new RegExp( '[\\#&]' + name + '=([^&]*)' ) ).exec( window.location.hash );
// just see if column contains a number if ( sort === null ) {
if ( isNaN( temp ) || temp > c.columns ) { return '';
regex = new RegExp( '(' + column + ')', 'i' ); } else {
column = c.$headers.filter( function( index, cell ) { value = s2h.processSort( c, wo, sort[ 1 ] );
return regex.test( c.$headers[ index ].textContent || '' ); if ( clean ) {
}).attr( 'data-column' ); window.location.hash = window.location.hash.replace( '&' + name + '=' + sort[ 1 ], '' );
} return value;
direction = arry[ indx++ ];
// ignore unpaired values
if ( typeof direction !== 'undefined' ) {
// convert text to 0, 1
if ( isNaN( direction ) ) {
// default to ascending sort
direction = direction.indexOf( wo.sort2Hash_directionText[ 1 ] ) > -1 ? 1 : 0;
} }
sort.push( [ column, direction ] ); return sort[ 1 ];
} }
} },
if ( sort.length ) { // convert 'first%20name,asc,last%20name,desc' into [[0,0], [1,1]]
c.sortList = sort; processHash : function( c, wo, sortHash ) {
} var regex, column, direction, temp,
}, arry = decodeURI( sortHash || '' ).split( wo.sort2Hash_separator ),
indx = 0,
// convert [[0,0],[1,1]] to 'first%20name,asc,last%20name,desc' len = arry.length,
processSort : function( c, wo ) { sort = [];
var index, txt, column, direction, while ( indx < len ) {
sort = [], // column index or text
arry = c.sortList || [], column = arry[ indx++ ];
len = arry.length; temp = parseInt( column, 10 );
for ( index = 0; index < len; index++ ) { // ignore wo.sort2Hash_useHeaderText setting &
column = arry[ index ][ 0 ]; // just see if column contains a number
if ( wo.sort2Hash_useHeaderText ) { if ( isNaN( temp ) || temp > c.columns ) {
txt = $.trim( c.$headerIndexed[ column ].text() ); regex = new RegExp( '(' + column + ')', 'i' );
if ( typeof wo.sort2Hash_processHeaderText === 'function' ) { column = c.$headers.filter( function( index, cell ) {
txt = wo.sort2Hash_processHeaderText( txt, c, column ); return regex.test( c.$headers[ index ].textContent || '' );
}).attr( 'data-column' );
}
direction = arry[ indx++ ];
// ignore unpaired values
if ( typeof direction !== 'undefined' ) {
// convert text to 0, 1
if ( isNaN( direction ) ) {
// default to ascending sort
direction = direction.indexOf( wo.sort2Hash_directionText[ 1 ] ) > -1 ? 1 : 0;
}
sort.push( [ column, direction ] );
} }
column = txt;
} }
sort.push( column ); if ( sort.length ) {
direction = wo.sort2Hash_directionText[ arry[ index ][ 1 ] ]; c.sortList = sort;
sort.push( direction ); }
},
} // convert [[0,0],[1,1]] to 'first%20name,asc,last%20name,desc'
// join with separator processSort : function( c, wo ) {
return sort.join( wo.sort2Hash_separator ); var index, txt, column, direction,
}, sort = [],
setHash : function( c, wo ) { arry = c.sortList || [],
var arry = [], len = arry.length;
sort = s2h.processSort( c, wo ); for ( index = 0; index < len; index++ ) {
if ( sort.length ) { column = arry[ index ][ 0 ];
// remove old hash if ( wo.sort2Hash_useHeaderText ) {
s2h.getSort( c, wo, true ); txt = $.trim( c.$headerIndexed[ column ].text() );
window.location.hash += ( window.location.hash.length ? '' : wo.sort2Hash_hash ) + if ( typeof wo.sort2Hash_processHeaderText === 'function' ) {
'&' + s2h.getTableId( c, wo ) + '=' + encodeURI( sort ); txt = wo.sort2Hash_processHeaderText( txt, c, column );
} }
} column = txt;
}; }
sort.push( column );
direction = wo.sort2Hash_directionText[ arry[ index ][ 1 ] ];
sort.push( direction );
ts.addWidget({ }
id: 'sort2Hash', // join with separator
priority: 30, // after saveSort return sort.join( wo.sort2Hash_separator );
options: { },
sort2Hash_hash : '#', // hash prefix setHash : function( c, wo ) {
sort2Hash_separator : '-', // don't '#' or '=' here var arry = [],
sort2Hash_tableId : null, // this option > table ID > table index on page, sort = s2h.processSort( c, wo );
sort2Hash_useHeaderText : false, // use column header text (true) or zero-based column index if ( sort.length ) {
sort2Hash_processHeaderText : null, // function( text, config, columnIndex ) {}, // remove old hash
sort2Hash_directionText : [ 0, 1 ], // [ 'asc', 'desc' ], s2h.getSort( c, wo, true );
sort2Hash_overrideSaveSort : false // if true, override saveSort widget if saved sort available window.location.hash += ( window.location.hash.length ? '' : wo.sort2Hash_hash ) +
}, '&' + s2h.getTableId( c, wo ) + '=' + encodeURI( sort );
init: function(table, thisWidget, c, wo) { }
s2h.init( c, wo ); }
}, };
remove: function(table, c) {
c.$table.off( 'sortEnd.sort2hash' ); ts.addWidget({
} id: 'sort2Hash',
}); priority: 30, // after saveSort
options: {
sort2Hash_hash : '#', // hash prefix
sort2Hash_separator : '-', // don't '#' or '=' here
sort2Hash_tableId : null, // this option > table ID > table index on page,
sort2Hash_useHeaderText : false, // use column header text (true) or zero-based column index
sort2Hash_processHeaderText : null, // function( text, config, columnIndex ) {},
sort2Hash_directionText : [ 0, 1 ], // [ 'asc', 'desc' ],
sort2Hash_overrideSaveSort : false // if true, override saveSort widget if saved sort available
},
init: function(table, thisWidget, c, wo) {
s2h.init( c, wo );
},
remove: function(table, c) {
c.$table.off( 'sortEnd.sort2hash' );
}
});
})(jQuery); })(jQuery);

View File

@ -5,224 +5,224 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;( function( $ ) { ;( function( $ ) {
'use strict'; 'use strict';
var ts = $.tablesorter; var ts = $.tablesorter;
ts.sortTbodies = { ts.sortTbodies = {
init: function( c, wo ) { init: function( c, wo ) {
var index, rows, txt, max, $rows, var index, rows, txt, max, $rows,
namespace = c.namespace + 'sortTbody', namespace = c.namespace + 'sortTbody',
$tbodies = c.$table.children( 'tbody' ), $tbodies = c.$table.children( 'tbody' ),
len = $tbodies.length; len = $tbodies.length;
// save serverSideSorting value; use to toggle internal row sorting // save serverSideSorting value; use to toggle internal row sorting
wo.sortTbody_original_serverSideSorting = c.serverSideSorting; wo.sortTbody_original_serverSideSorting = c.serverSideSorting;
// include info-only tbodies - we need parsed data from *all* tbodies // include info-only tbodies - we need parsed data from *all* tbodies
wo.sortTbody_original_cssInfoBlock = c.cssInfoBlock; wo.sortTbody_original_cssInfoBlock = c.cssInfoBlock;
c.cssInfoBlock = wo.sortTbody_noSort; c.cssInfoBlock = wo.sortTbody_noSort;
ts.sortTbodies.setTbodies( c, wo );
// add original order index for stable sort
for ( index = 0; index < len; index++ ) {
$tbodies.eq( index ).attr( 'data-ts-original-order', index );
}
c.$table
.unbind( 'sortBegin updateComplete '.split( ' ' ).join( namespace + ' ' ) )
.bind( 'sortBegin' + namespace, function() {
ts.sortTbodies.sorter( c );
})
.bind( 'updateComplete' + namespace, function() {
// find parsers for each column
ts.sortTbodies.setTbodies( c, wo );
c.$table.trigger( 'updateCache', [ null, c.$tbodies ] );
});
// detect parsers - in case the table contains only info-only tbodies
if ( $.isEmptyObject( c.parsers ) || c.$tbodies.length !== $tbodies.length ) {
ts.sortTbodies.setTbodies( c, wo ); ts.sortTbodies.setTbodies( c, wo );
c.$table.trigger( 'updateCache', [ null, c.$tbodies ] );
}
// find colMax; this only matter for numeric columns // add original order index for stable sort
$rows = $tbodies.children( 'tr' ); for ( index = 0; index < len; index++ ) {
len = $rows.length; $tbodies.eq( index ).attr( 'data-ts-original-order', index );
for ( index = 0; index < c.columns; index++ ) {
max = 0;
if ( c.parsers[ index ].type === 'numeric' ) {
for ( rows = 0; rows < len; rows++ ) {
// update column max value (ignore sign)
txt = ts.getParsedText( c, $rows.eq( rows ).children()[ index ], index );
max = Math.max( Math.abs( txt ) || 0, max );
}
} }
c.$headerIndexed[ index ].attr( 'data-ts-col-max-value', max );
}
}, c.$table
.unbind( 'sortBegin updateComplete '.split( ' ' ).join( namespace + ' ' ) )
// make sure c.$tbodies is up-to-date (init & after updates) .bind( 'sortBegin' + namespace, function() {
setTbodies: function( c, wo ) { ts.sortTbodies.sorter( c );
c.$tbodies = c.$table.children( 'tbody' ).not( '.' + wo.sortTbody_noSort ); })
}, .bind( 'updateComplete' + namespace, function() {
// find parsers for each column
sorter: function( c ) { ts.sortTbodies.setTbodies( c, wo );
var $table = c.$table, c.$table.trigger( 'updateCache', [ null, c.$tbodies ] );
wo = c.widgetOptions;
// prevent multiple calls while processing
if ( wo.sortTbody_busy !== true ) {
wo.sortTbody_busy = true;
var $tbodies = $table.children( 'tbody' ).not( '.' + wo.sortTbody_noSort ),
primary = wo.sortTbody_primaryRow || 'tr:eq(0)',
sortList = c.sortList || [],
len = sortList.length;
if ( len ) {
// toggle internal row sorting
c.serverSideSorting = !wo.sortTbody_sortRows;
$tbodies.sort( function( a, b ) {
var sortListIndex, txt, dir, num, colMax, sort, col, order, colA, colB, x, y,
table = c.table,
parsers = c.parsers,
cts = c.textSorter || '',
$tbodyA = $( a ),
$tbodyB = $( b ),
$a = $tbodyA.find( primary ).children( 'td, th' ),
$b = $tbodyB.find( primary ).children( 'td, th' );
for ( sortListIndex = 0; sortListIndex < len; sortListIndex++ ) {
col = sortList[ sortListIndex ][0];
order = sortList[ sortListIndex ][1];
// sort direction, true = asc, false = desc
dir = order === 0;
// column txt - tbody A
txt = ts.getElementText( c, $a.eq( col ), col );
colA = parsers[ col ].format( txt, table, $a[ col ], col );
// column txt - tbody B
txt = ts.getElementText( c, $b.eq( col ), col );
colB = parsers[ col ].format( txt, table, $b[ col ], col );
if (c.sortStable && colA === colB && len === 1) {
return $tbodyA.attr( 'data-ts-original-order' ) - $tbodyB.attr( 'data-ts-original-order' );
}
// fallback to natural sort since it is more robust
num = /n/i.test( parsers && parsers[ col ] ? parsers[ col ].type || '' : '' );
if ( num && c.strings[ col ] ) {
colMax = c.$headerIndexed[ col ].attr( 'data-ts-col-max-value' ) ||
1.79E+308; // close to Number.MAX_VALUE
// sort strings in numerical columns
if ( typeof ( c.string[ c.strings[ col ] ] ) === 'boolean' ) {
num = ( dir ? 1 : -1 ) * ( c.string[ c.strings[ col ] ] ? -1 : 1 );
} else {
num = ( c.strings[ col ] ) ? c.string[ c.strings[ col ] ] || 0 : 0;
}
// fall back to built-in numeric sort
// var sort = $.tablesorter['sort' + s](a, b, dir, colMax, table);
sort = c.numberSorter ? c.numberSorter( colA, colB, dir, colMax, table ) :
ts[ 'sortNumeric' + ( dir ? 'Asc' : 'Desc' ) ]( colA, colB, num, colMax, col, table );
} else {
// set a & b depending on sort direction
x = dir ? colA : colB;
y = dir ? colB : colA;
// text sort function
if ( typeof ( cts ) === 'function' ) {
// custom OVERALL text sorter
sort = cts( x, y, dir, col, table );
} else if ( typeof ( cts ) === 'object' && cts.hasOwnProperty( col ) ) {
// custom text sorter for a SPECIFIC COLUMN
sort = cts[ col ]( x, y, dir, col, table );
} else {
// fall back to natural sort
sort = ts[ 'sortNatural' + ( dir ? 'Asc' : 'Desc' ) ]( colA, colB, col, table, c );
}
}
if ( sort ) { return sort; }
}
return $tbodyA.attr( 'data-ts-original-order' ) - $tbodyB.attr( 'data-ts-original-order' );
}); });
ts.sortTbodies.restoreTbodies ( c, wo, $tbodies ); // detect parsers - in case the table contains only info-only tbodies
wo.sortTbody_busy = false; if ( $.isEmptyObject( c.parsers ) || c.$tbodies.length !== $tbodies.length ) {
ts.sortTbodies.setTbodies( c, wo );
c.$table.trigger( 'updateCache', [ null, c.$tbodies ] );
} }
}
},
restoreTbodies : function ( c, wo, $sortedTbodies ) {
var $nosort, $tbodies, $thisTbody, tbLen, nsLen, index, targetIndex,
$table = c.$table,
hasShuffled = true,
indx = 0;
// hide entire table to improve sort performance
$table.hide();
$sortedTbodies.appendTo( $table );
// reposition no-sort tbodies
$tbodies = $table.children( 'tbody' );
tbLen = $tbodies.length;
$nosort = $tbodies.filter( '.' + wo.sortTbody_noSort ).appendTo( $table );
nsLen = $nosort.length;
if ( nsLen ) {
// don't allow the while loop to cycle more times than the set number of no-sort tbodies
while ( hasShuffled && indx < nsLen ) {
hasShuffled = false;
for ( index = 0; index < nsLen; index++ ) {
targetIndex = parseInt( $nosort.eq( index ).attr( 'data-ts-original-order' ), 10 );
// if target index > number of tbodies, make it last
targetIndex = targetIndex >= tbLen ? tbLen : targetIndex < 0 ? 0 : targetIndex;
if ( targetIndex !== $nosort.eq( index ).index() ) {
hasShuffled = true;
$thisTbody = $nosort.eq( index ).detach();
if ( targetIndex >= tbLen ) {
// Are we trying to be the last tbody?
$thisTbody.appendTo( $table );
} else if ( targetIndex === 0 ) {
// Are we trying to be the first tbody?
$thisTbody.prependTo( $table );
} else {
// No, we want to be somewhere in the middle!
$thisTbody.insertBefore( $table.children( 'tbody:eq(' + targetIndex + ')' ) );
}
// find colMax; this only matter for numeric columns
$rows = $tbodies.children( 'tr' );
len = $rows.length;
for ( index = 0; index < c.columns; index++ ) {
max = 0;
if ( c.parsers[ index ].type === 'numeric' ) {
for ( rows = 0; rows < len; rows++ ) {
// update column max value (ignore sign)
txt = ts.getParsedText( c, $rows.eq( rows ).children()[ index ], index );
max = Math.max( Math.abs( txt ) || 0, max );
} }
} }
indx++; c.$headerIndexed[ index ].attr( 'data-ts-col-max-value', max );
} }
},
// make sure c.$tbodies is up-to-date (init & after updates)
setTbodies: function( c, wo ) {
c.$tbodies = c.$table.children( 'tbody' ).not( '.' + wo.sortTbody_noSort );
},
sorter: function( c ) {
var $table = c.$table,
wo = c.widgetOptions;
// prevent multiple calls while processing
if ( wo.sortTbody_busy !== true ) {
wo.sortTbody_busy = true;
var $tbodies = $table.children( 'tbody' ).not( '.' + wo.sortTbody_noSort ),
primary = wo.sortTbody_primaryRow || 'tr:eq(0)',
sortList = c.sortList || [],
len = sortList.length;
if ( len ) {
// toggle internal row sorting
c.serverSideSorting = !wo.sortTbody_sortRows;
$tbodies.sort( function( a, b ) {
var sortListIndex, txt, dir, num, colMax, sort, col, order, colA, colB, x, y,
table = c.table,
parsers = c.parsers,
cts = c.textSorter || '',
$tbodyA = $( a ),
$tbodyB = $( b ),
$a = $tbodyA.find( primary ).children( 'td, th' ),
$b = $tbodyB.find( primary ).children( 'td, th' );
for ( sortListIndex = 0; sortListIndex < len; sortListIndex++ ) {
col = sortList[ sortListIndex ][0];
order = sortList[ sortListIndex ][1];
// sort direction, true = asc, false = desc
dir = order === 0;
// column txt - tbody A
txt = ts.getElementText( c, $a.eq( col ), col );
colA = parsers[ col ].format( txt, table, $a[ col ], col );
// column txt - tbody B
txt = ts.getElementText( c, $b.eq( col ), col );
colB = parsers[ col ].format( txt, table, $b[ col ], col );
if (c.sortStable && colA === colB && len === 1) {
return $tbodyA.attr( 'data-ts-original-order' ) - $tbodyB.attr( 'data-ts-original-order' );
}
// fallback to natural sort since it is more robust
num = /n/i.test( parsers && parsers[ col ] ? parsers[ col ].type || '' : '' );
if ( num && c.strings[ col ] ) {
colMax = c.$headerIndexed[ col ].attr( 'data-ts-col-max-value' ) ||
1.79E+308; // close to Number.MAX_VALUE
// sort strings in numerical columns
if ( typeof ( c.string[ c.strings[ col ] ] ) === 'boolean' ) {
num = ( dir ? 1 : -1 ) * ( c.string[ c.strings[ col ] ] ? -1 : 1 );
} else {
num = ( c.strings[ col ] ) ? c.string[ c.strings[ col ] ] || 0 : 0;
}
// fall back to built-in numeric sort
// var sort = $.tablesorter['sort' + s](a, b, dir, colMax, table);
sort = c.numberSorter ? c.numberSorter( colA, colB, dir, colMax, table ) :
ts[ 'sortNumeric' + ( dir ? 'Asc' : 'Desc' ) ]( colA, colB, num, colMax, col, table );
} else {
// set a & b depending on sort direction
x = dir ? colA : colB;
y = dir ? colB : colA;
// text sort function
if ( typeof ( cts ) === 'function' ) {
// custom OVERALL text sorter
sort = cts( x, y, dir, col, table );
} else if ( typeof ( cts ) === 'object' && cts.hasOwnProperty( col ) ) {
// custom text sorter for a SPECIFIC COLUMN
sort = cts[ col ]( x, y, dir, col, table );
} else {
// fall back to natural sort
sort = ts[ 'sortNatural' + ( dir ? 'Asc' : 'Desc' ) ]( colA, colB, col, table, c );
}
}
if ( sort ) { return sort; }
}
return $tbodyA.attr( 'data-ts-original-order' ) - $tbodyB.attr( 'data-ts-original-order' );
});
ts.sortTbodies.restoreTbodies( c, wo, $tbodies );
wo.sortTbody_busy = false;
}
}
},
restoreTbodies : function ( c, wo, $sortedTbodies ) {
var $nosort, $tbodies, $thisTbody, tbLen, nsLen, index, targetIndex,
$table = c.$table,
hasShuffled = true,
indx = 0;
// hide entire table to improve sort performance
$table.hide();
$sortedTbodies.appendTo( $table );
// reposition no-sort tbodies
$tbodies = $table.children( 'tbody' );
tbLen = $tbodies.length;
$nosort = $tbodies.filter( '.' + wo.sortTbody_noSort ).appendTo( $table );
nsLen = $nosort.length;
if ( nsLen ) {
// don't allow the while loop to cycle more times than the set number of no-sort tbodies
while ( hasShuffled && indx < nsLen ) {
hasShuffled = false;
for ( index = 0; index < nsLen; index++ ) {
targetIndex = parseInt( $nosort.eq( index ).attr( 'data-ts-original-order' ), 10 );
// if target index > number of tbodies, make it last
targetIndex = targetIndex >= tbLen ? tbLen : targetIndex < 0 ? 0 : targetIndex;
if ( targetIndex !== $nosort.eq( index ).index() ) {
hasShuffled = true;
$thisTbody = $nosort.eq( index ).detach();
if ( targetIndex >= tbLen ) {
// Are we trying to be the last tbody?
$thisTbody.appendTo( $table );
} else if ( targetIndex === 0 ) {
// Are we trying to be the first tbody?
$thisTbody.prependTo( $table );
} else {
// No, we want to be somewhere in the middle!
$thisTbody.insertBefore( $table.children( 'tbody:eq(' + targetIndex + ')' ) );
}
}
}
indx++;
}
}
$table.show();
} }
$table.show(); };
}
}; ts.addWidget({
id: 'sortTbody',
ts.addWidget({ // priority < 50 (filter widget), so c.$tbodies has the correct elements
id: 'sortTbody', priority: 40,
// priority < 50 (filter widget), so c.$tbodies has the correct elements options: {
priority: 40, // point to a row within the tbody that matches the number of header columns
options: { sortTbody_primaryRow : null,
// point to a row within the tbody that matches the number of header columns // sort tbody internal rows
sortTbody_primaryRow : null, sortTbody_sortRows : false,
// sort tbody internal rows // static tbodies (like static rows)
sortTbody_sortRows : false, sortTbody_noSort : 'tablesorter-no-sort-tbody'
// static tbodies (like static rows) },
sortTbody_noSort : 'tablesorter-no-sort-tbody' init : function( table, thisWidget, c, wo ) {
}, ts.sortTbodies.init( c, wo );
init : function( table, thisWidget, c, wo ) { },
ts.sortTbodies.init( c, wo ); remove : function( table, c, wo, refreshing ) {
}, c.$table.unbind( 'sortBegin updateComplete '.split( ' ' ).join( c.namespace + 'sortTbody ' ) );
remove : function( table, c, wo, refreshing ) { c.serverSideSorting = wo.sortTbody_original_serverSideSorting;
c.$table.unbind( 'sortBegin updateComplete '.split( ' ' ).join( c.namespace + 'sortTbody ' ) ); c.cssInfoBlock = wo.sortTbody_original_cssInfoBlock;
c.serverSideSorting = wo.sortTbody_original_serverSideSorting; }
c.cssInfoBlock = wo.sortTbody_original_cssInfoBlock; });
}
});
})( jQuery ); })( jQuery );

View File

@ -12,110 +12,110 @@
/*jshint browser:true, jquery:true, unused:false */ /*jshint browser:true, jquery:true, unused:false */
/*global jQuery: false */ /*global jQuery: false */
;(function($){ ;(function($){
"use strict"; 'use strict';
var ts = $.tablesorter, var ts = $.tablesorter,
// add/refresh row indexes // add/refresh row indexes
addIndexes = function(table){ addIndexes = function(table){
var $tr, wo, v, indx, rows, var $tr, wo, v, indx, rows,
c = table.config; c = table.config;
// "Index" the static rows, saving their current (starting) position in the // 'Index' the static rows, saving their current (starting) position in the
// table inside a data() param on the <tr> element itself for later use. // table inside a data() param on the <tr> element itself for later use.
if (c) { if (c) {
wo = c.widgetOptions; wo = c.widgetOptions;
c.$tbodies.each(function(){ c.$tbodies.each(function(){
$tr = $(this).children(); $tr = $(this).children();
rows = $tr.length; rows = $tr.length;
$tr.filter(wo.staticRow_class).each(function() { $tr.filter(wo.staticRow_class).each(function() {
$tr = $(this); $tr = $(this);
indx = $tr.data(wo.staticRow_index); indx = $tr.data(wo.staticRow_index);
if (typeof indx !== "undefined") { if (typeof indx !== 'undefined') {
v = parseFloat(indx); v = parseFloat(indx);
// percentage of total rows // percentage of total rows
indx = (/%/.test(indx)) ? Math.round(v/100 * rows) : v; indx = (/%/.test(indx)) ? Math.round(v / 100 * rows) : v;
} else { } else {
indx = $tr.index(); indx = $tr.index();
} }
// row indexing starts over within each tbody // row indexing starts over within each tbody
$tr.data( wo.staticRow_data, indx ); $tr.data( wo.staticRow_data, indx );
});
}); });
}); }
} };
};
ts.addWidget({ ts.addWidget({
// Give the new Widget an ID to be used in the tablesorter() call, as follows: // Give the new Widget an ID to be used in the tablesorter() call, as follows:
// $('#myElement').tablesorter({ widgets: ['zebra', 'staticRow'] }); // $('#myElement').tablesorter({ widgets: ['zebra', 'staticRow'] });
id: 'staticRow', id: 'staticRow',
options: { options: {
staticRow_class : '.static', staticRow_class : '.static',
staticRow_data : 'static-index', staticRow_data : 'static-index',
staticRow_index : 'row-index', staticRow_index : 'row-index',
staticRow_event : 'staticRowsRefresh' staticRow_event : 'staticRowsRefresh'
}, },
init: function(table, thisWidget, c, wo){ init: function(table, thisWidget, c, wo){
addIndexes(table); addIndexes(table);
// refresh static rows after updates // refresh static rows after updates
c.$table c.$table
.unbind( ('updateComplete.tsstaticrows ' + wo.staticRow_event).replace(/\s+/g, ' ') ) .unbind( ('updateComplete.tsstaticrows ' + wo.staticRow_event).replace(/\s+/g, ' ') )
.bind('updateComplete.tsstaticrows ' + wo.staticRow_event, function(){ .bind('updateComplete.tsstaticrows ' + wo.staticRow_event, function(){
addIndexes(table); addIndexes(table);
c.$table.trigger('applyWidgets'); c.$table.trigger('applyWidgets');
}); });
}, },
format: function(table, c, wo) { format: function(table, c, wo) {
// Loop thru static rows, moving them to their original "indexed" position, // Loop thru static rows, moving them to their original 'indexed' position,
// & repeat until no more re-shuffling is needed // & repeat until no more re-shuffling is needed
var targetIndex, $thisRow, indx, numRows, $tbody, hasShuffled, $rows, max; var targetIndex, $thisRow, indx, numRows, $tbody, hasShuffled, $rows, max;
c.$tbodies.each(function(){ c.$tbodies.each(function(){
$tbody = $.tablesorter.processTbody(table, $(this), true); // remove tbody $tbody = $.tablesorter.processTbody(table, $(this), true); // remove tbody
hasShuffled = true; hasShuffled = true;
indx = 0; indx = 0;
$rows = $tbody.children(wo.staticRow_class); $rows = $tbody.children(wo.staticRow_class);
numRows = $tbody.children('tr').length - 1; numRows = $tbody.children('tr').length - 1;
max = $rows.length; max = $rows.length;
// don't allow the while loop to cycle more times than the set number of static rows // don't allow the while loop to cycle more times than the set number of static rows
while (hasShuffled && indx < max) { while (hasShuffled && indx < max) {
hasShuffled = false; hasShuffled = false;
/*jshint loopfunc:true */ /*jshint loopfunc:true */
$rows.each(function() { $rows.each(function() {
targetIndex = $(this).data(wo.staticRow_data); targetIndex = $(this).data(wo.staticRow_data);
// allow setting target index >> num rows to always make a row last // allow setting target index >> num rows to always make a row last
targetIndex = targetIndex >= numRows ? numRows : targetIndex < 0 ? 0 : targetIndex; targetIndex = targetIndex >= numRows ? numRows : targetIndex < 0 ? 0 : targetIndex;
if (targetIndex !== $(this).index()) { if (targetIndex !== $(this).index()) {
hasShuffled = true; hasShuffled = true;
$thisRow = $(this).detach(); $thisRow = $(this).detach();
if (targetIndex >= numRows) { if (targetIndex >= numRows) {
// Are we trying to be the last row? // Are we trying to be the last row?
$thisRow.appendTo( $tbody ); $thisRow.appendTo( $tbody );
} else if (targetIndex === 0) { } else if (targetIndex === 0) {
// Are we trying to be the first row? // Are we trying to be the first row?
$thisRow.prependTo( $tbody ); $thisRow.prependTo( $tbody );
} else { } else {
// No, we want to be somewhere in the middle! // No, we want to be somewhere in the middle!
$thisRow.insertBefore( $tbody.find('tr:eq(' + targetIndex + ')') ); $thisRow.insertBefore( $tbody.find('tr:eq(' + targetIndex + ')') );
}
} }
} });
}); indx++;
indx++; }
}
$.tablesorter.processTbody(table, $tbody, false); // restore tbody $.tablesorter.processTbody(table, $tbody, false); // restore tbody
}); });
c.$table.trigger('staticRowsComplete', table); c.$table.trigger('staticRowsComplete', table);
}, },
remove : function(table, c, wo){ remove : function(table, c, wo){
c.$table.unbind( ('updateComplete.tsstaticrows ' + wo.staticRow_event).replace(/\s+/g, ' ') ); c.$table.unbind( ('updateComplete.tsstaticrows ' + wo.staticRow_event).replace(/\s+/g, ' ') );
} }
}); });
})(jQuery); })(jQuery);

View File

@ -3,286 +3,286 @@
* by Rob Garrison * by Rob Garrison
*/ */
;(function ($, window) { ;(function ($, window) {
'use strict'; 'use strict';
var ts = $.tablesorter || {}; var ts = $.tablesorter || {};
$.extend(ts.css, { $.extend(ts.css, {
sticky : 'tablesorter-stickyHeader', // stickyHeader sticky : 'tablesorter-stickyHeader', // stickyHeader
stickyVis : 'tablesorter-sticky-visible', stickyVis : 'tablesorter-sticky-visible',
stickyHide: 'tablesorter-sticky-hidden', stickyHide: 'tablesorter-sticky-hidden',
stickyWrap: 'tablesorter-sticky-wrapper' stickyWrap: 'tablesorter-sticky-wrapper'
}); });
// Add a resize event to table headers // Add a resize event to table headers
ts.addHeaderResizeEvent = function(table, disable, settings) { ts.addHeaderResizeEvent = function(table, disable, settings) {
table = $(table)[0]; // make sure we're using a dom element table = $(table)[0]; // make sure we're using a dom element
if ( !table.config ) { return; } if ( !table.config ) { return; }
var defaults = { var defaults = {
timer : 250 timer : 250
},
options = $.extend({}, defaults, settings),
c = table.config,
wo = c.widgetOptions,
checkSizes = function( triggerEvent ) {
var index, headers, $header, sizes, width, height,
len = c.$headers.length;
wo.resize_flag = true;
headers = [];
for ( index = 0; index < len; index++ ) {
$header = c.$headers.eq( index );
sizes = $header.data( 'savedSizes' ) || [ 0, 0 ]; // fixes #394
width = $header[0].offsetWidth;
height = $header[0].offsetHeight;
if ( width !== sizes[0] || height !== sizes[1] ) {
$header.data( 'savedSizes', [ width, height ] );
headers.push( $header[0] );
}
}
if ( headers.length && triggerEvent !== false ) {
c.$table.trigger( 'resize', [ headers ] );
}
wo.resize_flag = false;
};
checkSizes( false );
clearInterval(wo.resize_timer);
if (disable) {
wo.resize_flag = false;
return false;
}
wo.resize_timer = setInterval(function() {
if (wo.resize_flag) { return; }
checkSizes();
}, options.timer);
};
// Sticky headers based on this awesome article:
// http://css-tricks.com/13465-persistent-headers/
// and https://github.com/jmosbech/StickyTableHeaders by Jonas Mosbech
// **************************
ts.addWidget({
id: 'stickyHeaders',
priority: 60, // sticky widget must be initialized after the filter widget!
options: {
stickyHeaders : '', // extra class name added to the sticky header row
stickyHeaders_attachTo : null, // jQuery selector or object to attach sticky header to
stickyHeaders_xScroll : null, // jQuery selector or object to monitor horizontal scroll position (defaults: xScroll > attachTo > window)
stickyHeaders_yScroll : null, // jQuery selector or object to monitor vertical scroll position (defaults: yScroll > attachTo > window)
stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element
stickyHeaders_filteredToTop: true, // scroll table top into view after filtering
stickyHeaders_cloneId : '-sticky', // added to table ID, if it exists
stickyHeaders_addResizeEvent : true, // trigger 'resize' event on headers
stickyHeaders_includeCaption : true, // if false and a caption exist, it won't be included in the sticky header
stickyHeaders_zIndex : 2 // The zIndex of the stickyHeaders, allows the user to adjust this to their needs
}, },
options = $.extend({}, defaults, settings), format: function(table, c, wo) {
c = table.config, // filter widget doesn't initialize on an empty table. Fixes #449
wo = c.widgetOptions, if ( c.$table.hasClass('hasStickyHeaders') || ($.inArray('filter', c.widgets) >= 0 && !c.$table.hasClass('hasFilters')) ) {
checkSizes = function( triggerEvent ) { return;
var index, headers, $header, sizes, width, height, }
len = c.$headers.length; var index, len, $t,
wo.resize_flag = true; $table = c.$table,
headers = []; // add position: relative to attach element, hopefully it won't cause trouble.
for ( index = 0; index < len; index++ ) { $attach = $(wo.stickyHeaders_attachTo),
$header = c.$headers.eq( index ); namespace = c.namespace + 'stickyheaders ',
sizes = $header.data( 'savedSizes' ) || [ 0,0 ]; // fixes #394 // element to watch for the scroll event
width = $header[0].offsetWidth; $yScroll = $(wo.stickyHeaders_yScroll || wo.stickyHeaders_attachTo || window),
height = $header[0].offsetHeight; $xScroll = $(wo.stickyHeaders_xScroll || wo.stickyHeaders_attachTo || window),
if ( width !== sizes[0] || height !== sizes[1] ) { $thead = $table.children('thead:first'),
$header.data( 'savedSizes', [ width, height ] ); $header = $thead.children('tr').not('.sticky-false').children(),
headers.push( $header[0] ); $tfoot = $table.children('tfoot'),
$stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '',
stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0,
// is this table nested? If so, find parent sticky header wrapper (div, not table)
$nestedSticky = $table.parent().closest('.' + ts.css.table).hasClass('hasStickyHeaders') ?
$table.parent().closest('table.tablesorter')[0].config.widgetOptions.$sticky.parent() : [],
nestedStickyTop = $nestedSticky.length ? $nestedSticky.height() : 0,
// clone table, then wrap to make sticky header
$stickyTable = wo.$sticky = $table.clone()
.addClass('containsStickyHeaders ' + ts.css.sticky + ' ' + wo.stickyHeaders + ' ' + c.namespace.slice(1) + '_extra_table' )
.wrap('<div class="' + ts.css.stickyWrap + '">'),
$stickyWrap = $stickyTable.parent()
.addClass(ts.css.stickyHide)
.css({
position : $attach.length ? 'absolute' : 'fixed',
padding : parseInt( $stickyTable.parent().parent().css('padding-left'), 10 ),
top : stickyOffset + nestedStickyTop,
left : 0,
visibility : 'hidden',
zIndex : wo.stickyHeaders_zIndex || 2
}),
$stickyThead = $stickyTable.children('thead:first'),
$stickyCells,
laststate = '',
spacing = 0,
setWidth = function($orig, $clone){
var index, width, border, $cell, $this,
$cells = $orig.filter(':visible'),
len = $cells.length;
for ( index = 0; index < len; index++ ) {
$cell = $clone.filter(':visible').eq(index);
$this = $cells.eq(index);
// code from https://github.com/jmosbech/StickyTableHeaders
if ($this.css('box-sizing') === 'border-box') {
width = $this.outerWidth();
} else {
if ($cell.css('border-collapse') === 'collapse') {
if (window.getComputedStyle) {
width = parseFloat( window.getComputedStyle($this[0], null).width );
} else {
// ie8 only
border = parseFloat( $this.css('border-width') );
width = $this.outerWidth() - parseFloat( $this.css('padding-left') ) - parseFloat( $this.css('padding-right') ) - border;
}
} else {
width = $this.width();
}
}
$cell.css({
'width': width,
'min-width': width,
'max-width': width
});
}
},
resizeHeader = function() {
stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0;
spacing = 0;
$stickyWrap.css({
left : $attach.length ? parseInt($attach.css('padding-left'), 10) || 0 :
$table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing,
width: $table.outerWidth()
});
setWidth( $table, $stickyTable );
setWidth( $header, $stickyCells );
},
scrollSticky = function( resizing ) {
if (!$table.is(':visible')) { return; } // fixes #278
// Detect nested tables - fixes #724
nestedStickyTop = $nestedSticky.length ? $nestedSticky.offset().top - $yScroll.scrollTop() + $nestedSticky.height() : 0;
var offset = $table.offset(),
yWindow = $.isWindow( $yScroll[0] ), // $.isWindow needs jQuery 1.4.3
xWindow = $.isWindow( $xScroll[0] ),
// scrollTop = ( $attach.length ? $attach.offset().top : $yScroll.scrollTop() ) + stickyOffset + nestedStickyTop,
scrollTop = ( $attach.length ? ( yWindow ? $yScroll.scrollTop() : $yScroll.offset().top ) : $yScroll.scrollTop() ) + stickyOffset + nestedStickyTop,
tableHeight = $table.height() - ($stickyWrap.height() + ($tfoot.height() || 0)),
isVisible = ( scrollTop > offset.top ) && ( scrollTop < offset.top + tableHeight ) ? 'visible' : 'hidden',
cssSettings = { visibility : isVisible };
if ($attach.length) {
cssSettings.top = yWindow ? scrollTop - $attach.offset().top : $attach.scrollTop();
}
if (xWindow) {
// adjust when scrolling horizontally - fixes issue #143
cssSettings.left = $table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing;
}
if ($nestedSticky.length) {
cssSettings.top = ( cssSettings.top || 0 ) + stickyOffset + nestedStickyTop;
}
$stickyWrap
.removeClass( ts.css.stickyVis + ' ' + ts.css.stickyHide )
.addClass( isVisible === 'visible' ? ts.css.stickyVis : ts.css.stickyHide )
.css(cssSettings);
if (isVisible !== laststate || resizing) {
// make sure the column widths match
resizeHeader();
laststate = isVisible;
}
};
// only add a position relative if a position isn't already defined
if ($attach.length && !$attach.css('position')) {
$attach.css('position', 'relative');
}
// fix clone ID, if it exists - fixes #271
if ($stickyTable.attr('id')) { $stickyTable[0].id += wo.stickyHeaders_cloneId; }
// clear out cloned table, except for sticky header
// include caption & filter row (fixes #126 & #249) - don't remove cells to get correct cell indexing
$stickyTable.find('thead:gt(0), tr.sticky-false').hide();
$stickyTable.find('tbody, tfoot').remove();
$stickyTable.find('caption').toggle(wo.stickyHeaders_includeCaption);
// issue #172 - find td/th in sticky header
$stickyCells = $stickyThead.children().children();
$stickyTable.css({ height:0, width:0, margin: 0 });
// remove resizable block
$stickyCells.find('.' + ts.css.resizer).remove();
// update sticky header class names to match real header after sorting
$table
.addClass('hasStickyHeaders')
.bind('pagerComplete' + namespace, function() {
resizeHeader();
});
ts.bindEvents(table, $stickyThead.children().children('.' + ts.css.header));
// add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned.
$table.after( $stickyWrap );
// onRenderHeader is defined, we need to do something about it (fixes #641)
if (c.onRenderHeader) {
$t = $stickyThead.children('tr').children();
len = $t.length;
for ( index = 0; index < len; index++ ) {
// send second parameter
c.onRenderHeader.apply( $t.eq( index ), [ index, c, $stickyTable ] );
} }
} }
if ( headers.length && triggerEvent !== false ) {
c.$table.trigger( 'resize', [ headers ] );
}
wo.resize_flag = false;
};
checkSizes( false );
clearInterval(wo.resize_timer);
if (disable) {
wo.resize_flag = false;
return false;
}
wo.resize_timer = setInterval(function() {
if (wo.resize_flag) { return; }
checkSizes();
}, options.timer);
};
// Sticky headers based on this awesome article: // make it sticky!
// http://css-tricks.com/13465-persistent-headers/ $xScroll.add($yScroll)
// and https://github.com/jmosbech/StickyTableHeaders by Jonas Mosbech .unbind( ('scroll resize '.split(' ').join( namespace )).replace(/\s+/g, ' ') )
// ************************** .bind('scroll resize '.split(' ').join( namespace ), function( event ) {
ts.addWidget({ scrollSticky( event.type === 'resize' );
id: "stickyHeaders", });
priority: 60, // sticky widget must be initialized after the filter widget! c.$table
options: { .unbind('stickyHeadersUpdate' + namespace)
stickyHeaders : '', // extra class name added to the sticky header row .bind('stickyHeadersUpdate' + namespace, function(){
stickyHeaders_attachTo : null, // jQuery selector or object to attach sticky header to scrollSticky( true );
stickyHeaders_xScroll : null, // jQuery selector or object to monitor horizontal scroll position (defaults: xScroll > attachTo > window) });
stickyHeaders_yScroll : null, // jQuery selector or object to monitor vertical scroll position (defaults: yScroll > attachTo > window)
stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element if (wo.stickyHeaders_addResizeEvent) {
stickyHeaders_filteredToTop: true, // scroll table top into view after filtering ts.addHeaderResizeEvent(table);
stickyHeaders_cloneId : '-sticky', // added to table ID, if it exists }
stickyHeaders_addResizeEvent : true, // trigger "resize" event on headers
stickyHeaders_includeCaption : true, // if false and a caption exist, it won't be included in the sticky header // look for filter widget
stickyHeaders_zIndex : 2 // The zIndex of the stickyHeaders, allows the user to adjust this to their needs if ($table.hasClass('hasFilters') && wo.filter_columnFilters) {
}, // scroll table into view after filtering, if sticky header is active - #482
format: function(table, c, wo) { $table.bind('filterEnd' + namespace, function() {
// filter widget doesn't initialize on an empty table. Fixes #449 // $(':focus') needs jQuery 1.6+
if ( c.$table.hasClass('hasStickyHeaders') || ($.inArray('filter', c.widgets) >= 0 && !c.$table.hasClass('hasFilters')) ) { var $td = $(document.activeElement).closest('td'),
return; column = $td.parent().children().index($td);
} // only scroll if sticky header is active
var index, len, $t, if ($stickyWrap.hasClass(ts.css.stickyVis) && wo.stickyHeaders_filteredToTop) {
$table = c.$table, // scroll to original table (not sticky clone)
// add position: relative to attach element, hopefully it won't cause trouble. window.scrollTo(0, $table.position().top);
$attach = $(wo.stickyHeaders_attachTo), // give same input/select focus; check if c.$filters exists; fixes #594
namespace = c.namespace + 'stickyheaders ', if (column >= 0 && c.$filters) {
// element to watch for the scroll event c.$filters.eq(column).find('a, select, input').filter(':visible').focus();
$yScroll = $(wo.stickyHeaders_yScroll || wo.stickyHeaders_attachTo || window),
$xScroll = $(wo.stickyHeaders_xScroll || wo.stickyHeaders_attachTo || window),
$thead = $table.children('thead:first'),
$header = $thead.children('tr').not('.sticky-false').children(),
$tfoot = $table.children('tfoot'),
$stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '',
stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0,
// is this table nested? If so, find parent sticky header wrapper (div, not table)
$nestedSticky = $table.parent().closest('.' + ts.css.table).hasClass('hasStickyHeaders') ?
$table.parent().closest('table.tablesorter')[0].config.widgetOptions.$sticky.parent() : [],
nestedStickyTop = $nestedSticky.length ? $nestedSticky.height() : 0,
// clone table, then wrap to make sticky header
$stickyTable = wo.$sticky = $table.clone()
.addClass('containsStickyHeaders ' + ts.css.sticky + ' ' + wo.stickyHeaders + ' ' + c.namespace.slice(1) + '_extra_table' )
.wrap('<div class="' + ts.css.stickyWrap + '">'),
$stickyWrap = $stickyTable.parent()
.addClass(ts.css.stickyHide)
.css({
position : $attach.length ? 'absolute' : 'fixed',
padding : parseInt( $stickyTable.parent().parent().css('padding-left'), 10 ),
top : stickyOffset + nestedStickyTop,
left : 0,
visibility : 'hidden',
zIndex : wo.stickyHeaders_zIndex || 2
}),
$stickyThead = $stickyTable.children('thead:first'),
$stickyCells,
laststate = '',
spacing = 0,
setWidth = function($orig, $clone){
var index, width, border, $cell, $this,
$cells = $orig.filter(':visible'),
len = $cells.length;
for ( index = 0; index < len; index++ ) {
$cell = $clone.filter(':visible').eq(index);
$this = $cells.eq(index);
// code from https://github.com/jmosbech/StickyTableHeaders
if ($this.css('box-sizing') === 'border-box') {
width = $this.outerWidth();
} else {
if ($cell.css('border-collapse') === 'collapse') {
if (window.getComputedStyle) {
width = parseFloat( window.getComputedStyle($this[0], null).width );
} else {
// ie8 only
border = parseFloat( $this.css('border-width') );
width = $this.outerWidth() - parseFloat( $this.css('padding-left') ) - parseFloat( $this.css('padding-right') ) - border;
}
} else {
width = $this.width();
} }
} }
$cell.css({
'width': width,
'min-width': width,
'max-width': width
});
}
},
resizeHeader = function() {
stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0;
spacing = 0;
$stickyWrap.css({
left : $attach.length ? parseInt($attach.css('padding-left'), 10) || 0 :
$table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing,
width: $table.outerWidth()
}); });
setWidth( $table, $stickyTable ); ts.filter.bindSearch( $table, $stickyCells.find('.' + ts.css.filter) );
setWidth( $header, $stickyCells ); // support hideFilters
}, if (wo.filter_hideFilters) {
scrollSticky = function( resizing ) { ts.filter.hideFilters($stickyTable, c);
if (!$table.is(':visible')) { return; } // fixes #278
// Detect nested tables - fixes #724
nestedStickyTop = $nestedSticky.length ? $nestedSticky.offset().top - $yScroll.scrollTop() + $nestedSticky.height() : 0;
var offset = $table.offset(),
yWindow = $.isWindow( $yScroll[0] ), // $.isWindow needs jQuery 1.4.3
xWindow = $.isWindow( $xScroll[0] ),
// scrollTop = ( $attach.length ? $attach.offset().top : $yScroll.scrollTop() ) + stickyOffset + nestedStickyTop,
scrollTop = ( $attach.length ? ( yWindow ? $yScroll.scrollTop() : $yScroll.offset().top ) : $yScroll.scrollTop() ) + stickyOffset + nestedStickyTop,
tableHeight = $table.height() - ($stickyWrap.height() + ($tfoot.height() || 0)),
isVisible = ( scrollTop > offset.top ) && ( scrollTop < offset.top + tableHeight ) ? 'visible' : 'hidden',
cssSettings = { visibility : isVisible };
if ($attach.length) {
cssSettings.top = yWindow ? scrollTop - $attach.offset().top : $attach.scrollTop();
} }
if (xWindow) {
// adjust when scrolling horizontally - fixes issue #143
cssSettings.left = $table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing;
}
if ($nestedSticky.length) {
cssSettings.top = ( cssSettings.top || 0 ) + stickyOffset + nestedStickyTop;
}
$stickyWrap
.removeClass( ts.css.stickyVis + ' ' + ts.css.stickyHide )
.addClass( isVisible === 'visible' ? ts.css.stickyVis : ts.css.stickyHide )
.css(cssSettings);
if (isVisible !== laststate || resizing) {
// make sure the column widths match
resizeHeader();
laststate = isVisible;
}
};
// only add a position relative if a position isn't already defined
if ($attach.length && !$attach.css('position')) {
$attach.css('position', 'relative');
}
// fix clone ID, if it exists - fixes #271
if ($stickyTable.attr('id')) { $stickyTable[0].id += wo.stickyHeaders_cloneId; }
// clear out cloned table, except for sticky header
// include caption & filter row (fixes #126 & #249) - don't remove cells to get correct cell indexing
$stickyTable.find('thead:gt(0), tr.sticky-false').hide();
$stickyTable.find('tbody, tfoot').remove();
$stickyTable.find('caption').toggle(wo.stickyHeaders_includeCaption);
// issue #172 - find td/th in sticky header
$stickyCells = $stickyThead.children().children();
$stickyTable.css({ height:0, width:0, margin: 0 });
// remove resizable block
$stickyCells.find('.' + ts.css.resizer).remove();
// update sticky header class names to match real header after sorting
$table
.addClass('hasStickyHeaders')
.bind('pagerComplete' + namespace, function() {
resizeHeader();
});
ts.bindEvents(table, $stickyThead.children().children('.' + ts.css.header));
// add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned.
$table.after( $stickyWrap );
// onRenderHeader is defined, we need to do something about it (fixes #641)
if (c.onRenderHeader) {
$t = $stickyThead.children('tr').children();
len = $t.length;
for ( index = 0; index < len; index++ ) {
// send second parameter
c.onRenderHeader.apply( $t.eq( index ), [ index, c, $stickyTable ] );
} }
$table.trigger('stickyHeadersInit');
},
remove: function(table, c, wo) {
var namespace = c.namespace + 'stickyheaders ';
c.$table
.removeClass('hasStickyHeaders')
.unbind( ('pagerComplete filterEnd stickyHeadersUpdate '.split(' ').join(namespace)).replace(/\s+/g, ' ') )
.next('.' + ts.css.stickyWrap).remove();
if (wo.$sticky && wo.$sticky.length) { wo.$sticky.remove(); } // remove cloned table
$(window)
.add(wo.stickyHeaders_xScroll)
.add(wo.stickyHeaders_yScroll)
.add(wo.stickyHeaders_attachTo)
.unbind( ('scroll resize '.split(' ').join(namespace)).replace(/\s+/g, ' ') );
ts.addHeaderResizeEvent(table, false);
} }
});
// make it sticky!
$xScroll.add($yScroll)
.unbind( ('scroll resize '.split(' ').join( namespace )).replace(/\s+/g, ' ') )
.bind('scroll resize '.split(' ').join( namespace ), function( event ) {
scrollSticky( event.type === 'resize' );
});
c.$table
.unbind('stickyHeadersUpdate' + namespace)
.bind('stickyHeadersUpdate' + namespace, function(){
scrollSticky( true );
});
if (wo.stickyHeaders_addResizeEvent) {
ts.addHeaderResizeEvent(table);
}
// look for filter widget
if ($table.hasClass('hasFilters') && wo.filter_columnFilters) {
// scroll table into view after filtering, if sticky header is active - #482
$table.bind('filterEnd' + namespace, function() {
// $(':focus') needs jQuery 1.6+
var $td = $(document.activeElement).closest('td'),
column = $td.parent().children().index($td);
// only scroll if sticky header is active
if ($stickyWrap.hasClass(ts.css.stickyVis) && wo.stickyHeaders_filteredToTop) {
// scroll to original table (not sticky clone)
window.scrollTo(0, $table.position().top);
// give same input/select focus; check if c.$filters exists; fixes #594
if (column >= 0 && c.$filters) {
c.$filters.eq(column).find('a, select, input').filter(':visible').focus();
}
}
});
ts.filter.bindSearch( $table, $stickyCells.find('.' + ts.css.filter) );
// support hideFilters
if (wo.filter_hideFilters) {
ts.filter.hideFilters($stickyTable, c);
}
}
$table.trigger('stickyHeadersInit');
},
remove: function(table, c, wo) {
var namespace = c.namespace + 'stickyheaders ';
c.$table
.removeClass('hasStickyHeaders')
.unbind( ('pagerComplete filterEnd stickyHeadersUpdate '.split(' ').join(namespace)).replace(/\s+/g, ' ') )
.next('.' + ts.css.stickyWrap).remove();
if (wo.$sticky && wo.$sticky.length) { wo.$sticky.remove(); } // remove cloned table
$(window)
.add(wo.stickyHeaders_xScroll)
.add(wo.stickyHeaders_yScroll)
.add(wo.stickyHeaders_attachTo)
.unbind( ('scroll resize '.split(' ').join(namespace)).replace(/\s+/g, ' ') );
ts.addHeaderResizeEvent(table, false);
}
});
})(jQuery, window); })(jQuery, window);

View File

@ -1,89 +1,89 @@
/*! Widget: storage - updated 3/26/2015 (v2.21.3) */ /*! Widget: storage - updated 3/26/2015 (v2.21.3) */
;(function ($, window, document) { ;(function ($, window, document) {
'use strict'; 'use strict';
var ts = $.tablesorter || {}; var ts = $.tablesorter || {};
// *** Store data in local storage, with a cookie fallback *** // *** Store data in local storage, with a cookie fallback ***
/* IE7 needs JSON library for JSON.stringify - (http://caniuse.com/#search=json) /* IE7 needs JSON library for JSON.stringify - (http://caniuse.com/#search=json)
if you need it, then include https://github.com/douglascrockford/JSON-js if you need it, then include https://github.com/douglascrockford/JSON-js
$.parseJSON is not available is jQuery versions older than 1.4.1, using older $.parseJSON is not available is jQuery versions older than 1.4.1, using older
versions will only allow storing information for one page at a time versions will only allow storing information for one page at a time
// *** Save data (JSON format only) *** // *** Save data (JSON format only) ***
// val must be valid JSON... use http://jsonlint.com/ to ensure it is valid // val must be valid JSON... use http://jsonlint.com/ to ensure it is valid
var val = { "mywidget" : "data1" }; // valid JSON uses double quotes var val = { "mywidget" : "data1" }; // valid JSON uses double quotes
// $.tablesorter.storage(table, key, val); // $.tablesorter.storage(table, key, val);
$.tablesorter.storage(table, 'tablesorter-mywidget', val); $.tablesorter.storage(table, 'tablesorter-mywidget', val);
// *** Get data: $.tablesorter.storage(table, key); *** // *** Get data: $.tablesorter.storage(table, key); ***
v = $.tablesorter.storage(table, 'tablesorter-mywidget'); v = $.tablesorter.storage(table, 'tablesorter-mywidget');
// val may be empty, so also check for your data // val may be empty, so also check for your data
val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : ''; val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : '';
alert(val); // "data1" if saved, or "" if not alert(val); // 'data1' if saved, or '' if not
*/ */
ts.storage = function(table, key, value, options) { ts.storage = function(table, key, value, options) {
table = $(table)[0]; table = $(table)[0];
var cookieIndex, cookies, date, var cookieIndex, cookies, date,
hasStorage = false, hasStorage = false,
values = {}, values = {},
c = table.config, c = table.config,
wo = c && c.widgetOptions, wo = c && c.widgetOptions,
storageType = ( options && options.useSessionStorage ) || ( wo && wo.storage_useSessionStorage ) ? storageType = ( options && options.useSessionStorage ) || ( wo && wo.storage_useSessionStorage ) ?
'sessionStorage' : 'localStorage', 'sessionStorage' : 'localStorage',
$table = $(table), $table = $(table),
// id from (1) options ID, (2) table "data-table-group" attribute, (3) widgetOptions.storage_tableId, // id from (1) options ID, (2) table 'data-table-group' attribute, (3) widgetOptions.storage_tableId,
// (4) table ID, then (5) table index // (4) table ID, then (5) table index
id = options && options.id || id = options && options.id ||
$table.attr( options && options.group || wo && wo.storage_group || 'data-table-group') || $table.attr( options && options.group || wo && wo.storage_group || 'data-table-group') ||
wo && wo.storage_tableId || table.id || $('.tablesorter').index( $table ), wo && wo.storage_tableId || table.id || $('.tablesorter').index( $table ),
// url from (1) options url, (2) table "data-table-page" attribute, (3) widgetOptions.storage_fixedUrl, // url from (1) options url, (2) table 'data-table-page' attribute, (3) widgetOptions.storage_fixedUrl,
// (4) table.config.fixedUrl (deprecated), then (5) window location path // (4) table.config.fixedUrl (deprecated), then (5) window location path
url = options && options.url || url = options && options.url ||
$table.attr(options && options.page || wo && wo.storage_page || 'data-table-page') || $table.attr(options && options.page || wo && wo.storage_page || 'data-table-page') ||
wo && wo.storage_fixedUrl || c && c.fixedUrl || window.location.pathname; wo && wo.storage_fixedUrl || c && c.fixedUrl || window.location.pathname;
// https://gist.github.com/paulirish/5558557 // https://gist.github.com/paulirish/5558557
if (storageType in window) { if (storageType in window) {
try { try {
window[storageType].setItem('_tmptest', 'temp'); window[storageType].setItem('_tmptest', 'temp');
hasStorage = true; hasStorage = true;
window[storageType].removeItem('_tmptest'); window[storageType].removeItem('_tmptest');
} catch(error) { } catch (error) {
if (c && c.debug) { if (c && c.debug) {
ts.log( storageType + ' is not supported in this browser' ); ts.log( storageType + ' is not supported in this browser' );
}
} }
} }
} // *** get value ***
// *** get value *** if ($.parseJSON) {
if ($.parseJSON) { if (hasStorage) {
if (hasStorage) { values = $.parseJSON( window[storageType][key] || 'null' ) || {};
values = $.parseJSON( window[storageType][key] || 'null' ) || {}; } else {
// old browser, using cookies
cookies = document.cookie.split(/[;\s|=]/);
// add one to get from the key to the value
cookieIndex = $.inArray(key, cookies) + 1;
values = (cookieIndex !== 0) ? $.parseJSON(cookies[cookieIndex] || 'null') || {} : {};
}
}
// allow value to be an empty string too
if ((value || value === '') && window.JSON && JSON.hasOwnProperty('stringify')) {
// add unique identifiers = url pathname > table ID/index on page > data
if (!values[url]) {
values[url] = {};
}
values[url][id] = value;
// *** set value ***
if (hasStorage) {
window[storageType][key] = JSON.stringify(values);
} else {
date = new Date();
date.setTime(date.getTime() + (31536e+6)); // 365 days
document.cookie = key + '=' + (JSON.stringify(values)).replace(/\"/g, '\"') + '; expires=' + date.toGMTString() + '; path=/';
}
} else { } else {
// old browser, using cookies return values && values[url] ? values[url][id] : '';
cookies = document.cookie.split(/[;\s|=]/);
// add one to get from the key to the value
cookieIndex = $.inArray(key, cookies) + 1;
values = (cookieIndex !== 0) ? $.parseJSON(cookies[cookieIndex] || 'null') || {} : {};
} }
} };
// allow value to be an empty string too
if ((value || value === '') && window.JSON && JSON.hasOwnProperty('stringify')) {
// add unique identifiers = url pathname > table ID/index on page > data
if (!values[url]) {
values[url] = {};
}
values[url][id] = value;
// *** set value ***
if (hasStorage) {
window[storageType][key] = JSON.stringify(values);
} else {
date = new Date();
date.setTime(date.getTime() + (31536e+6)); // 365 days
document.cookie = key + '=' + (JSON.stringify(values)).replace(/\"/g,'\"') + '; expires=' + date.toGMTString() + '; path=/';
}
} else {
return values && values[url] ? values[url][id] : '';
}
};
})(jQuery, window, document); })(jQuery, window, document);

View File

@ -1,185 +1,185 @@
/*! Widget: uitheme - updated 3/26/2015 (v2.21.3) */ /*! Widget: uitheme - updated 3/26/2015 (v2.21.3) */
;(function ($) { ;(function ($) {
'use strict'; 'use strict';
var ts = $.tablesorter || {}; var ts = $.tablesorter || {};
ts.themes = { ts.themes = {
'bootstrap' : { 'bootstrap' : {
table : 'table table-bordered table-striped', table : 'table table-bordered table-striped',
caption : 'caption', caption : 'caption',
// header class names // header class names
header : 'bootstrap-header', // give the header a gradient background (theme.bootstrap_2.css) header : 'bootstrap-header', // give the header a gradient background (theme.bootstrap_2.css)
sortNone : '', sortNone : '',
sortAsc : '', sortAsc : '',
sortDesc : '', sortDesc : '',
active : '', // applied when column is sorted active : '', // applied when column is sorted
hover : '', // custom css required - a defined bootstrap style may not override other classes hover : '', // custom css required - a defined bootstrap style may not override other classes
// icon class names // icon class names
icons : '', // add "icon-white" to make them white; this icon class is added to the <i> in the header icons : '', // add 'icon-white' to make them white; this icon class is added to the <i> in the header
iconSortNone : 'bootstrap-icon-unsorted', // class name added to icon when column is not sorted iconSortNone : 'bootstrap-icon-unsorted', // class name added to icon when column is not sorted
iconSortAsc : 'icon-chevron-up glyphicon glyphicon-chevron-up', // class name added to icon when column has ascending sort iconSortAsc : 'icon-chevron-up glyphicon glyphicon-chevron-up', // class name added to icon when column has ascending sort
iconSortDesc : 'icon-chevron-down glyphicon glyphicon-chevron-down', // class name added to icon when column has descending sort iconSortDesc : 'icon-chevron-down glyphicon glyphicon-chevron-down', // class name added to icon when column has descending sort
filterRow : '', // filter row class filterRow : '', // filter row class
footerRow : '', footerRow : '',
footerCells : '', footerCells : '',
even : '', // even row zebra striping even : '', // even row zebra striping
odd : '' // odd row zebra striping odd : '' // odd row zebra striping
}, },
'jui' : { 'jui' : {
table : 'ui-widget ui-widget-content ui-corner-all', // table classes table : 'ui-widget ui-widget-content ui-corner-all', // table classes
caption : 'ui-widget-content', caption : 'ui-widget-content',
// header class names // header class names
header : 'ui-widget-header ui-corner-all ui-state-default', // header classes header : 'ui-widget-header ui-corner-all ui-state-default', // header classes
sortNone : '', sortNone : '',
sortAsc : '', sortAsc : '',
sortDesc : '', sortDesc : '',
active : 'ui-state-active', // applied when column is sorted active : 'ui-state-active', // applied when column is sorted
hover : 'ui-state-hover', // hover class hover : 'ui-state-hover', // hover class
// icon class names // icon class names
icons : 'ui-icon', // icon class added to the <i> in the header icons : 'ui-icon', // icon class added to the <i> in the header
iconSortNone : 'ui-icon-carat-2-n-s', // class name added to icon when column is not sorted iconSortNone : 'ui-icon-carat-2-n-s', // class name added to icon when column is not sorted
iconSortAsc : 'ui-icon-carat-1-n', // class name added to icon when column has ascending sort iconSortAsc : 'ui-icon-carat-1-n', // class name added to icon when column has ascending sort
iconSortDesc : 'ui-icon-carat-1-s', // class name added to icon when column has descending sort iconSortDesc : 'ui-icon-carat-1-s', // class name added to icon when column has descending sort
filterRow : '', filterRow : '',
footerRow : '', footerRow : '',
footerCells : '', footerCells : '',
even : 'ui-widget-content', // even row zebra striping even : 'ui-widget-content', // even row zebra striping
odd : 'ui-state-default' // odd row zebra striping odd : 'ui-state-default' // odd row zebra striping
} }
}; };
$.extend(ts.css, { $.extend(ts.css, {
wrapper : 'tablesorter-wrapper' // ui theme & resizable wrapper : 'tablesorter-wrapper' // ui theme & resizable
}); });
ts.addWidget({ ts.addWidget({
id: "uitheme", id: 'uitheme',
priority: 10, priority: 10,
format: function(table, c, wo) { format: function(table, c, wo) {
var i, hdr, icon, time, $header, $icon, $tfoot, $h, oldtheme, oldremove, oldIconRmv, hasOldTheme, var i, hdr, icon, time, $header, $icon, $tfoot, $h, oldtheme, oldremove, oldIconRmv, hasOldTheme,
themesAll = ts.themes, themesAll = ts.themes,
$table = c.$table.add( $( c.namespace + '_extra_table' ) ), $table = c.$table.add( $( c.namespace + '_extra_table' ) ),
$headers = c.$headers.add( $( c.namespace + '_extra_headers' ) ), $headers = c.$headers.add( $( c.namespace + '_extra_headers' ) ),
theme = c.theme || 'jui', theme = c.theme || 'jui',
themes = themesAll[theme] || {}, themes = themesAll[theme] || {},
remove = $.trim( [ themes.sortNone, themes.sortDesc, themes.sortAsc, themes.active ].join( ' ' ) ), remove = $.trim( [ themes.sortNone, themes.sortDesc, themes.sortAsc, themes.active ].join( ' ' ) ),
iconRmv = $.trim( [ themes.iconSortNone, themes.iconSortDesc, themes.iconSortAsc ].join( ' ' ) ); iconRmv = $.trim( [ themes.iconSortNone, themes.iconSortDesc, themes.iconSortAsc ].join( ' ' ) );
if (c.debug) { time = new Date(); } if (c.debug) { time = new Date(); }
// initialization code - run once // initialization code - run once
if (!$table.hasClass('tablesorter-' + theme) || c.theme !== c.appliedTheme || !wo.uitheme_applied) { if (!$table.hasClass('tablesorter-' + theme) || c.theme !== c.appliedTheme || !wo.uitheme_applied) {
wo.uitheme_applied = true; wo.uitheme_applied = true;
oldtheme = themesAll[c.appliedTheme] || {}; oldtheme = themesAll[c.appliedTheme] || {};
hasOldTheme = !$.isEmptyObject(oldtheme); hasOldTheme = !$.isEmptyObject(oldtheme);
oldremove = hasOldTheme ? [ oldtheme.sortNone, oldtheme.sortDesc, oldtheme.sortAsc, oldtheme.active ].join( ' ' ) : ''; oldremove = hasOldTheme ? [ oldtheme.sortNone, oldtheme.sortDesc, oldtheme.sortAsc, oldtheme.active ].join( ' ' ) : '';
oldIconRmv = hasOldTheme ? [ oldtheme.iconSortNone, oldtheme.iconSortDesc, oldtheme.iconSortAsc ].join( ' ' ) : ''; oldIconRmv = hasOldTheme ? [ oldtheme.iconSortNone, oldtheme.iconSortDesc, oldtheme.iconSortAsc ].join( ' ' ) : '';
if (hasOldTheme) { if (hasOldTheme) {
wo.zebra[0] = $.trim( ' ' + wo.zebra[0].replace(' ' + oldtheme.even, '') ); wo.zebra[0] = $.trim( ' ' + wo.zebra[0].replace(' ' + oldtheme.even, '') );
wo.zebra[1] = $.trim( ' ' + wo.zebra[1].replace(' ' + oldtheme.odd, '') ); wo.zebra[1] = $.trim( ' ' + wo.zebra[1].replace(' ' + oldtheme.odd, '') );
c.$tbodies.children().removeClass( [oldtheme.even, oldtheme.odd].join(' ') ); c.$tbodies.children().removeClass( [ oldtheme.even, oldtheme.odd ].join(' ') );
}
// update zebra stripes
if (themes.even) { wo.zebra[0] += ' ' + themes.even; }
if (themes.odd) { wo.zebra[1] += ' ' + themes.odd; }
// add caption style
$table.children('caption')
.removeClass(oldtheme.caption || '')
.addClass(themes.caption);
// add table/footer class names
$tfoot = $table
// remove other selected themes
.removeClass( (c.appliedTheme ? 'tablesorter-' + (c.appliedTheme || '') : '') + ' ' + (oldtheme.table || '') )
.addClass('tablesorter-' + theme + ' ' + (themes.table || '')) // add theme widget class name
.children('tfoot');
c.appliedTheme = c.theme;
if ($tfoot.length) {
$tfoot
// if oldtheme.footerRow or oldtheme.footerCells are undefined, all class names are removed
.children('tr').removeClass(oldtheme.footerRow || '').addClass(themes.footerRow)
.children('th, td').removeClass(oldtheme.footerCells || '').addClass(themes.footerCells);
}
// update header classes
$headers
.removeClass( (hasOldTheme ? [oldtheme.header, oldtheme.hover, oldremove].join(' ') : '') || '' )
.addClass(themes.header)
.not('.sorter-false')
.unbind('mouseenter.tsuitheme mouseleave.tsuitheme')
.bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(event) {
// toggleClass with switch added in jQuery 1.3
$(this)[ event.type === 'mouseenter' ? 'addClass' : 'removeClass' ](themes.hover || '');
});
$headers.each(function(){
var $this = $(this);
if (!$this.find('.' + ts.css.wrapper).length) {
// Firefox needs this inner div to position the icon & resizer correctly
$this.wrapInner('<div class="' + ts.css.wrapper + '" style="position:relative;height:100%;width:100%"></div>');
} }
}); // update zebra stripes
if (c.cssIcon) { if (themes.even) { wo.zebra[0] += ' ' + themes.even; }
// if c.cssIcon is '', then no <i> is added to the header if (themes.odd) { wo.zebra[1] += ' ' + themes.odd; }
// add caption style
$table.children('caption')
.removeClass(oldtheme.caption || '')
.addClass(themes.caption);
// add table/footer class names
$tfoot = $table
// remove other selected themes
.removeClass( (c.appliedTheme ? 'tablesorter-' + (c.appliedTheme || '') : '') + ' ' + (oldtheme.table || '') )
.addClass('tablesorter-' + theme + ' ' + (themes.table || '')) // add theme widget class name
.children('tfoot');
c.appliedTheme = c.theme;
if ($tfoot.length) {
$tfoot
// if oldtheme.footerRow or oldtheme.footerCells are undefined, all class names are removed
.children('tr').removeClass(oldtheme.footerRow || '').addClass(themes.footerRow)
.children('th, td').removeClass(oldtheme.footerCells || '').addClass(themes.footerCells);
}
// update header classes
$headers $headers
.find('.' + ts.css.icon) .removeClass( (hasOldTheme ? [ oldtheme.header, oldtheme.hover, oldremove ].join(' ') : '') || '' )
.removeClass(hasOldTheme ? [oldtheme.icons, oldIconRmv].join(' ') : '') .addClass(themes.header)
.addClass(themes.icons || ''); .not('.sorter-false')
} .unbind('mouseenter.tsuitheme mouseleave.tsuitheme')
if ($table.hasClass('hasFilters')) { .bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(event) {
$table.children('thead').children('.' + ts.css.filterRow) // toggleClass with switch added in jQuery 1.3
.removeClass(hasOldTheme ? oldtheme.filterRow || '' : '') $(this)[ event.type === 'mouseenter' ? 'addClass' : 'removeClass' ](themes.hover || '');
.addClass(themes.filterRow || ''); });
}
} $headers.each(function(){
for (i = 0; i < c.columns; i++) { var $this = $(this);
$header = c.$headers if (!$this.find('.' + ts.css.wrapper).length) {
.add($(c.namespace + '_extra_headers')) // Firefox needs this inner div to position the icon & resizer correctly
.not('.sorter-false') $this.wrapInner('<div class="' + ts.css.wrapper + '" style="position:relative;height:100%;width:100%"></div>');
.filter('[data-column="' + i + '"]');
$icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $();
$h = $headers.not('.sorter-false').filter('[data-column="' + i + '"]:last');
if ($h.length) {
$header.removeClass(remove);
$icon.removeClass(iconRmv);
if ($h[0].sortDisabled) {
// no sort arrows for disabled columns!
$icon.removeClass(themes.icons || '');
} else {
hdr = themes.sortNone;
icon = themes.iconSortNone;
if ($h.hasClass(ts.css.sortAsc)) {
hdr = [themes.sortAsc, themes.active].join(' ');
icon = themes.iconSortAsc;
} else if ($h.hasClass(ts.css.sortDesc)) {
hdr = [themes.sortDesc, themes.active].join(' ');
icon = themes.iconSortDesc;
} }
$header.addClass(hdr); });
$icon.addClass(icon || ''); if (c.cssIcon) {
// if c.cssIcon is '', then no <i> is added to the header
$headers
.find('.' + ts.css.icon)
.removeClass(hasOldTheme ? [ oldtheme.icons, oldIconRmv ].join(' ') : '')
.addClass(themes.icons || '');
}
if ($table.hasClass('hasFilters')) {
$table.children('thead').children('.' + ts.css.filterRow)
.removeClass(hasOldTheme ? oldtheme.filterRow || '' : '')
.addClass(themes.filterRow || '');
} }
} }
for (i = 0; i < c.columns; i++) {
$header = c.$headers
.add($(c.namespace + '_extra_headers'))
.not('.sorter-false')
.filter('[data-column="' + i + '"]');
$icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $();
$h = $headers.not('.sorter-false').filter('[data-column="' + i + '"]:last');
if ($h.length) {
$header.removeClass(remove);
$icon.removeClass(iconRmv);
if ($h[0].sortDisabled) {
// no sort arrows for disabled columns!
$icon.removeClass(themes.icons || '');
} else {
hdr = themes.sortNone;
icon = themes.iconSortNone;
if ($h.hasClass(ts.css.sortAsc)) {
hdr = [ themes.sortAsc, themes.active ].join(' ');
icon = themes.iconSortAsc;
} else if ($h.hasClass(ts.css.sortDesc)) {
hdr = [ themes.sortDesc, themes.active ].join(' ');
icon = themes.iconSortDesc;
}
$header.addClass(hdr);
$icon.addClass(icon || '');
}
}
}
if (c.debug) {
ts.benchmark('Applying ' + theme + ' theme', time);
}
},
remove: function(table, c, wo, refreshing) {
if (!wo.uitheme_applied) { return; }
var $table = c.$table,
theme = c.appliedTheme || 'jui',
themes = ts.themes[ theme ] || ts.themes.jui,
$headers = $table.children('thead').children(),
remove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc,
iconRmv = themes.iconSortNone + ' ' + themes.iconSortDesc + ' ' + themes.iconSortAsc;
$table.removeClass('tablesorter-' + theme + ' ' + themes.table);
wo.uitheme_applied = false;
if (refreshing) { return; }
$table.find(ts.css.header).removeClass(themes.header);
$headers
.unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover
.removeClass(themes.hover + ' ' + remove + ' ' + themes.active)
.filter('.' + ts.css.filterRow)
.removeClass(themes.filterRow);
$headers.find('.' + ts.css.icon).removeClass(themes.icons + ' ' + iconRmv);
} }
if (c.debug) { });
ts.benchmark("Applying " + theme + " theme", time);
}
},
remove: function(table, c, wo, refreshing) {
if (!wo.uitheme_applied) { return; }
var $table = c.$table,
theme = c.appliedTheme || 'jui',
themes = ts.themes[ theme ] || ts.themes.jui,
$headers = $table.children('thead').children(),
remove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc,
iconRmv = themes.iconSortNone + ' ' + themes.iconSortDesc + ' ' + themes.iconSortAsc;
$table.removeClass('tablesorter-' + theme + ' ' + themes.table);
wo.uitheme_applied = false;
if (refreshing) { return; }
$table.find(ts.css.header).removeClass(themes.header);
$headers
.unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover
.removeClass(themes.hover + ' ' + remove + ' ' + themes.active)
.filter('.' + ts.css.filterRow)
.removeClass(themes.filterRow);
$headers.find('.' + ts.css.icon).removeClass(themes.icons + ' ' + iconRmv);
}
});
})(jQuery); })(jQuery);

0
jscs.errors.txt Normal file
View File

View File

@ -75,6 +75,7 @@
"grunt-contrib-qunit": "^0.5.2", "grunt-contrib-qunit": "^0.5.2",
"grunt-contrib-uglify": "^0.7.0", "grunt-contrib-uglify": "^0.7.0",
"grunt-contrib-watch": "^0.6.1", "grunt-contrib-watch": "^0.6.1",
"grunt-jscs": "^1.8.0",
"grunt-string-replace": "^1.0.0" "grunt-string-replace": "^1.0.0"
} }
} }