@visactor/vtable
Version:
canvas table width high performance
424 lines (395 loc) • 22.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.sortBy = exports.naturalSort = exports.typeSort = exports.indicatorSort = exports.MinAggregator = exports.MaxAggregator = exports.AvgAggregator = exports.CountAggregator = exports.SumAggregator = exports.RecalculateAggregator = exports.CustomAggregator = exports.NoneAggregator = exports.RecordAggregator = exports.Aggregator = exports.registeredAggregators = void 0;
const vutils_1 = require("@visactor/vutils"), __1 = require("..");
exports.registeredAggregators = {};
class Aggregator {
constructor(config) {
var _a;
this.isAggregator = !0, this.isRecord = !0, this.records = [], this.key = config.key,
this.field = config.field, this.formatFun = config.formatFun, this.isRecord = null !== (_a = config.isRecord) && void 0 !== _a ? _a : this.isRecord;
}
clearCacheValue() {
this._formatedValue = void 0;
}
formatValue(col, row, table) {
return this._formatedValue || (this.formatFun ? this._formatedValue = this.formatFun(this.value(), col, row, table) : this._formatedValue = this.value()),
this._formatedValue;
}
reset() {
this.records = [], this.clearCacheValue();
}
}
exports.Aggregator = Aggregator;
class RecordAggregator extends Aggregator {
constructor() {
super(...arguments), this.type = __1.AggregationType.RECORD, this.isRecord = !0;
}
push(record) {
record && this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
this.clearCacheValue();
}
deleteRecord(record) {
record && this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
this.clearCacheValue();
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
this.clearCacheValue());
}
value() {
return this.records;
}
reset() {
this.records = [];
}
recalculate() {}
}
exports.RecordAggregator = RecordAggregator;
class NoneAggregator extends Aggregator {
constructor() {
super(...arguments), this.type = __1.AggregationType.NONE, this.isRecord = !0;
}
push(record) {
record && (this.isRecord && (this.records = [ record ]), this.field && (this.fieldValue = record[this.field])),
this.clearCacheValue();
}
deleteRecord(record) {
record && (this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
this.field && this.records.length && (this.fieldValue = this.records[this.records.length - 1][this.field])),
this.clearCacheValue();
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
this.field && this.records.length && (this.fieldValue = this.records[this.records.length - 1][this.field]),
this.clearCacheValue());
}
value() {
return this.fieldValue;
}
reset() {
this.records = [], this.fieldValue = void 0;
}
recalculate() {}
}
exports.NoneAggregator = NoneAggregator;
class CustomAggregator extends Aggregator {
constructor(config) {
super(config), this.type = __1.AggregationType.CUSTOM, this.isRecord = !0, this.values = [],
this.aggregationFun = config.aggregationFun;
}
push(record) {
record && (this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
this.field && this.values.push(record[this.field])), this.clearCacheValue();
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
this.field && this.records.length && (this.values = this.records.map((item => item[this.field]))),
this.clearCacheValue());
}
deleteRecord(record) {
record && (this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
this.field && this.records.length && (this.values = this.records.map((item => item[this.field])))),
this.clearCacheValue();
}
value() {
var _a;
return this.fieldValue || (this.fieldValue = null === (_a = this.aggregationFun) || void 0 === _a ? void 0 : _a.call(this, this.values, this.records, this.field)),
this.fieldValue;
}
reset() {
this.records = [], this.fieldValue = void 0;
}
recalculate() {
this.fieldValue = void 0, this._formatedValue = void 0;
}
}
exports.CustomAggregator = CustomAggregator;
class RecalculateAggregator extends Aggregator {
constructor(config) {
super(config), this.type = __1.AggregationType.RECALCULATE, this.isRecord = !0,
this.calculateFun = config.calculateFun, this.dependAggregators = config.dependAggregators,
this.dependIndicatorKeys = config.dependIndicatorKeys;
}
push(record) {
record && this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
this.clearCacheValue();
}
deleteRecord(record) {
record && this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
this.clearCacheValue();
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
this.clearCacheValue());
}
value() {
var _a;
if (!this.fieldValue) {
const aggregatorValue = _getDependAggregatorValues(this.dependAggregators, this.dependIndicatorKeys);
this.fieldValue = null === (_a = this.calculateFun) || void 0 === _a ? void 0 : _a.call(this, aggregatorValue, this.records, this.field);
}
return this.fieldValue;
}
reset() {
this.records = [], this.fieldValue = void 0;
}
recalculate() {}
}
exports.RecalculateAggregator = RecalculateAggregator;
class SumAggregator extends Aggregator {
constructor(config) {
var _a;
super(config), this.type = __1.AggregationType.SUM, this.sum = 0, this.positiveSum = 0,
this.nagetiveSum = 0, this.needSplitPositiveAndNegativeForSum = !1, this.needSplitPositiveAndNegativeForSum = null !== (_a = config.needSplitPositiveAndNegative) && void 0 !== _a && _a;
}
push(record) {
if (record) if (this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
record.isAggregator) {
const value = record.value();
this.sum += null != value ? value : 0, this.needSplitPositiveAndNegativeForSum && (value > 0 ? this.positiveSum += value : value < 0 && (this.nagetiveSum += value));
} else if (this.field && !isNaN(parseFloat(record[this.field]))) {
const value = parseFloat(record[this.field]);
this.sum += value, this.needSplitPositiveAndNegativeForSum && (value > 0 ? this.positiveSum += value : value < 0 && (this.nagetiveSum += value));
}
this.clearCacheValue();
}
deleteRecord(record) {
if (record) if (this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
record.isAggregator) {
const value = record.value();
this.sum -= null != value ? value : 0, this.needSplitPositiveAndNegativeForSum && (value > 0 ? this.positiveSum -= value : value < 0 && (this.nagetiveSum -= value));
} else if (this.field && !isNaN(parseFloat(record[this.field]))) {
const value = parseFloat(record[this.field]);
this.sum -= value, this.needSplitPositiveAndNegativeForSum && (value > 0 ? this.positiveSum -= value : value < 0 && (this.nagetiveSum -= value));
}
this.clearCacheValue();
}
updateRecord(oldRecord, newRecord) {
if (oldRecord && newRecord) {
if (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
oldRecord.isAggregator) {
const oldValue = oldRecord.value(), newValue = newRecord.value();
this.sum += newValue - oldValue, this.needSplitPositiveAndNegativeForSum && (oldValue > 0 ? this.positiveSum -= oldValue : oldValue < 0 && (this.nagetiveSum -= oldValue),
newValue > 0 ? this.positiveSum += newValue : newValue < 0 && (this.nagetiveSum += newValue));
} else if (this.field && !isNaN(parseFloat(oldRecord[this.field]))) {
const oldValue = parseFloat(oldRecord[this.field]), newValue = parseFloat(newRecord[this.field]);
this.sum += newValue - oldValue, this.needSplitPositiveAndNegativeForSum && (oldValue > 0 ? this.positiveSum -= oldValue : oldValue < 0 && (this.nagetiveSum -= oldValue),
newValue > 0 ? this.positiveSum += newValue : newValue < 0 && (this.nagetiveSum += newValue));
}
this.clearCacheValue();
}
}
value() {
var _a;
return (null === (_a = this.records) || void 0 === _a ? void 0 : _a.length) >= 1 ? this.sum : void 0;
}
positiveValue() {
return this.positiveSum;
}
negativeValue() {
return this.nagetiveSum;
}
reset() {
super.reset(), this.records = [], this.sum = 0;
}
recalculate() {
if (this.sum = 0, this._formatedValue = void 0, this.records) for (let i = 0; i < this.records.length; i++) {
const record = this.records[i];
if (record.isAggregator) {
const value = record.value();
this.sum += null != value ? value : 0, this.needSplitPositiveAndNegativeForSum && (value > 0 ? this.positiveSum += value : value < 0 && (this.nagetiveSum += value));
} else if (this.field && !isNaN(parseFloat(record[this.field]))) {
const value = parseFloat(record[this.field]);
this.sum += value, this.needSplitPositiveAndNegativeForSum && (value > 0 ? this.positiveSum += value : value < 0 && (this.nagetiveSum += value));
}
}
}
}
exports.SumAggregator = SumAggregator;
class CountAggregator extends Aggregator {
constructor() {
super(...arguments), this.type = __1.AggregationType.COUNT, this.count = 0;
}
push(record) {
record && (this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
record.isAggregator ? this.count += record.value() : this.count++), this.clearCacheValue();
}
deleteRecord(record) {
record && (this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
record.isAggregator ? this.count -= record.value() : this.count--), this.clearCacheValue();
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
oldRecord.isAggregator && (this.count += newRecord.value() - oldRecord.value()));
}
value() {
return this.count;
}
reset() {
this.records = [], this.count = 0;
}
recalculate() {
if (this.count = 0, this._formatedValue = void 0, this.records) for (let i = 0; i < this.records.length; i++) {
const record = this.records[i];
record.isAggregator ? this.count += record.value() : this.count++;
}
}
}
exports.CountAggregator = CountAggregator;
class AvgAggregator extends Aggregator {
constructor() {
super(...arguments), this.type = __1.AggregationType.AVG, this.sum = 0, this.count = 0;
}
push(record) {
record && (this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
record.isAggregator && record.type === __1.AggregationType.AVG ? (this.sum += record.sum,
this.count += record.count) : this.field && !isNaN(parseFloat(record[this.field])) && (this.sum += parseFloat(record[this.field]),
this.count++)), this.clearCacheValue();
}
deleteRecord(record) {
record && (this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
record.isAggregator && record.type === __1.AggregationType.AVG ? (this.sum -= record.sum,
this.count -= record.count) : this.field && !isNaN(parseFloat(record[this.field])) && (this.sum -= parseFloat(record[this.field]),
this.count--)), this.clearCacheValue();
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
oldRecord.isAggregator && oldRecord.type === __1.AggregationType.AVG ? (this.sum += newRecord.sum - oldRecord.sum,
this.count += newRecord.count - oldRecord.count) : this.field && !isNaN(parseFloat(oldRecord[this.field])) && (this.sum += parseFloat(newRecord[this.field]) - parseFloat(oldRecord[this.field])),
this.clearCacheValue());
}
value() {
var _a;
return (null === (_a = this.records) || void 0 === _a ? void 0 : _a.length) >= 1 ? this.sum / this.count : void 0;
}
reset() {
this.records = [], this.sum = 0, this.count = 0;
}
recalculate() {
if (this.sum = 0, this.count = 0, this._formatedValue = void 0, this.records) for (let i = 0; i < this.records.length; i++) {
const record = this.records[i];
record.isAggregator && record.type === __1.AggregationType.AVG ? (this.sum += record.sum,
this.count += record.count) : this.field && !isNaN(parseFloat(record[this.field])) && (this.sum += parseFloat(record[this.field]),
this.count++);
}
}
}
exports.AvgAggregator = AvgAggregator;
class MaxAggregator extends Aggregator {
constructor() {
super(...arguments), this.type = __1.AggregationType.MAX, this.max = Number.MIN_SAFE_INTEGER;
}
push(record) {
record && (this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
record.isAggregator ? this.max = record.max > this.max ? record.max : this.max : "number" == typeof record ? this.max = record > this.max ? record : this.max : this.field && "number" == typeof record[this.field] ? this.max = record[this.field] > this.max ? record[this.field] : this.max : this.field && !isNaN(record[this.field]) && (this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max)),
this.clearCacheValue();
}
deleteRecord(record) {
record && (this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
this.recalculate());
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
this.recalculate());
}
value() {
var _a;
return (null === (_a = this.records) || void 0 === _a ? void 0 : _a.length) >= 1 ? this.max : void 0;
}
reset() {
this.records = [], this.max = Number.MIN_SAFE_INTEGER;
}
recalculate() {
if (this.max = Number.MIN_SAFE_INTEGER, this._formatedValue = void 0, this.records) for (let i = 0; i < this.records.length; i++) {
const record = this.records[i];
record.isAggregator ? this.max = record.max > this.max ? record.max : this.max : "number" == typeof record ? this.max = record > this.max ? record : this.max : this.field && "number" == typeof record[this.field] ? this.max = record[this.field] > this.max ? record[this.field] : this.max : this.field && !isNaN(record[this.field]) && (this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max);
}
}
}
exports.MaxAggregator = MaxAggregator;
class MinAggregator extends Aggregator {
constructor() {
super(...arguments), this.type = __1.AggregationType.MIN, this.min = Number.MAX_SAFE_INTEGER;
}
push(record) {
record && (this.isRecord && this.records && (record.isAggregator ? this.records.push(...record.records) : this.records.push(record)),
record.isAggregator ? this.min = record.min < this.min ? record.min : this.min : "number" == typeof record ? this.min = record < this.min ? record : this.min : this.field && "number" == typeof record[this.field] ? this.min = record[this.field] < this.min ? record[this.field] : this.min : this.field && !isNaN(record[this.field]) && (this.min = parseFloat(record[this.field]) < this.min ? parseFloat(record[this.field]) : this.min)),
this.clearCacheValue();
}
deleteRecord(record) {
record && (this.isRecord && this.records && (this.records = this.records.filter((item => item !== record))),
this.recalculate());
}
updateRecord(oldRecord, newRecord) {
oldRecord && newRecord && (this.isRecord && this.records && (this.records = this.records.map((item => item === oldRecord ? newRecord : item))),
this.recalculate());
}
value() {
var _a;
return (null === (_a = this.records) || void 0 === _a ? void 0 : _a.length) >= 1 ? this.min : void 0;
}
reset() {
this.records = [], this.min = Number.MAX_SAFE_INTEGER;
}
recalculate() {
if (this.min = Number.MAX_SAFE_INTEGER, this._formatedValue = void 0, this.records) for (let i = 0; i < this.records.length; i++) {
const record = this.records[i];
record.isAggregator ? this.min = record.min < this.min ? record.min : this.min : "number" == typeof record ? this.min = record < this.min ? record : this.min : this.field && "number" == typeof record[this.field] ? this.min = record[this.field] < this.min ? record[this.field] : this.min : this.field && !isNaN(record[this.field]) && (this.min = parseFloat(record[this.field]) < this.min ? parseFloat(record[this.field]) : this.min);
}
}
}
function indicatorSort(a, b) {
return a && b ? a.toString().localeCompare(b.toString(), "zh") : a ? 1 : -1;
}
function typeSort(a, b, sortType) {
if (sortType === __1.SortType.NORMAL || sortType === __1.SortType.normal) return 0;
const factor = sortType === __1.SortType.DESC || sortType === __1.SortType.desc ? -1 : 1;
return a && b ? a.toString().localeCompare(b.toString(), "zh") * factor : a ? 1 * factor : -1 * factor;
}
function naturalSort(as, bs, sortType) {
if (sortType === __1.SortType.NORMAL || sortType === __1.SortType.normal) return 0;
const rx = /(\d+)|(\D+)/g, rd = /\d/, rz = /^0/;
let a, a1, b, b1, nas = 0, nbs = 0;
const factor = sortType === __1.SortType.DESC || sortType === __1.SortType.desc ? -1 : 1;
if (null !== bs && null === as) return -1 * factor;
if (null !== as && null === bs) return 1 * factor;
if ("number" == typeof as && isNaN(as)) return -1 * factor;
if ("number" == typeof bs && isNaN(bs)) return 1 * factor;
if (nas = +as, nbs = +bs, nas < nbs) return -1 * factor;
if (nas > nbs) return 1 * factor;
if ("number" == typeof as && "number" != typeof bs) return -1 * factor;
if ("number" == typeof bs && "number" != typeof as) return 1 * factor;
if ("number" == typeof as && "number" == typeof bs) return 0;
if (isNaN(nbs) && !isNaN(nas)) return -1 * factor;
if (isNaN(nas) && !isNaN(nbs)) return 1 * factor;
if (a = String(as), b = String(bs), a === b) return 0;
if (!rd.test(a) || !rd.test(b)) return (a > b ? 1 : -1) * factor;
for (a = a.match(rx), b = b.match(rx); a.length && b.length; ) if (a1 = a.shift(),
b1 = b.shift(), a1 !== b1) return rd.test(a1) && rd.test(b1) ? (a1.replace(rz, ".0") - b1.replace(rz, ".0")) * factor : (a1 > b1 ? 1 : -1) * factor;
return (a.length - b.length) * factor;
}
function sortBy(order) {
let x;
const mapping = {}, lowercase_mapping = {};
for (let i = 0; i < order.length; i++) x = order[i], mapping[x] = i, "string" == typeof x && (lowercase_mapping[x.toLowerCase()] = i);
return function(a, b, sortType) {
if (sortType === __1.SortType.NORMAL || sortType === __1.SortType.normal) return 0;
const factor = sortType === __1.SortType.DESC || sortType === __1.SortType.desc ? -1 : 1;
let comparison;
return null !== mapping[a] && void 0 !== mapping[a] && null !== mapping[b] && void 0 !== mapping[b] ? comparison = mapping[a] - mapping[b] : null !== mapping[a] && void 0 !== mapping[a] ? comparison = -1 : null !== mapping[b] && void 0 !== mapping[b] ? comparison = 1 : null !== lowercase_mapping[a] && void 0 !== mapping[a] && null !== lowercase_mapping[b] && void 0 !== mapping[b] ? comparison = lowercase_mapping[a] - lowercase_mapping[b] : null === lowercase_mapping[a] || void 0 === mapping[a] || null === lowercase_mapping[b] || void 0 === mapping[b] ? comparison = 0 : null !== lowercase_mapping[a] && void 0 !== mapping[a] ? comparison = -1 : null !== lowercase_mapping[b] && void 0 !== mapping[b] && (comparison = 1),
(0, vutils_1.isValid)(comparison) ? comparison * factor : naturalSort(a, b, sortType);
};
}
function _getDependAggregatorValues(aggregators, dependIndicatorKeys) {
const dependAggregatorValues = {};
for (let m = 0; m < (null == dependIndicatorKeys ? void 0 : dependIndicatorKeys.length); m++) {
const aggrator = aggregators.find((aggrator => (null == aggrator ? void 0 : aggrator.key) === dependIndicatorKeys[m]));
aggrator && (dependAggregatorValues[aggrator.key] = null == aggrator ? void 0 : aggrator.value());
}
return dependAggregatorValues;
}
exports.MinAggregator = MinAggregator, exports.indicatorSort = indicatorSort, exports.typeSort = typeSort,
exports.naturalSort = naturalSort, exports.sortBy = sortBy;
//# sourceMappingURL=aggregation.js.map