feat(filter): Filter now supports complex queries for Number columns
More advanced filter support for Number columns For e.g >5000 filters rows with the cell value greater than 5000 <30 filters rows with cell value less than 30 20:340 filters rows with cell value in the range of 20 and 340 You can also provide a custom filter function by providing a `filterRows` function in the options during initialization.
This commit is contained in:
parent
ae6415c950
commit
cdb276abfd
@ -99,6 +99,11 @@
|
||||
data,
|
||||
inlineFilters: true,
|
||||
dynamicRowHeight: true,
|
||||
// filterRows(keyword, cells, colIndex) {
|
||||
// return cells
|
||||
// .filter(cell => cell.content.includes(keyword))
|
||||
// .map(cell => cell.rowIndex);
|
||||
// },
|
||||
getEditor(colIndex, rowIndex, value, parent) {
|
||||
// editing obj only for date field
|
||||
if (colIndex != 6) return;
|
||||
|
||||
@ -13,6 +13,7 @@ export default class CellManager {
|
||||
'wrapper',
|
||||
'options',
|
||||
'style',
|
||||
'header',
|
||||
'bodyScrollable',
|
||||
'columnmanager',
|
||||
'rowmanager',
|
||||
@ -121,6 +122,10 @@ export default class CellManager {
|
||||
this.activateFilter(colIndex);
|
||||
return true;
|
||||
});
|
||||
|
||||
$.on(this.header, 'focusin', '.dt-filter', () => {
|
||||
this.unfocusCell(this.$focusedCell);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,6 +251,19 @@ export default class CellManager {
|
||||
this.highlightRowColumnHeader($cell);
|
||||
}
|
||||
|
||||
unfocusCell($cell) {
|
||||
if (!$cell) return;
|
||||
|
||||
// remove cell border
|
||||
$cell.classList.remove('dt-cell--focus');
|
||||
this.$focusedCell = null;
|
||||
|
||||
// reset header background
|
||||
if (this.lastHeaders) {
|
||||
this.lastHeaders.forEach(header => header.classList.remove('dt-cell--highlight'));
|
||||
}
|
||||
}
|
||||
|
||||
highlightRowColumnHeader($cell) {
|
||||
const {
|
||||
colIndex,
|
||||
|
||||
@ -269,24 +269,26 @@ export default class ColumnManager {
|
||||
bindFilter() {
|
||||
if (!this.options.inlineFilters) return;
|
||||
const handler = e => {
|
||||
const $filterCell = $.closest('.dt-cell', e.target);
|
||||
const {
|
||||
colIndex
|
||||
} = $.data($filterCell);
|
||||
this.$filterCell = $.closest('.dt-cell', e.target);
|
||||
const { colIndex } = $.data(this.$filterCell);
|
||||
const keyword = e.target.value;
|
||||
|
||||
this.datamanager.filterRows(keyword, colIndex)
|
||||
.then(({
|
||||
rowsToHide,
|
||||
rowsToShow
|
||||
}) => {
|
||||
this.rowmanager.hideRows(rowsToHide);
|
||||
this.rowmanager.showRows(rowsToShow);
|
||||
});
|
||||
this.applyFilter(keyword, colIndex);
|
||||
};
|
||||
$.on(this.header, 'keydown', '.dt-filter', debounce(handler, 300));
|
||||
}
|
||||
|
||||
applyFilter(keyword, colIndex) {
|
||||
this.datamanager.filterRows(keyword, colIndex)
|
||||
.then(({
|
||||
rowsToHide,
|
||||
rowsToShow
|
||||
}) => {
|
||||
this.rowmanager.hideRows(rowsToHide);
|
||||
this.rowmanager.showRows(rowsToShow);
|
||||
});
|
||||
}
|
||||
|
||||
applyDefaultSortOrder() {
|
||||
// sort rows if any 1 column has a default sortOrder set
|
||||
const columnsToSort = this.getColumns().filter(col => col.sortOrder !== 'none');
|
||||
|
||||
@ -11,7 +11,6 @@ export default class DataManager {
|
||||
this.sortRows = nextTick(this.sortRows, this);
|
||||
this.switchColumn = nextTick(this.switchColumn, this);
|
||||
this.removeColumn = nextTick(this.removeColumn, this);
|
||||
this.filterRows = nextTick(this.filterRows, this);
|
||||
}
|
||||
|
||||
init(data, columns) {
|
||||
@ -423,31 +422,36 @@ export default class DataManager {
|
||||
}
|
||||
|
||||
filterRows(keyword, colIndex) {
|
||||
let rowsToHide = [];
|
||||
let rowsToShow = [];
|
||||
const cells = this.rows.map(row => row[colIndex]);
|
||||
let result = this.options.filterRows(keyword, cells, colIndex);
|
||||
|
||||
cells.forEach(cell => {
|
||||
const hay = String(cell.content || '').toLowerCase();
|
||||
const needle = (keyword || '').toLowerCase();
|
||||
if (!result) {
|
||||
result = this.getAllRowIndices();
|
||||
}
|
||||
|
||||
if (!needle || hay.includes(needle)) {
|
||||
rowsToShow.push(cell.rowIndex);
|
||||
} else {
|
||||
rowsToHide.push(cell.rowIndex);
|
||||
}
|
||||
if (!result.then) {
|
||||
result = Promise.resolve(result);
|
||||
}
|
||||
|
||||
return result.then(rowsToShow => {
|
||||
this._filteredRows = rowsToShow;
|
||||
|
||||
const rowsToHide = this.getAllRowIndices()
|
||||
.filter(index => !rowsToShow.includes(index));
|
||||
|
||||
return {
|
||||
rowsToHide,
|
||||
rowsToShow
|
||||
};
|
||||
});
|
||||
|
||||
this._filteredRows = rowsToShow;
|
||||
|
||||
return {
|
||||
rowsToHide,
|
||||
rowsToShow
|
||||
};
|
||||
}
|
||||
|
||||
getFilteredRowIndices() {
|
||||
return this._filteredRows || this.rows.map(row => row.meta.rowIndex);
|
||||
return this._filteredRows || this.getAllRowIndices();
|
||||
}
|
||||
|
||||
getAllRowIndices() {
|
||||
return this.rows.map(row => row.meta.rowIndex);
|
||||
}
|
||||
|
||||
getRowCount() {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import filterRows from './filterRows';
|
||||
|
||||
export default {
|
||||
columns: [],
|
||||
data: [],
|
||||
@ -40,6 +42,7 @@ export default {
|
||||
desc: '↓',
|
||||
none: ''
|
||||
},
|
||||
filterRows: filterRows,
|
||||
freezeMessage: '',
|
||||
getEditor: null,
|
||||
serialNoColumn: true,
|
||||
|
||||
93
src/filterRows.js
Normal file
93
src/filterRows.js
Normal file
@ -0,0 +1,93 @@
|
||||
import { isNumber } from './utils';
|
||||
|
||||
export default function filterRows(keyword, cells, colIndex) {
|
||||
let filter = guessFilter(keyword);
|
||||
let filterMethod = getFilterMethod(filter);
|
||||
|
||||
if (filterMethod) {
|
||||
return filterMethod(filter.text, cells);
|
||||
}
|
||||
|
||||
return cells.map(cell => cell.rowIndex);
|
||||
};
|
||||
|
||||
function getFilterMethod(filter) {
|
||||
let filterMethodMap = {
|
||||
contains(keyword, cells) {
|
||||
return cells
|
||||
.filter(cell => {
|
||||
const hay = String(cell.content || '').toLowerCase();
|
||||
const needle = (keyword || '').toLowerCase();
|
||||
return !needle || hay.includes(needle);
|
||||
})
|
||||
.map(cell => cell.rowIndex);
|
||||
},
|
||||
|
||||
greaterThan(keyword, cells) {
|
||||
return cells
|
||||
.filter(cell => {
|
||||
const value = Number(cell.content);
|
||||
return value > keyword;
|
||||
})
|
||||
.map(cell => cell.rowIndex);
|
||||
},
|
||||
|
||||
lessThan(keyword, cells) {
|
||||
return cells
|
||||
.filter(cell => {
|
||||
const value = Number(cell.content);
|
||||
return value < keyword;
|
||||
})
|
||||
.map(cell => cell.rowIndex);
|
||||
},
|
||||
|
||||
range(rangeValues, cells) {
|
||||
return cells
|
||||
.filter(cell => {
|
||||
const value = Number(cell.content);
|
||||
return value >= rangeValues[0] && value <= rangeValues[1];
|
||||
})
|
||||
.map(cell => cell.rowIndex);
|
||||
}
|
||||
};
|
||||
|
||||
return filterMethodMap[filter.type];
|
||||
}
|
||||
|
||||
function guessFilter(keyword) {
|
||||
if (keyword.length === 1) return {};
|
||||
|
||||
if (keyword.startsWith('>')) {
|
||||
if (isNumber(keyword.slice(1))) {
|
||||
return {
|
||||
type: 'greaterThan',
|
||||
text: Number(keyword.slice(1).trim())
|
||||
};
|
||||
}
|
||||
|
||||
keyword = keyword.slice(1);
|
||||
}
|
||||
|
||||
if (keyword.startsWith('<')) {
|
||||
if (isNumber(keyword.slice(1))) {
|
||||
return {
|
||||
type: 'lessThan',
|
||||
text: Number(keyword.slice(1).trim())
|
||||
};
|
||||
}
|
||||
|
||||
keyword = keyword.slice(1);
|
||||
}
|
||||
|
||||
if (keyword.split(':').length === 2 && keyword.split(':').every(isNumber)) {
|
||||
return {
|
||||
type: 'range',
|
||||
text: keyword.split(':').map(v => v.trim()).map(Number)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'contains',
|
||||
text: keyword.toLowerCase()
|
||||
};
|
||||
}
|
||||
@ -277,7 +277,7 @@ export default class RowManager {
|
||||
|
||||
getFilterInput(props) {
|
||||
const dataAttr = makeDataAttributeString(props);
|
||||
return `<input class="dt-filter dt-input" type="text" ${dataAttr} />`;
|
||||
return `<input class="dt-filter dt-input" type="text" ${dataAttr} tabindex="1" />`;
|
||||
}
|
||||
|
||||
selector(rowIndex) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user