private getFilteredData()

in packages/tablesorter/src/providers/JSONDataProvider.ts [176:277]


    private getFilteredData(options: IQueryOptions) {
        let final = this.data.slice(0);

        // If we are handling filtering, and their is a filter being applied
        if (this.handleFilter && options.query && options.query.length) {
            options.query.forEach((filter) => {
                let filterMethod = JSONDataProvider.checkStringFilter as any;

                // There HAS to be some value and a column for us to be able to filter correctly
                if (filter.value && filter.column) {
                    const explictValues = filter.value && (<IExplicitFilter>filter.value).values;
                    const filteredDomain = filter.value && (<INumericalFilter>filter.value).domain;
                    if (explictValues) {
                        filterMethod = JSONDataProvider.checkExplicitFilter as any;

                    // A numerical filter
                    } else if (filteredDomain) {
                        const actualDomain = this.domains[filter.column];

                        // If the filtered domain is ACTUALLY different from the full domain, then filter
                        // This case is specifically for null values, if the dataset contains null values
                        // and we apply a filter with the same domain as the actual domain, then null values get filtered
                        // out since they don't actually fall within the domain
                        if (filteredDomain[0] !== actualDomain[0] || filteredDomain[1] !== actualDomain[1]) {
                            filterMethod = JSONDataProvider.checkNumberFilter as any;
                        } else {

                            // Otherwise, we don't need a filter
                            filterMethod = undefined;
                        }
                    }
                    final = final.filter((item) => !filterMethod || filterMethod(item, filter));
                }
            });
        }

        // If we are handling sort, and there is a sort applied to tablesorter
        if (this.handleSort && options.sort && options.sort.length) {
            const sortItem = options.sort[0];
            const basicSort = (aValue: any, bValue: any, asc: boolean) => {
                const dir = asc ? 1 : -1;
                /* tslint:disable */
                if (aValue == bValue) {
                /* tslint:enable */
                    return 0;
                }
                return (aValue > bValue ? 1 : -1) * dir;
            };

            const calcStackedValue = (
                item: any,
                sortToCheck: ITableSorterSort,
                minMax: { [col: string]: { min: number, max: number }}) => {
                const columns = sortToCheck.stack.columns;
                if (columns) {
                    const sortVal = columns.reduce((a, v) => {
                        /**
                         * This calculates the percent that this guy is of the max value
                         */
                        const min = minMax[v.column].min || 0;
                        const max = minMax[v.column].max || min;
                        let value = item[v.column];

                        // We only need to do the actual weighting with items that have values
                        if (value !== null && value !== undefined) { //tslint:disable-line
                            // The max is the min, in this case, the value should be 100% (or 1)
                            if (max === min) {
                                value = 1;
                            } else {
                                value = ((value - min) / (max - min));
                            }
                            return a + (value * v.weight);
                        }
                        // Null/undefined values have no value, so just ignore them
                        return a;
                    }, 0);
                    return sortVal;
                }
                return 0;
            };

            let maxValues: { [col: string]: { min: number, max: number }};
            if (sortItem.stack) {
                 maxValues = sortItem.stack.columns.reduce((a, b) => {
                    const [min, max] = this.domains[b.column];
                    a[b.column] = {
                        max,
                        min,
                    };
                    return a;
                }, <any>{});
            }

            final.sort((a, b) => {
                if (sortItem.stack) {
                    return basicSort(calcStackedValue(a, sortItem, maxValues), calcStackedValue(b, sortItem, maxValues), sortItem.asc);
                }
                return basicSort(a[sortItem.column], b[sortItem.column], sortItem.asc);
            });
        }
        return final;
    }