Merge branch 'working' into build

This commit is contained in:
Mottie 2015-02-20 10:54:52 -06:00
commit b9b09922a3
8 changed files with 179 additions and 163 deletions

View File

@ -135,18 +135,15 @@
}, },
calcFilters = function(table, p) { calcFilters = function(table, p) {
var tbodyIndex, var c = table.config,
c = table.config,
hasFilters = c.$table.hasClass('hasFilters'); hasFilters = c.$table.hasClass('hasFilters');
if (hasFilters && !p.ajaxUrl) { if (hasFilters && !p.ajaxUrl) {
if ($.isEmptyObject(c.cache)) { if ($.isEmptyObject(c.cache)) {
// delayInit: true so nothing is in the cache // delayInit: true so nothing is in the cache
p.filteredRows = p.totalRows = c.$tbodies.eq(0).children('tr').not( p.countChildRows ? '' : '.' + c.cssChildRow ).length; p.filteredRows = p.totalRows = c.$tbodies.eq(0).children('tr').not( p.countChildRows ? '' : '.' + c.cssChildRow ).length;
} else { } else {
// just in case the pager tbody isn't the first tbody
tbodyIndex = c.$table.children('tbody').index( c.$tbodies.eq(0) );
p.filteredRows = 0; p.filteredRows = 0;
$.each(c.cache[tbodyIndex].normalized, function(i, el) { $.each(c.cache[0].normalized, function(i, el) {
p.filteredRows += p.regexRows.test(el[c.columns].$row[0].className) ? 0 : 1; p.filteredRows += p.regexRows.test(el[c.columns].$row[0].className) ? 0 : 1;
}); });
} }
@ -659,8 +656,7 @@
c.$table.trigger('updateCache', [ function(){ c.$table.trigger('updateCache', [ function(){
var i, var i,
rows = [], rows = [],
tbodyIndex = c.$table.children('tbody').index( c.$tbodies.eq(0) ), n = table.config.cache[0].normalized;
n = table.config.cache[tbodyIndex].normalized;
p.totalRows = n.length; p.totalRows = n.length;
for (i = 0; i < p.totalRows; i++) { for (i = 0; i < p.totalRows; i++) {
rows.push(n[i][c.columns].$row); rows.push(n[i][c.columns].$row);

View File

@ -824,11 +824,11 @@
<td></td> <td></td>
</tr> </tr>
<tr id="cssallowclicks"> <tr id="cssnosort">
<td><span class="permalink">cssAllowClicks</span></td> <td><span class="permalink">cssNoSort</span></td>
<td>String</td> <td>String</td>
<td>&quot;tablesorter-allowClicks&quot;</td> <td>&quot;tablesorter-noSort&quot;</td>
<td>Class name added to table header which allows clicks to bubble up. (<span class="version">v2.18.1</span>).</td> <td>Class name added to element inside header. Clicking on that element, or any elements within it won't cause a sort. (<span class="version">v2.19.2</span>).</td>
<td></td> <td></td>
</tr> </tr>
@ -1974,10 +1974,26 @@ $(function(){
<!-- non-sorting tbody --> <!-- non-sorting tbody -->
<tbody id="deprecated" class="tablesorter-infoOnly"> <tbody id="deprecated" class="tablesorter-infoOnly">
<tr><th colspan="5">Deprecated Options</th></tr> <tr><th colspan="5">Deprecated/Removed Options</th></tr>
</tbody> </tbody>
<tbody> <tbody>
<tr id="cssallowclicks">
<td><a href="#" class="permalink alert">cssAllowClicks</a></td>
<td>String</td>
<td></td>
<td>This option was <span class="label label-danger">removed</span>!
It has been replaced by <a href="#cssnosort">cssNoSort</a> which does the opposite of what this class name was supposed to do.
<div class="collapsible">
<p>This option was not working as intended, so it was completely removed - sorry for the lack of notice.</p>
<p>Previous default was <code>&quot;tablesorter-allowClicks&quot;</code></p>
Class name added to table header which allows clicks to bubble up. (added v2.18.1; removed in v2.19.2).
</div>
</td>
<td></td>
</tr>
<tr id="widgetcolumns"> <tr id="widgetcolumns">
<td><a href="#" class="permalink alert">widgetColumns</a></td> <td><a href="#" class="permalink alert">widgetColumns</a></td>
<td></td> <td></td>
@ -5309,12 +5325,12 @@ var config = $('#mytable').data('tablesorter');
<tr id="variable-cache"> <tr id="variable-cache">
<td><a href="#" class="permalink">config.cache</a></td> <td><a href="#" class="permalink">config.cache</a></td>
<td>Object</td> <td>Object</td>
<td>Internal list of table contents (<span class="version">v2.0.18</span>; <span class="version updated">v2.19.1</span> ) <td>Internal list of table contents (<span class="version">v2.0.18</span>; <span class="version updated">v2.19.2</span> )
<div class="collapsible"> <div class="collapsible">
<br> <br>
This object contains the following:<br> This object contains the following:<br>
<ul> <ul>
<li>tbody index <li>tbody index (non-info block only, numeration is the same as for <a href="#variable-tbodies"><code>config.$tbodies</code></a> <span class="version updated">v2.19.2</span>)
<ul> <ul>
<li><code>colMax</code> <li><code>colMax</code>
<ul> <ul>
@ -5780,7 +5796,6 @@ var p = $('#mytable').data('tablesorter').pager;
For example, if you want to get the parsed values for the rows currently displayed within the pager, use the <code>table.config.pager.cacheIndex</code> variable as follows: For example, if you want to get the parsed values for the rows currently displayed within the pager, use the <code>table.config.pager.cacheIndex</code> variable as follows:
<pre class="prettyprint lang-js">var c = $('table')[0].config, <pre class="prettyprint lang-js">var c = $('table')[0].config,
p = c.pager, p = c.pager,
// the cache may not have a zero index if there are any "info-only" tbodies above the main tbody
cache = c.cache[0].normalized, cache = c.cache[0].normalized,
cachedValues = []; cachedValues = [];
$.each( p.cacheIndex, function(i, v) { $.each( p.cacheIndex, function(i, v) {

View File

@ -106,7 +106,7 @@
cssIconAsc : '', // class name added to the icon when the column has an ascending sort cssIconAsc : '', // class name added to the icon when the column has an ascending sort
cssIconDesc : '', // class name added to the icon when the column has a descending sort cssIconDesc : '', // class name added to the icon when the column has a descending sort
cssInfoBlock : 'tablesorter-infoOnly', // don't sort tbody with this class name (only one class name allowed here!) cssInfoBlock : 'tablesorter-infoOnly', // don't sort tbody with this class name (only one class name allowed here!)
cssAllowClicks : 'tablesorter-allowClicks', // class name added to table header which allows clicks to bubble up cssNoSort : 'tablesorter-noSort', // class name added to element inside header; clicking on it won't cause a sort
cssIgnoreRow : 'tablesorter-ignoreRow', // header row to ignore; cells within this row will not be added to c.$headers cssIgnoreRow : 'tablesorter-ignoreRow', // header row to ignore; cells within this row will not be added to c.$headers
// *** selectors // *** selectors
@ -138,7 +138,6 @@
headerRow : 'tablesorter-headerRow', headerRow : 'tablesorter-headerRow',
headerIn : 'tablesorter-header-inner', headerIn : 'tablesorter-header-inner',
icon : 'tablesorter-icon', icon : 'tablesorter-icon',
info : 'tablesorter-infoOnly',
processing : 'tablesorter-processing', processing : 'tablesorter-processing',
sortAsc : 'tablesorter-headerAsc', sortAsc : 'tablesorter-headerAsc',
sortDesc : 'tablesorter-headerDesc', sortDesc : 'tablesorter-headerDesc',
@ -182,37 +181,39 @@
return true; return true;
} }
function getElementText(table, node, cellIndex) { ts.getElementText = function(c, node, cellIndex) {
if (!node) { return ''; } if (!node) { return ''; }
var te, var te,
$node = $(node), t = c.textExtraction || '',
c = table.config, // node could be a jquery object
t = c.textExtraction || ''; // http://jsperf.com/jquery-vs-instanceof-jquery/2
$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!
return $.trim( (t === 'basic' ? $node.attr(c.textAttribute) || node.textContent : node.textContent ) || $node.text() || '' ); return $.trim( ( t === 'basic' ? $node.attr(c.textAttribute) || node.textContent : node.textContent ) || $node.text() || '' );
} else { } else {
if (typeof(t) === 'function') { if (typeof(t) === 'function') {
return $.trim( t(node, table, cellIndex) ); return $.trim( t($node[0], c.table, cellIndex) );
} else if (typeof (te = ts.getColumnData( table, t, cellIndex )) === 'function') { } else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') {
return $.trim( te(node, table, cellIndex) ); return $.trim( te($node[0], c.table, cellIndex) );
} }
} }
// fallback // fallback
return $.trim( node.textContent || $node.text() || '' ); return $.trim( $node[0].textContent || $node.text() || '' );
} }
function detectParserForColumn(table, rows, rowIndex, cellIndex) { function detectParserForColumn(table, rows, rowIndex, cellIndex) {
var cur, $node, var cur, $node,
i = ts.parsers.length, c = table.config,
node = false, i = ts.parsers.length,
nodeValue = '', node = false,
keepLooking = true; nodeValue = '',
keepLooking = true;
while (nodeValue === '' && keepLooking) { while (nodeValue === '' && keepLooking) {
rowIndex++; rowIndex++;
if (rows[rowIndex]) { if (rows[rowIndex]) {
node = rows[rowIndex].cells[cellIndex]; node = rows[rowIndex].cells[cellIndex];
nodeValue = getElementText(table, node, cellIndex); nodeValue = ts.getElementText(c, node, cellIndex);
$node = $(node); $node = $(node);
if (table.config.debug) { if (table.config.debug) {
log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"'); log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"');
@ -295,10 +296,10 @@
/* utils */ /* utils */
function buildCache(table) { function buildCache(table) {
var cc, t, tx, v, i, j, k, $row, rows, cols, cacheTime, var cc, t, tx, v, i, j, k, $row, cols, cacheTime,
totalRows, rowData, colMax, totalRows, rowData, colMax,
c = table.config, c = table.config,
$tb = c.$table.children('tbody'), $tb = c.$tbodies,
extractors = c.extractors, extractors = c.extractors,
parsers = c.parsers; parsers = c.parsers;
c.cache = {}; c.cache = {};
@ -321,68 +322,65 @@
// colMax: # // added at the end // colMax: # // added at the end
}; };
// ignore tbodies with class name from c.cssInfoBlock totalRows = ($tb[k] && $tb[k].rows.length) || 0;
if (!$tb.eq(k).hasClass(c.cssInfoBlock)) { for (i = 0; i < totalRows; ++i) {
totalRows = ($tb[k] && $tb[k].rows.length) || 0; rowData = {
for (i = 0; i < totalRows; ++i) { // order: original row order #
rowData = { // $row : jQuery Object[]
// order: original row order # child: [], // child row text (filter widget)
// $row : jQuery Object[] raw: [] // original row text
child: [], // child row text (filter widget) };
raw: [] // original row text /** Add the table data to main data array */
}; $row = $($tb[k].rows[i]);
/** Add the table data to main data array */ cols = [];
$row = $($tb[k].rows[i]); // if this is a child row, add it to the last row's children and continue to the next row
rows = [ new Array(c.columns) ]; // ignore child row class, if it is the first row
cols = []; if ($row.hasClass(c.cssChildRow) && i !== 0) {
// if this is a child row, add it to the last row's children and continue to the next row t = cc.normalized.length - 1;
// ignore child row class, if it is the first row cc.normalized[t][c.columns].$row = cc.normalized[t][c.columns].$row.add($row);
if ($row.hasClass(c.cssChildRow) && i !== 0) { // add 'hasChild' class name to parent row
t = cc.normalized.length - 1; if (!$row.prev().hasClass(c.cssChildRow)) {
cc.normalized[t][c.columns].$row = cc.normalized[t][c.columns].$row.add($row); $row.prev().addClass(ts.css.cssHasChild);
// add 'hasChild' class name to parent row }
if (!$row.prev().hasClass(c.cssChildRow)) { // save child row content (un-parsed!)
$row.prev().addClass(ts.css.cssHasChild); rowData.child[t] = $.trim( $row[0].textContent || $row.text() || '' );
// go to the next for loop
continue;
}
rowData.$row = $row;
rowData.order = i; // add original row position to rowCache
for (j = 0; j < c.columns; ++j) {
if (typeof parsers[j] === 'undefined') {
if (c.debug) {
log('No parser found for cell:', $row[0].cells[j], 'does it have a header?');
} }
// save child row content (un-parsed!)
rowData.child[t] = $.trim( $row[0].textContent || $row.text() || '' );
// go to the next for loop
continue; continue;
} }
rowData.$row = $row; t = ts.getElementText(c, $row[0].cells[j], j);
rowData.order = i; // add original row position to rowCache rowData.raw.push(t); // save original row text
for (j = 0; j < c.columns; ++j) { // do extract before parsing if there is one
if (typeof parsers[j] === 'undefined') { if (typeof extractors[j].id === 'undefined') {
if (c.debug) { tx = t;
log('No parser found for cell:', $row[0].cells[j], 'does it have a header?'); } else {
} tx = extractors[j].format(t, table, $row[0].cells[j], j);
continue; }
} // allow parsing if the string is empty, previously parsing would change it to zero,
t = getElementText(table, $row[0].cells[j], j); // in case the parser needs to extract data from the table cell attributes
rowData.raw.push(t); // save original row text v = parsers[j].id === 'no-parser' ? '' : parsers[j].format(tx, table, $row[0].cells[j], j);
// do extract before parsing if there is one cols.push( c.ignoreCase && typeof v === 'string' ? v.toLowerCase() : v );
if (typeof extractors[j].id === 'undefined') { if ((parsers[j].type || '').toLowerCase() === 'numeric') {
tx = t; // determine column max value (ignore sign)
} else { colMax[j] = Math.max(Math.abs(v) || 0, colMax[j] || 0);
tx = extractors[j].format(t, table, $row[0].cells[j], j);
}
// allow parsing if the string is empty, previously parsing would change it to zero,
// in case the parser needs to extract data from the table cell attributes
v = parsers[j].id === 'no-parser' ? '' : parsers[j].format(tx, table, $row[0].cells[j], j);
cols.push( c.ignoreCase && typeof v === 'string' ? v.toLowerCase() : v );
if ((parsers[j].type || '').toLowerCase() === 'numeric') {
// determine column max value (ignore sign)
colMax[j] = Math.max(Math.abs(v) || 0, colMax[j] || 0);
}
} }
// ensure rowData is always in the same location (after the last column)
cols[c.columns] = rowData;
cc.normalized.push(cols);
} }
cc.colMax = colMax; // ensure rowData is always in the same location (after the last column)
// total up rows, not including child rows cols[c.columns] = rowData;
c.totalRows += cc.normalized.length; cc.normalized.push(cols);
} }
cc.colMax = colMax;
// total up rows, not including child rows
c.totalRows += cc.normalized.length;
} }
if (c.showProcessing) { if (c.showProcessing) {
ts.isProcessing(table); // remove processing icon ts.isProcessing(table); // remove processing icon
@ -396,7 +394,7 @@
function appendToTable(table, init) { function appendToTable(table, init) {
var c = table.config, var c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
b = table.tBodies, b = c.$tbodies,
rows = [], rows = [],
cc = c.cache, cc = c.cache,
n, totalRows, $bk, $tb, n, totalRows, $bk, $tb,
@ -412,7 +410,7 @@
} }
for (k = 0; k < b.length; k++) { for (k = 0; k < b.length; k++) {
$bk = $(b[k]); $bk = $(b[k]);
if ($bk.length && !$bk.hasClass(c.cssInfoBlock)) { if ($bk.length) {
// get tbody // get tbody
$tb = ts.processTbody(table, $bk, true); $tb = ts.processTbody(table, $bk, true);
n = cc[k].normalized; n = cc[k].normalized;
@ -754,23 +752,23 @@
// sort multiple columns // sort multiple columns
function multisort(table) { /*jshint loopfunc:true */ function multisort(table) { /*jshint loopfunc:true */
var i, k, num, col, sortTime, colMax, var i, k, num, col, sortTime, colMax,
cache, order, sort, x, y, rows, order, sort, x, y,
dir = 0, dir = 0,
c = table.config, c = table.config,
cts = c.textSorter || '', cts = c.textSorter || '',
sortList = c.sortList, sortList = c.sortList,
l = sortList.length, l = sortList.length,
bl = table.tBodies.length; bl = c.$tbodies.length;
if (c.serverSideSorting || isEmptyObject(c.cache)) { // empty table - fixes #206/#346 if (c.serverSideSorting || isEmptyObject(c.cache)) { // empty table - fixes #206/#346
return; return;
} }
if (c.debug) { sortTime = new Date(); } if (c.debug) { sortTime = new Date(); }
for (k = 0; k < bl; k++) { for (k = 0; k < bl; k++) {
colMax = c.cache[k].colMax; colMax = c.cache[k].colMax;
cache = c.cache[k].normalized; rows = c.cache[k].normalized;
cache.sort(function(a, b) { rows.sort(function(a, b) {
// cache is undefined here in IE, so don't use it! // rows is undefined here in IE, so don't use it!
for (i = 0; i < l; i++) { for (i = 0; i < l; i++) {
col = sortList[i][0]; col = sortList[i][0];
order = sortList[i][1]; order = sortList[i][1];
@ -891,7 +889,7 @@
$table.find(c.selectorRemove).remove(); $table.find(c.selectorRemove).remove();
// get position from the dom // get position from the dom
var v, t, row, icell, var v, t, row, icell,
$tb = $table.find('tbody'), $tb = c.$tbodies,
$cell = $(cell), $cell = $(cell),
// update cache - format: function(s, table, cell, cellIndex) // update cache - format: function(s, table, cell, cellIndex)
// no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr'); // no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr');
@ -904,9 +902,9 @@
icell = $cell.index(); icell = $cell.index();
c.cache[tbdy].normalized[row][c.columns].$row = $row; c.cache[tbdy].normalized[row][c.columns].$row = $row;
if (typeof c.extractors[icell].id === 'undefined') { if (typeof c.extractors[icell].id === 'undefined') {
t = getElementText(table, cell, icell); t = ts.getElementText(c, cell, icell);
} else { } else {
t = c.extractors[icell].format( getElementText(table, cell, icell), table, cell, icell ); t = c.extractors[icell].format( ts.getElementText(c, cell, icell), table, cell, icell );
} }
v = c.parsers[icell].id === 'no-parser' ? '' : v = c.parsers[icell].id === 'no-parser' ? '' :
c.parsers[icell].format( t, table, cell, icell ); c.parsers[icell].format( t, table, cell, icell );
@ -940,7 +938,7 @@
$row = $($row).attr('role', 'row'); // make sure we're using a jQuery object $row = $($row).attr('role', 'row'); // make sure we're using a jQuery object
var i, j, l, t, v, rowData, cells, var i, j, l, t, v, rowData, cells,
rows = $row.filter('tr').length, rows = $row.filter('tr').length,
tbdy = $table.find('tbody').index( $row.parents('tbody').filter(':first') ); tbdy = c.$tbodies.index( $row.parents('tbody').filter(':first') );
// fixes adding rows to an empty table - see issue #179 // fixes adding rows to an empty table - see issue #179
if (!(c.parsers && c.parsers.length)) { if (!(c.parsers && c.parsers.length)) {
buildParserCache(table); buildParserCache(table);
@ -957,9 +955,9 @@
// add each cell // add each cell
for (j = 0; j < l; j++) { for (j = 0; j < l; j++) {
if (typeof c.extractors[j].id === 'undefined') { if (typeof c.extractors[j].id === 'undefined') {
t = getElementText(table, $row[i].cells[j], j); t = ts.getElementText(c, $row[i].cells[j], j);
} else { } else {
t = c.extractors[j].format( getElementText(table, $row[i].cells[j], j), table, $row[i].cells[j], j ); t = c.extractors[j].format( ts.getElementText(c, $row[i].cells[j], j), table, $row[i].cells[j], j );
} }
v = c.parsers[j].id === 'no-parser' ? '' : v = c.parsers[j].id === 'no-parser' ? '' :
c.parsers[j].format( t, table, $row[i].cells[j], j ); c.parsers[j].format( t, table, $row[i].cells[j], j );
@ -1200,7 +1198,7 @@
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
$(table.tBodies).not('.' + c.cssInfoBlock).find('tr:first').children(':visible').each(function() { c.$tbodies.find('tr:first').children(':visible').each(function() {
percent = parseInt( ( $(this).width() / overallWidth ) * 1000, 10 ) / 10 + '%'; percent = parseInt( ( $(this).width() / overallWidth ) * 1000, 10 ) / 10 + '%';
colgroup.append( $('<col>').css('width', percent) ); colgroup.append( $('<col>').css('width', percent) );
}); });
@ -1334,7 +1332,9 @@
.find(c.selectorSort).add( $headers.filter(c.selectorSort) ) .find(c.selectorSort).add( $headers.filter(c.selectorSort) )
.unbind( $.trim('mousedown mouseup sort keyup '.split(' ').join(c.namespace + ' ')) ) .unbind( $.trim('mousedown mouseup sort keyup '.split(' ').join(c.namespace + ' ')) )
.bind( $.trim('mousedown mouseup sort keyup '.split(' ').join(c.namespace + ' ')), function(e, external) { .bind( $.trim('mousedown mouseup sort keyup '.split(' ').join(c.namespace + ' ')), function(e, external) {
var cell, type = e.type; var cell,
$target = $(e.target),
type = e.type;
// only recognize left clicks or enter // only recognize left clicks or enter
if ( ((e.which || e.button) !== 1 && !/sort|keyup/.test(type)) || (type === 'keyup' && e.which !== 13) ) { if ( ((e.which || e.button) !== 1 && !/sort|keyup/.test(type)) || (type === 'keyup' && e.which !== 13) ) {
return; return;
@ -1344,10 +1344,16 @@
// set timer on mousedown // set timer on mousedown
if (type === 'mousedown') { if (type === 'mousedown') {
downTime = new Date().getTime(); downTime = new Date().getTime();
cell = $.fn.closest ? $(e.target).closest('td,th') : $(e.target).parents('td,th').filter(':first'); return;
return /(input|select|button|textarea)/i.test(e.target.tagName) || }
// allow clicks to contents of selected cells cell = $.fn.closest ? $target.closest('td,th') : $target.parents('td,th').filter(':first');
cell.hasClass(c.cssAllowClicks) ? '' : !c.cancelSelection; // prevent sort being triggered on form elements
if ( /(input|select|button|textarea)/i.test(e.target.tagName) ||
// nosort class name, or elements within a nosort container
$target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 ||
// elements within a button
$target.parents('button').length > 0 ) {
return !c.cancelSelection;
} }
if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); } if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); }
// jQuery v1.2.6 doesn't have closest() // jQuery v1.2.6 doesn't have closest()

View File

@ -1113,13 +1113,12 @@ ts.filter = {
}, },
findRows: function(table, filters, combinedFilters) { findRows: function(table, filters, combinedFilters) {
if (table.config.lastCombinedFilter === combinedFilters || !table.config.widgetOptions.filter_initialized) { return; } if (table.config.lastCombinedFilter === combinedFilters || !table.config.widgetOptions.filter_initialized) { return; }
var len, $rows, rowIndex, tbodyIndex, $tbody, $cells, $cell, columnIndex, var len, norm_rows, $rows, rowIndex, tbodyIndex, $tbody, $cells, $cell, columnIndex,
childRow, lastSearch, hasSelect, matches, result, showRow, time, val, indx, childRow, lastSearch, hasSelect, matches, result, showRow, time, val, indx,
notFiltered, searchFiltered, filterMatched, excludeMatch, fxn, ffxn, notFiltered, searchFiltered, filterMatched, excludeMatch, fxn, ffxn,
regex = ts.filter.regex, regex = ts.filter.regex,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
$tbodies = c.$table.children('tbody'), // target all tbodies #568
// data object passed to filters; anyMatch is a flag for the filters // data object passed to filters; anyMatch is a flag for the filters
data = { anyMatch: false }, data = { anyMatch: false },
// anyMatch really screws up with these types of filters // anyMatch really screws up with these types of filters
@ -1143,14 +1142,14 @@ ts.filter = {
// combindedFilters are undefined on init // combindedFilters are undefined on init
combinedFilters = (filters || []).join(''); combinedFilters = (filters || []).join('');
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
if ($tbodies.eq(tbodyIndex).hasClass(c.cssInfoBlock || ts.css.info)) { continue; } // ignore info blocks, issue #264 $tbody = ts.processTbody(table, c.$tbodies.eq(tbodyIndex), true);
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true);
// skip child rows & widget added (removable) rows - fixes #448 thanks to @hempel! // skip child rows & widget added (removable) rows - fixes #448 thanks to @hempel!
// $rows = $tbody.children('tr').not(c.selectorRemove); // $rows = $tbody.children('tr').not(c.selectorRemove);
columnIndex = c.columns; columnIndex = c.columns;
// convert stored rows into a jQuery object // convert stored rows into a jQuery object
$rows = $( $.map(c.cache[tbodyIndex].normalized, function(el){ return el[columnIndex].$row.get(); }) ); norm_rows = c.cache[tbodyIndex].normalized;
$rows = $( $.map(norm_rows, function(el){ return el[columnIndex].$row.get(); }) );
if (combinedFilters === '' || wo.filter_serversideFiltering) { if (combinedFilters === '' || wo.filter_serversideFiltering) {
$rows.removeClass(wo.filter_filteredRow).not('.' + c.cssChildRow).show(); $rows.removeClass(wo.filter_filteredRow).not('.' + c.cssChildRow).show();
@ -1207,7 +1206,7 @@ ts.filter = {
// loop through the rows // loop through the rows
for (rowIndex = 0; rowIndex < len; rowIndex++) { for (rowIndex = 0; rowIndex < len; rowIndex++) {
data.cacheArray = c.cache[tbodyIndex].normalized[rowIndex]; data.cacheArray = norm_rows[rowIndex];
childRow = $rows[rowIndex].className; childRow = $rows[rowIndex].className;
// skip child rows & already filtered rows // skip child rows & already filtered rows
@ -1455,26 +1454,23 @@ ts.filter = {
var rowIndex, tbodyIndex, len, row, cache, cell, var rowIndex, tbodyIndex, len, row, cache, cell,
c = table.config, c = table.config,
wo = c.widgetOptions, wo = c.widgetOptions,
$tbodies = c.$table.children('tbody'),
arry = []; arry = [];
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
if (!$tbodies.eq(tbodyIndex).hasClass(c.cssInfoBlock)) { cache = c.cache[tbodyIndex];
cache = c.cache[tbodyIndex]; len = c.cache[tbodyIndex].normalized.length;
len = c.cache[tbodyIndex].normalized.length; // loop through the rows
// loop through the rows for (rowIndex = 0; rowIndex < len; rowIndex++) {
for (rowIndex = 0; rowIndex < len; rowIndex++) { // get cached row from cache.row (old) or row data object (new; last item in normalized array)
// get cached row from cache.row (old) or row data object (new; last item in normalized array) row = cache.row ? cache.row[rowIndex] : cache.normalized[rowIndex][c.columns].$row[0];
row = cache.row ? cache.row[rowIndex] : cache.normalized[rowIndex][c.columns].$row[0]; // check if has class filtered
// check if has class filtered if (onlyAvail && row.className.match(wo.filter_filteredRow)) { continue; }
if (onlyAvail && row.className.match(wo.filter_filteredRow)) { continue; } // get non-normalized cell content
// get non-normalized cell content if (wo.filter_useParsedData || c.parsers[column].parsed || c.$headers.filter('[data-column="' + column + '"]:last').hasClass('filter-parsed')) {
if (wo.filter_useParsedData || c.parsers[column].parsed || c.$headers.filter('[data-column="' + column + '"]:last').hasClass('filter-parsed')) { arry.push( '' + cache.normalized[rowIndex][column] );
arry.push( '' + cache.normalized[rowIndex][column] ); } else {
} else { cell = row.cells[column];
cell = row.cells[column]; if (cell) {
if (cell) { arry.push( $.trim( cell.getAttribute( c.textAttribute ) || cell.textContent || $(cell).text() ) );
arry.push( $.trim( cell.getAttribute( c.textAttribute ) || cell.textContent || $(cell).text() ) );
}
} }
} }
} }

View File

@ -149,14 +149,13 @@
}, },
getRows: function(c, wo) { getRows: function(c, wo) {
// the cache may not have a zero index if there are any "info-only" tbodies above the main tbody var norm_rows = c.cache[0].normalized,
var cache = c.cache[0].normalized,
rows = []; rows = [];
chart_rows = []; chart_rows = [];
chart_categories = []; chart_categories = [];
chart_category = []; chart_category = [];
$.each(cache, function(indx, rowVal) { $.each(norm_rows, function(indx, rowVal) {
var i, txt, var i, txt,
$tr = rowVal[c.columns].$row, $tr = rowVal[c.columns].$row,
$cells = $tr.children('th,td'), $cells = $tr.children('th,td'),

View File

@ -54,7 +54,7 @@ ts.grouping = {
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, cache, 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,
@ -89,15 +89,15 @@ ts.grouping = {
} }
} }
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) { for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) {
cache = 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 = cache[rowIndex] ? currentGroup = norm_rows[rowIndex] ?
ts.grouping.types[grouping[1]]( c, c.$headers.filter('[data-column="' + column + '"]:last'), cache[rowIndex][column], /date/.test(groupClass) ? ts.grouping.types[grouping[1]]( c, c.$headers.filter('[data-column="' + column + '"]:last'), 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;

View File

@ -371,8 +371,7 @@ tsp = ts.pager = {
}, },
calcFilters: function(table, c) { calcFilters: function(table, c) {
var tbodyIndex, var wo = c.widgetOptions,
wo = c.widgetOptions,
p = c.pager, p = c.pager,
hasFilters = c.$table.hasClass('hasFilters'); hasFilters = c.$table.hasClass('hasFilters');
if (hasFilters && !wo.pager_ajaxUrl) { if (hasFilters && !wo.pager_ajaxUrl) {
@ -380,10 +379,8 @@ tsp = ts.pager = {
// delayInit: true so nothing is in the cache // delayInit: true so nothing is in the cache
p.filteredRows = p.totalRows = c.$tbodies.eq(0).children('tr').not( wo.pager_countChildRows ? '' : '.' + c.cssChildRow ).length; p.filteredRows = p.totalRows = c.$tbodies.eq(0).children('tr').not( wo.pager_countChildRows ? '' : '.' + c.cssChildRow ).length;
} else { } else {
// just in case the pager tbody isn't the first tbody
tbodyIndex = c.$table.children('tbody').index( c.$tbodies.eq(0) );
p.filteredRows = 0; p.filteredRows = 0;
$.each(c.cache[tbodyIndex].normalized, function(i, el) { $.each(c.cache[0].normalized, function(i, el) {
p.filteredRows += p.regexRows.test(el[c.columns].$row[0].className) ? 0 : 1; p.filteredRows += p.regexRows.test(el[c.columns].$row[0].className) ? 0 : 1;
}); });
} }
@ -898,8 +895,7 @@ tsp = ts.pager = {
if ( !$.isEmptyObject(table.config.cache) ) { if ( !$.isEmptyObject(table.config.cache) ) {
var i, var i,
rows = [], rows = [],
tbodyIndex = c.$table.children('tbody').index( c.$tbodies.eq(0) ), n = table.config.cache[0].normalized;
n = table.config.cache[tbodyIndex].normalized;
p.totalRows = n.length; p.totalRows = n.length;
for (i = 0; i < p.totalRows; i++) { for (i = 0; i < p.totalRows; i++) {
rows.push(n[i][c.columns].$row); rows.push(n[i][c.columns].$row);

View File

@ -31,7 +31,7 @@ var tester = {
var i, j = 0, k, l, var i, j = 0, k, l,
c = table.config, c = table.config,
result = [], result = [],
b = table.tBodies, b = c.$tbodies,
l2 = c.columns; l2 = c.columns;
for (k = 0; k < b.length; k++){ for (k = 0; k < b.length; k++){
l = b[k].rows.length; l = b[k].rows.length;
@ -423,7 +423,8 @@ $(function(){
expect(4); expect(4);
$table1.trigger('sorton', [[[ 0,0 ]]]); $table1.trigger('sorton', [[[ 0,0 ]]]);
tester.cacheCompare( table1, 0, [ 'test1', 'test2', 'test3', '', 'testa', 'testb', 'testc' ], 'from data-attribute' ); tester.cacheCompare( table1, 0, [ 'test1', 'test2', 'test3',
'testa', 'testb', 'testc' ], 'from data-attribute' );
$table3.trigger('sorton', [[[ 0,1 ]]]); $table3.trigger('sorton', [[[ 0,1 ]]]);
tester.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'ignore data-attribute' ); tester.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'ignore data-attribute' );
@ -442,13 +443,16 @@ $(function(){
$table1.trigger('sortReset'); $table1.trigger('sortReset');
// lower case because table was parsed before c1.ignoreCase was changed // lower case because table was parsed before c1.ignoreCase was changed
tester.cacheCompare( table1, 'all', [ 'test2', 'x2', 'test1', 'x3', 'test3', 'x1', '', '', 'testb', 'x5', 'testc', 'x4', 'testa', 'x6' ], 'unsorted' ); tester.cacheCompare( table1, 'all', [ 'test2', 'x2', 'test1', 'x3', 'test3', 'x1',
'testb', 'x5', 'testc', 'x4', 'testa', 'x6' ], 'unsorted' );
$table1.trigger('sorton', [[[ 0,0 ]]]); $table1.trigger('sorton', [[[ 0,0 ]]]);
tester.cacheCompare( table1, 'all', [ 'test1', 'x3', 'test2', 'x2', 'test3', 'x1', '', '', 'testa', 'x6', 'testb', 'x5', 'testc', 'x4' ], 'ascending sort' ); tester.cacheCompare( table1, 'all', [ 'test1', 'x3', 'test2', 'x2', 'test3', 'x1',
'testa', 'x6', 'testb', 'x5', 'testc', 'x4' ], 'ascending sort' );
$table1.trigger('sorton', [[[ 0,1 ]]]); $table1.trigger('sorton', [[[ 0,1 ]]]);
tester.cacheCompare( table1, 'all', [ 'test3', 'x1', 'test2', 'x2', 'test1', 'x3', '', '', 'testc', 'x4', 'testb', 'x5', 'testa', 'x6' ], 'descending sort' ); tester.cacheCompare( table1, 'all', [ 'test3', 'x1', 'test2', 'x2', 'test1', 'x3',
'testc', 'x4', 'testb', 'x5', 'testa', 'x6' ], 'descending sort' );
// empty cell position // empty cell position
$table3.trigger('sorton', [[[ 0,0 ]]]); $table3.trigger('sorton', [[[ 0,0 ]]]);
@ -569,36 +573,40 @@ $(function(){
hl = c1.headerList[1] === nw, hl = c1.headerList[1] === nw,
p1 = c1.parsers[1].id === 'digit'; p1 = c1.parsers[1].id === 'digit';
equal(hc && hd && hl && p1, true, 'testing header cache: updateAll - thead'); equal(hc && hd && hl && p1, true, 'testing header cache: updateAll - thead');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateAll - tbody' ); tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testc', 4, 'testb', 5, 'testa', 6 ], 'updateAll - tbody' );
}]); }]);
// addRows // addRows
t = $('<tr class="temp"><td>testd</td><td>7</td></tr>'); t = $('<tr class="temp"><td>testd</td><td>7</td></tr>');
$table1.find('tbody:last').prepend(t); $table1.find('tbody:last').prepend(t);
oldColMax = c1.cache[2].colMax[1]; oldColMax = c1.cache[1].colMax[1];
$table1.trigger('addRows', [t, true, function(){ $table1.trigger('addRows', [t, true, function(){
updateCallback++; updateCallback++;
equal( oldColMax === 6 && c1.cache[2].colMax[1] === 7, true, 'addRows includes updating colMax value'); equal( oldColMax === 6 && c1.cache[1].colMax[1] === 7, true, 'addRows includes updating colMax value');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testd', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'addRows method' ); tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testd', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'addRows method' );
}]); }]);
// updateCell // updateCell
t = $table1.find('td:contains("7")'); t = $table1.find('td:contains("7")');
t.html('-8'); t.html('-8');
oldColMax = c1.cache[2].colMax[1]; oldColMax = c1.cache[1].colMax[1];
$table1.trigger('updateCell', [t[0], true, function(){ $table1.trigger('updateCell', [t[0], true, function(){
updateCallback++; updateCallback++;
equal( oldColMax === 7 && c1.cache[2].colMax[1] === 8, true, 'updateCell includes updating colMax value'); equal( oldColMax === 7 && c1.cache[1].colMax[1] === 8, true, 'updateCell includes updating colMax value');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testd', -8, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' ); tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testd', -8, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' );
}]); }]);
// update // update
$table1.find('tr.temp').remove(); $table1.find('tr.temp').remove();
oldColMax = c1.cache[2].colMax[1]; oldColMax = c1.cache[1].colMax[1];
$table1.trigger('update', [true, function(){ $table1.trigger('update', [true, function(){
updateCallback++; updateCallback++;
equal( oldColMax === 8 && c1.cache[2].colMax[1] === 6, true, 'update includes updating colMax value'); equal( oldColMax === 8 && c1.cache[1].colMax[1] === 6, true, 'update includes updating colMax value');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, '', '', 'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' ); tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' );
}]); }]);
$table5 $table5