Math: Limit tbody cell processing & use cellIndex whenever possible. See #1048

This commit is contained in:
Rob Garrison 2015-12-04 00:48:41 -06:00
parent a9ec53ee19
commit 1bb9a5d1b2
3 changed files with 57 additions and 13 deletions

File diff suppressed because one or more lines are too long

View File

@ -179,7 +179,12 @@
<h3><a href="#">Notes</a></h3> <h3><a href="#">Notes</a></h3>
<div> <div>
<ul> <ul>
<li>In <span class="version">v2.24.7</span>, <code>math_rowFilter</code> can now be overridden by the row's <code>data-math-filter</code> attribute.</li> <li>In <span class="version">v2.24.7</span>
<ul>
<li><code>math_rowFilter</code> can now be overridden by the row's <code>data-math-filter</code> attribute.</li>
<li>On initialization, only tbody cells with a <code>rowspan</code> or <code>colspan</code> are now processed and only get a "data-column" set if the internal <code>cellIndex</code> doesn't match the calculated cell index. This should improve performance and reduce lag after initialization and updating the table (see <a href="https://github.com/Mottie/tablesorter/issues/1048">issue #1048</a>.</li>
</ul>
</li>
<li>In <span class="version">v2.24.6</span>, added <code>math_rowFilter</code> option.</li> <li>In <span class="version">v2.24.6</span>, added <code>math_rowFilter</code> option.</li>
<li>In <span class="version">v2.24.0</span> <li>In <span class="version">v2.24.0</span>
<ul> <ul>
@ -213,7 +218,7 @@
<li>The widget will update the calculations based on filtered rows, and will update if any data within the table changes (using update events).</li> <li>The widget will update the calculations based on filtered rows, and will update if any data within the table changes (using update events).</li>
<li>This widget is not optimized for very large tables, for two reasons: <li>This widget is not optimized for very large tables, for two reasons:
<ul> <ul>
<li>On initialization, it cycles through every table row, calculates the column index, and adds a <code>data-column</code> attribute.</li> <li>On initialization, it cycles through every table row, calculates the column index<del>, and adds a <code>data-column</code> attribute</del> (Fixed in <span class="version updated">v2.24.7</span>).</li>
<li>It uses the update method whenever it recalculates values to make the results sortable. This occurs when any of the update methods are used and after the table is filtered.</li> <li>It uses the update method whenever it recalculates values to make the results sortable. This occurs when any of the update methods are used and after the table is filtered.</li>
</ul> </ul>
</li> </li>

View File

