Earlier filtering was done based on the original value of the cell, but formatters could change the display value
108 lines
2.9 KiB
JavaScript
108 lines
2.9 KiB
JavaScript
import { isNumber, stripHTML } from './utils';
|
|
|
|
export default function filterRows(rows, filters) {
|
|
let filteredRowIndices = [];
|
|
|
|
for (let colIndex in filters) {
|
|
const keyword = filters[colIndex];
|
|
|
|
const filteredRows = filteredRowIndices.length ?
|
|
filteredRowIndices.map(i => rows[i]) :
|
|
rows;
|
|
|
|
const cells = filteredRows.map(row => row[colIndex]);
|
|
|
|
let filter = guessFilter(keyword);
|
|
let filterMethod = getFilterMethod(filter);
|
|
|
|
if (filterMethod) {
|
|
filteredRowIndices = filterMethod(filter.text, cells);
|
|
} else {
|
|
filteredRowIndices = cells.map(cell => cell.rowIndex);
|
|
}
|
|
}
|
|
|
|
return filteredRowIndices;
|
|
};
|
|
|
|
function getFilterMethod(filter) {
|
|
let filterMethodMap = {
|
|
contains(keyword, cells) {
|
|
return cells
|
|
.filter(cell => {
|
|
const hay = String(stripHTML(cell.html) || '').toLowerCase();
|
|
const needle = (keyword || '').toLowerCase();
|
|
return !needle || hay.includes(needle);
|
|
})
|
|
.map(cell => cell.rowIndex);
|
|
},
|
|
|
|
greaterThan(keyword, cells) {
|
|
return cells
|
|
.filter(cell => {
|
|
const value = Number(stripHTML(cell.html));
|
|
return value > keyword;
|
|
})
|
|
.map(cell => cell.rowIndex);
|
|
},
|
|
|
|
lessThan(keyword, cells) {
|
|
return cells
|
|
.filter(cell => {
|
|
const value = Number(stripHTML(cell.html));
|
|
return value < keyword;
|
|
})
|
|
.map(cell => cell.rowIndex);
|
|
},
|
|
|
|
range(rangeValues, cells) {
|
|
return cells
|
|
.filter(cell => {
|
|
const value = Number(stripHTML(cell.html));
|
|
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()
|
|
};
|
|
}
|