mirror of
https://github.com/DataTables/DataTables.git
synced 2025-03-15 16:29:16 +01:00
Internal: Change the application of global filtering methodology
- Reducing the complexity of how the global filter is applied in DataTables by removing the `asDataSearch` internal settings array which held information about each row's filtering data. This is now held on a per row basis in `_sFilterRow` which is built only when the data is invalidated. This should result in a small performance improvement as well as simplifying and reducing the code. - Filtering is now implemented by simply checking the built regex against the `_sFilterRow` parameter for the display array (with a reset to master, as there was before, if needed) - This also fixes an indexing issue that was present in the filtering in 1.10.dev only
This commit is contained in:
parent
1a880b9f46
commit
bda2d25b5f
@ -54,7 +54,6 @@ this.oApi = {
|
|||||||
"_fnFilterCustom": _fnFilterCustom,
|
"_fnFilterCustom": _fnFilterCustom,
|
||||||
"_fnFilterColumn": _fnFilterColumn,
|
"_fnFilterColumn": _fnFilterColumn,
|
||||||
"_fnFilter": _fnFilter,
|
"_fnFilter": _fnFilter,
|
||||||
"_fnBuildSearchArray": _fnBuildSearchArray,
|
|
||||||
"_fnFilterCreateSearch": _fnFilterCreateSearch,
|
"_fnFilterCreateSearch": _fnFilterCreateSearch,
|
||||||
"_fnSort": _fnSort,
|
"_fnSort": _fnSort,
|
||||||
"_fnSortAttachListener": _fnSortAttachListener,
|
"_fnSortAttachListener": _fnSortAttachListener,
|
||||||
|
@ -123,8 +123,6 @@ function _fnFilterComplete ( oSettings, oInput, iForce )
|
|||||||
/* Tell the draw function we have been filtering */
|
/* Tell the draw function we have been filtering */
|
||||||
oSettings.bFiltered = true;
|
oSettings.bFiltered = true;
|
||||||
$(oSettings.oInstance).trigger('filter', oSettings);
|
$(oSettings.oInstance).trigger('filter', oSettings);
|
||||||
|
|
||||||
_fnBuildSearchArray( oSettings, 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -193,123 +191,52 @@ function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsens
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter the data table based on user input and draw the table
|
* Filter the data table based on user input and draw the table
|
||||||
* @param {object} oSettings dataTables settings object
|
* @param {object} settings dataTables settings object
|
||||||
* @param {string} sInput string to filter on
|
* @param {string} input string to filter on
|
||||||
* @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)
|
* @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
|
||||||
* @param {bool} bRegex treat as a regular expression or not
|
* @param {bool} regex treat as a regular expression or not
|
||||||
* @param {bool} bSmart perform smart filtering or not
|
* @param {bool} smart perform smart filtering or not
|
||||||
* @param {bool} bCaseInsensitive Do case insenstive matching or not
|
* @param {bool} caseInsensitive Do case insenstive matching or not
|
||||||
* @memberof DataTable#oApi
|
* @memberof DataTable#oApi
|
||||||
*/
|
*/
|
||||||
function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive )
|
function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
|
||||||
{
|
{
|
||||||
var i;
|
var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
|
||||||
var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
|
var prevSearch = settings.oPreviousSearch.sSearch;
|
||||||
var oPrevSearch = oSettings.oPreviousSearch;
|
var displayMaster = settings.aiDisplayMaster;
|
||||||
|
var display, invalidated, i;
|
||||||
|
|
||||||
/* Check if we are forcing or not - optional parameter */
|
// Need to take account of custom filtering functions - always filter
|
||||||
if ( !iForce )
|
if ( DataTable.ext.afnFiltering.length !== 0 ) {
|
||||||
|
force = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the input is blank - we just want the full data set
|
||||||
|
if ( input.length <= 0 ) {
|
||||||
|
settings.aiDisplay = displayMaster.slice();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Check if any of the rows were invalidated
|
||||||
|
invalidated = _fnFilterData( settings );
|
||||||
|
|
||||||
|
// New search - start from the master array
|
||||||
|
if ( invalidated ||
|
||||||
|
force ||
|
||||||
|
prevSearch.length > input.length ||
|
||||||
|
input.indexOf(prevSearch) !== 0 )
|
||||||
{
|
{
|
||||||
iForce = 0;
|
settings.aiDisplay = displayMaster.slice();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need to take account of custom filtering functions - always filter */
|
// Search the display array
|
||||||
if ( DataTable.ext.afnFiltering.length !== 0 )
|
display = settings.aiDisplay;
|
||||||
{
|
|
||||||
iForce = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
for ( i=display.length-1 ; i>=0 ; i-- ) {
|
||||||
* If the input is blank - we want the full data set
|
if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
|
||||||
*/
|
display.splice( i, 1 );
|
||||||
if ( sInput.length <= 0 )
|
|
||||||
{
|
|
||||||
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if any of the rows were invalidated - if so, we need to do a
|
|
||||||
// full re-filter
|
|
||||||
var invalidated = _fnBuildSearchArray( oSettings, 1 );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We are starting a new search or the new search string is smaller
|
|
||||||
* then the old one (i.e. delete). Search from the master array
|
|
||||||
*/
|
|
||||||
if ( invalidated || iForce == 1 ||
|
|
||||||
oPrevSearch.sSearch.length > sInput.length ||
|
|
||||||
sInput.indexOf(oPrevSearch.sSearch) !== 0 )
|
|
||||||
{
|
|
||||||
/* Nuke the old display array - we are going to rebuild it */
|
|
||||||
oSettings.aiDisplay.length = 0;
|
|
||||||
|
|
||||||
/* Force a rebuild of the search array */
|
|
||||||
_fnBuildSearchArray( oSettings, 1 );
|
|
||||||
|
|
||||||
/* Search through all records to populate the search array
|
|
||||||
* The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
|
|
||||||
* mapping
|
|
||||||
*/
|
|
||||||
for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )
|
|
||||||
{
|
|
||||||
if ( rpSearch.test(oSettings.asDataSearch[i]) )
|
|
||||||
{
|
|
||||||
oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Using old search array - refine it - do it this way for speed
|
|
||||||
* Don't have to search the whole master array again
|
|
||||||
*/
|
|
||||||
var iIndexCorrector = 0;
|
|
||||||
|
|
||||||
/* Search the current results */
|
|
||||||
for ( i=0 ; i<oSettings.asDataSearch.length ; i++ )
|
|
||||||
{
|
|
||||||
if ( ! rpSearch.test(oSettings.asDataSearch[i]) )
|
|
||||||
{
|
|
||||||
oSettings.aiDisplay.splice( i-iIndexCorrector, 1 );
|
|
||||||
iIndexCorrector++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an array which can be quickly search through
|
|
||||||
* @param {object} oSettings dataTables settings object
|
|
||||||
* @param {int} iMaster use the master data array - optional
|
|
||||||
* @memberof DataTable#oApi
|
|
||||||
*/
|
|
||||||
function _fnBuildSearchArray ( settings, master )
|
|
||||||
{
|
|
||||||
var searchData = [];
|
|
||||||
var i, ien, rows;
|
|
||||||
var wasInvalidated = false;
|
|
||||||
|
|
||||||
if ( !settings.oFeatures.bServerSide ) {
|
|
||||||
// Resolve any invalidated rows
|
|
||||||
wasInvalidated = _fnFilterData( settings );
|
|
||||||
|
|
||||||
if ( wasInvalidated ) {
|
|
||||||
// Build the search array from the display arrays
|
|
||||||
rows = master===1 ?
|
|
||||||
settings.aiDisplayMaster :
|
|
||||||
settings.aiDisplay;
|
|
||||||
|
|
||||||
for ( i=0, ien=rows.length ; i<ien ; i++ ) {
|
|
||||||
searchData.push( settings.aoData[ rows[i] ]._aFilterData.join(' ') );
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.asDataSearch = searchData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wasInvalidated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -397,7 +324,8 @@ function _fnFilterData ( settings )
|
|||||||
filterData.push( cellData );
|
filterData.push( cellData );
|
||||||
}
|
}
|
||||||
|
|
||||||
row._aFilterData = filterData;
|
row._aFilterCells = filterData;
|
||||||
|
row._sFilterRow = filterData.join(' ');
|
||||||
wasInvalidated = true;
|
wasInvalidated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,24 @@ DataTable.models.oRow = {
|
|||||||
"_aSortData": null,
|
"_aSortData": null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filtering data cache. As per the sort data cache, used to increase the
|
* Per cell filtering data cache. As per the sort data cache, used to
|
||||||
* performance of the filtering in DataTables
|
* increase the performance of the filtering in DataTables
|
||||||
* @type array
|
* @type array
|
||||||
* @default null
|
* @default null
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
"_aFilterData": null,
|
"_aFilterCells": null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filtering data cache. This is the same as the cell filtering cache, but
|
||||||
|
* in this case a string rather than an array. This is easily computed with
|
||||||
|
* a join on `_aFilterCells`, but is provided as a cache so the join isn't
|
||||||
|
* needed on every search (memory traded for performance)
|
||||||
|
* @type array
|
||||||
|
* @default null
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
"_sFilterRow": null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache of the class name that DataTables has applied to the row, so we
|
* Cache of the class name that DataTables has applied to the row, so we
|
||||||
|
@ -322,13 +322,6 @@ DataTable.models.oSettings = {
|
|||||||
*/
|
*/
|
||||||
"aoFooter": [],
|
"aoFooter": [],
|
||||||
|
|
||||||
/**
|
|
||||||
* Search data array for regular expression searching
|
|
||||||
* @type array
|
|
||||||
* @default []
|
|
||||||
*/
|
|
||||||
"asDataSearch": [],
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the applied global search information in case we want to force a
|
* Store the applied global search information in case we want to force a
|
||||||
* research or compare the old search to a new one.
|
* research or compare the old search to a new one.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user