@ -52,7 +52,10 @@
if ( !isFiltered || hasFilter ) { if ( !isFiltered || hasFilter ) {
$cells = $row.children().not( '[' + wo.math_dataAttrib + '=ignore]' ); $cells = $row.children().not( '[' + wo.math_dataAttrib + '=ignore]' );
if ( wo.math_ignore.length ) { if ( wo.math_ignore.length ) {
$cells = $cells.not( '[data-column=' + wo.math_ignore.join( '],[data-column=' ) + ']' ); $cells = $cells.filter( function( indx ) {
// using $.inArray is not optimal (needed for IE8)
return $.inArray( math.getCellIndex( $( this ) ), wo.math_ignore ) === -1;
});
} }
arry = $cells.not( $el ).map( function() { arry = $cells.not( $el ).map( function() {
return math.processText( c, $( this ) ); return math.processText( c, $( this ) );
@ -70,7 +73,7 @@
mathAttr = wo.math_dataAttrib, mathAttr = wo.math_dataAttrib,
hasFilter = $row.attr( mathAttr + '-filter' ) || wo.math_rowFilter, hasFilter = $row.attr( mathAttr + '-filter' ) || wo.math_rowFilter,
filtered = wo.filter_filteredRow || 'filtered', filtered = wo.filter_filteredRow || 'filtered',
cIndex = parseInt( $el.attr( 'data-column' ), 10 ), cIndex = math.getCellIndex( $el ),
$rows = c.$table.children( 'tbody' ).children(); $rows = c.$table.children( 'tbody' ).children();
// make sure tfoot rows are AFTER the tbody rows // make sure tfoot rows are AFTER the tbody rows
// $rows.add( c.$table.children( 'tfoot' ).children() ); // $rows.add( c.$table.children( 'tfoot' ).children() );
@ -82,7 +85,9 @@
if ( hasFilter ) { if ( hasFilter ) {
$tr = $tr.filter( hasFilter ); $tr = $tr.filter( hasFilter );
} }
$t = $tr.children().filter( '[data-column=' + cIndex + ']' ); $t = $tr.children().filter( function( indx ) {
return math.getCellIndex( $( this ) ) === cIndex;
});
mathAbove = $t.filter( '[' + mathAttr + '^=above]' ).length; mathAbove = $t.filter( '[' + mathAttr + '^=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 ( ( ( !$tr.hasClass( filtered ) || hasFilter ) && if ( ( ( !$tr.hasClass( filtered ) || hasFilter ) &&
@ -106,7 +111,9 @@
if ( hasFilter ) { if ( hasFilter ) {
$tr = $tr.filter( hasFilter ); $tr = $tr.filter( hasFilter );
} }
$t = $tr.children().filter( '[data-column=' + cIndex + ']' ); $t = $tr.children().filter( function( indx ) {
return math.getCellIndex( $( this ) ) === cIndex;
});
if ( $t.filter( '[' + mathAttr + '^=below]' ).length ) { if ( $t.filter( '[' + mathAttr + '^=below]' ).length ) {
break; break;
} }
@ -125,7 +132,9 @@
if ( hasFilter ) { if ( hasFilter ) {
$tr = $tr.filter( hasFilter ); $tr = $tr.filter( hasFilter );
} }
$t = $tr.children().filter( '[data-column=' + cIndex + ']' ); $t = $tr.children().filter( function( indx ) {
return math.getCellIndex( $( this ) ) === cIndex;
});
if ( ( !$tr.hasClass( filtered ) || hasFilter ) && if ( ( !$tr.hasClass( filtered ) || hasFilter ) &&
$t.not( '[' + mathAttr + '^=above],[' + mathAttr + '^=below],[' + mathAttr + '^=col]' ).length && $t.not( '[' + mathAttr + '^=above],[' + mathAttr + '^=below],[' + mathAttr + '^=col]' ).length &&
!$t.is( $el ) ) { !$t.is( $el ) ) {
@ -157,7 +166,7 @@
// $row.children().each(function(){ // $row.children().each(function(){
for ( cellIndex = 0; cellIndex < cellLen; cellIndex++ ) { for ( cellIndex = 0; cellIndex < cellLen; cellIndex++ ) {
$t = $cells.eq( cellIndex ); $t = $cells.eq( cellIndex );
col = parseInt( $t.attr( 'data-column' ), 10); col = math.getCellIndex( $t );
if ( !$t.filter( '[' + mathAttr + ']' ).length && $.inArray( col, wo.math_ignore ) < 0 ) { if ( !$t.filter( '[' + mathAttr + ']' ).length && $.inArray( col, wo.math_ignore ) < 0 ) {
arry.push( math.processText( c, $t ) ); arry.push( math.processText( c, $t ) );
} }
@ -170,13 +179,42 @@
setColumnIndexes : function( c ) { setColumnIndexes : function( c ) {
c.$table.after( '<div id="_tablesorter_table_placeholder"></div>' ); c.$table.after( '<div id="_tablesorter_table_placeholder"></div>' );
// detach table from DOM to speed up column indexing // detach table from DOM to speed up column indexing
var $table = c.$table.detach(); var $table = c.$table.detach(),
ts.computeColumnIndex( $table.children( 'tbody' ).children() ); last = 1,
// only target rows with a colspan or rows included in a rowspan
$rows = $table.children( 'tbody' ).children().filter( function() {
var cells, indx, len,
$this = $( this ),
include = $this.children( '[colspan]' ).length > 0;
if ( last > 1 ) {
last--;
include = true;
} else if ( last < 1 ) {
last = 1;
}
if ( $this.children( '[rowspan]' ).length > 0 ) {
cells = this.cells;
// find max rowspan (in case more than one cell has a rowspan)
for ( indx = 0; indx < cells.length; indx++ ) {
last = Math.max( cells[ indx ].rowSpan, last );
}
}
return include;
});
// pass `c` (table.config) to computeColumnIndex so it won't add a data-column
// to every tbody cell, just the ones where the .cellIndex property doesn't match
// the calculated cell index - hopefully fixes the lag issue in #1048
ts.computeColumnIndex( $rows, c );
$( '#_tablesorter_table_placeholder' ) $( '#_tablesorter_table_placeholder' )
.after( $table ) .after( $table )
.remove(); .remove();
}, },
getCellIndex : function( $cell ) {
var indx = $cell.attr( 'data-column' );
return typeof indx === 'undefined' ? $cell[0].cellIndex : parseInt( indx, 10 );
},
recalculate : function(c, wo, init) { recalculate : function(c, wo, init) {
if ( c && ( !wo.math_isUpdating || init ) ) { if ( c && ( !wo.math_isUpdating || init ) ) {
@ -531,9 +569,10 @@
.on( math.events + ' ' + wo.math_event, function( e ) { .on( math.events + ' ' + wo.math_event, function( e ) {
var init = e.type === 'tablesorter-initialized'; var init = e.type === 'tablesorter-initialized';
if ( !wo.math_isUpdating || init ) { if ( !wo.math_isUpdating || init ) {
if ( !/filter/.test( e.type ) ) { // don't setColumnIndexes on init here, or it gets done twice
if ( !/filter/.test( e.type ) && !init ) {
// redo data-column indexes on update // redo data-column indexes on update
math.setColumnIndexes( c ) ; math.setColumnIndexes( c );
} }
math.recalculate( c, wo, init ); math.recalculate( c, wo, init );
} }