UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

594 lines (589 loc) • 19.8 kB
/** * DevExtreme (cjs/data/array_query.js) * Version: 23.2.6 * Build date: Wed May 01 2024 * * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; exports.default = void 0; var _class = _interopRequireDefault(require("../core/class")); var _type = require("../core/utils/type"); var _iterator = require("../core/utils/iterator"); var _data = require("../core/utils/data"); var _deferred = require("../core/utils/deferred"); var _errors = require("./errors"); var _utils = require("./utils"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } } const Iterator = _class.default.inherit({ toArray: function() { const result = []; this.reset(); while (this.next()) { result.push(this.current()) } return result }, countable: function() { return false } }); const ArrayIterator = Iterator.inherit({ ctor: function(array) { this.array = array; this.index = -1 }, next: function() { if (this.index + 1 < this.array.length) { this.index++; return true } return false }, current: function() { return this.array[this.index] }, reset: function() { this.index = -1 }, toArray: function() { return this.array.slice(0) }, countable: function() { return true }, count: function() { return this.array.length } }); const WrappedIterator = Iterator.inherit({ ctor: function(iter) { this.iter = iter }, next: function() { return this.iter.next() }, current: function() { return this.iter.current() }, reset: function() { return this.iter.reset() } }); const MapIterator = WrappedIterator.inherit({ ctor: function(iter, mapper) { this.callBase(iter); this.index = -1; this.mapper = mapper }, current: function() { return this.mapper(this.callBase(), this.index) }, next: function() { const hasNext = this.callBase(); if (hasNext) { this.index++ } return hasNext } }); const defaultCompare = function(xValue, yValue, options) { if ((0, _type.isString)(xValue) && (0, _type.isString)(yValue) && (null !== options && void 0 !== options && options.locale || null !== options && void 0 !== options && options.collatorOptions)) { return new Intl.Collator((null === options || void 0 === options ? void 0 : options.locale) || void 0, (null === options || void 0 === options ? void 0 : options.collatorOptions) || void 0).compare(xValue, yValue) } xValue = (0, _data.toComparable)(xValue, false, options); yValue = (0, _data.toComparable)(yValue, false, options); if (null === xValue && null !== yValue) { return -1 } if (null !== xValue && null === yValue) { return 1 } if (void 0 === xValue && void 0 !== yValue) { return 1 } if (void 0 !== xValue && void 0 === yValue) { return -1 } if (xValue < yValue) { return -1 } if (xValue > yValue) { return 1 } return 0 }; const SortIterator = Iterator.inherit({ ctor: function(iter, getter, desc, compare) { this.langParams = iter.langParams; if (!(iter instanceof MapIterator)) { iter = new MapIterator(iter, this._wrap); iter.langParams = this.langParams } this.iter = iter; this.rules = [{ getter: getter, desc: desc, compare: compare, langParams: this.langParams }] }, thenBy: function(getter, desc, compare) { const result = new SortIterator(this.sortedIter || this.iter, getter, desc, compare); if (!this.sortedIter) { result.rules = this.rules.concat(result.rules) } return result }, next: function() { this._ensureSorted(); return this.sortedIter.next() }, current: function() { this._ensureSorted(); return this.sortedIter.current() }, reset: function() { delete this.sortedIter }, countable: function() { return this.sortedIter || this.iter.countable() }, count: function() { if (this.sortedIter) { return this.sortedIter.count() } return this.iter.count() }, _ensureSorted: function() { const that = this; if (that.sortedIter) { return }(0, _iterator.each)(that.rules, (function() { this.getter = (0, _data.compileGetter)(this.getter) })); that.sortedIter = new MapIterator(new ArrayIterator(this.iter.toArray().sort((function(x, y) { return that._compare(x, y) }))), that._unwrap) }, _wrap: function(record, index) { return { index: index, value: record } }, _unwrap: function(wrappedItem) { return wrappedItem.value }, _getDefaultCompare: langParams => (xValue, yValue) => defaultCompare(xValue, yValue, langParams), _compare: function(x, y) { const xIndex = x.index; const yIndex = y.index; x = x.value; y = y.value; if (x === y) { return xIndex - yIndex } for (let i = 0, rulesCount = this.rules.length; i < rulesCount; i++) { const rule = this.rules[i]; const xValue = rule.getter(x); const yValue = rule.getter(y); const compare = rule.compare || this._getDefaultCompare(rule.langParams); const compareResult = compare(xValue, yValue); if (compareResult) { return rule.desc ? -compareResult : compareResult } } return xIndex - yIndex } }); const compileCriteria = function() { let langParams = {}; const _toComparable = value => (0, _data.toComparable)(value, false, langParams); const compileGroup = function(crit) { if ((0, _utils.isUniformEqualsByOr)(crit)) { return (crit => { const getter = (0, _data.compileGetter)(crit[0][0]); const filterValues = crit.reduce((acc, item, i) => { if (i % 2 === 0) { acc.push(_toComparable(item[2])) } return acc }, []); return obj => { const value = _toComparable(getter(obj)); return filterValues.some(filterValue => useStrictComparison(filterValue) ? value === filterValue : value == filterValue) } })(crit) } const ops = []; let isConjunctiveOperator = false; let isConjunctiveNextOperator = false; (0, _iterator.each)(crit, (function() { if (Array.isArray(this) || (0, _type.isFunction)(this)) { if (ops.length > 1 && isConjunctiveOperator !== isConjunctiveNextOperator) { throw new _errors.errors.Error("E4019") } ops.push(compileCriteria(this, langParams)); isConjunctiveOperator = isConjunctiveNextOperator; isConjunctiveNextOperator = true } else { isConjunctiveNextOperator = (0, _utils.isConjunctiveOperator)(this) } })); return function(d) { let result = isConjunctiveOperator; for (let i = 0; i < ops.length; i++) { if (ops[i](d) !== isConjunctiveOperator) { result = !isConjunctiveOperator; break } } return result } }; const toString = function(value) { var _langParams; return (0, _type.isDefined)(value) ? null !== (_langParams = langParams) && void 0 !== _langParams && _langParams.locale ? value.toLocaleString(langParams.locale) : value.toString() : "" }; function compileEquals(getter, value, negate) { return function(obj) { obj = _toComparable(getter(obj)); let result = useStrictComparison(value) ? obj === value : obj == value; if (negate) { result = !result } return result } } function useStrictComparison(value) { return "" === value || 0 === value || false === value } return function(crit, options) { langParams = options || {}; if ((0, _type.isFunction)(crit)) { return crit } if ((0, _utils.isGroupCriterion)(crit)) { return compileGroup(crit) } if ((0, _utils.isUnaryOperation)(crit)) { return function(crit) { const op = crit[0]; const criteria = compileCriteria(crit[1], langParams); if ("!" === op) { return function(obj) { return !criteria(obj) } } throw _errors.errors.Error("E4003", op) }(crit) } return function(crit) { crit = (0, _utils.normalizeBinaryCriterion)(crit); const getter = (0, _data.compileGetter)(crit[0]); const op = crit[1]; let value = crit[2]; value = _toComparable(value); const compare = (obj, operatorFn) => { obj = _toComparable(getter(obj)); return (null == value || null == obj) && value !== obj ? false : operatorFn(obj, value) }; switch (op.toLowerCase()) { case "=": return compileEquals(getter, value); case "<>": return compileEquals(getter, value, true); case ">": return obj => compare(obj, (a, b) => a > b); case "<": return obj => compare(obj, (a, b) => a < b); case ">=": return obj => compare(obj, (a, b) => a >= b); case "<=": return obj => compare(obj, (a, b) => a <= b); case "startswith": return function(obj) { return 0 === _toComparable(toString(getter(obj))).indexOf(value) }; case "endswith": return function(obj) { const getterValue = _toComparable(toString(getter(obj))); const searchValue = toString(value); if (getterValue.length < searchValue.length) { return false } const index = getterValue.lastIndexOf(value); return -1 !== index && index === getterValue.length - value.length }; case "contains": return function(obj) { return _toComparable(toString(getter(obj))).indexOf(value) > -1 }; case "notcontains": return function(obj) { return -1 === _toComparable(toString(getter(obj))).indexOf(value) } } throw _errors.errors.Error("E4003", op) }(crit) } }(); const FilterIterator = WrappedIterator.inherit({ ctor: function(iter, criteria) { this.callBase(iter); this.langParams = iter.langParams; this.criteria = compileCriteria(criteria, this.langParams) }, next: function() { while (this.iter.next()) { if (this.criteria(this.current())) { return true } } return false } }); const GroupIterator = Iterator.inherit({ ctor: function(iter, getter) { this.iter = iter; this.getter = getter }, next: function() { this._ensureGrouped(); return this.groupedIter.next() }, current: function() { this._ensureGrouped(); return this.groupedIter.current() }, reset: function() { delete this.groupedIter }, countable: function() { return !!this.groupedIter }, count: function() { return this.groupedIter.count() }, _ensureGrouped: function() { if (this.groupedIter) { return } const hash = {}; const keys = []; const iter = this.iter; const getter = (0, _data.compileGetter)(this.getter); iter.reset(); while (iter.next()) { const current = iter.current(); const key = getter(current); if (key in hash) { hash[key].push(current) } else { hash[key] = [current]; keys.push(key) } } this.groupedIter = new ArrayIterator((0, _iterator.map)(keys, (function(key) { return { key: key, items: hash[key] } }))) } }); const SelectIterator = WrappedIterator.inherit({ ctor: function(iter, getter) { this.callBase(iter); this.getter = (0, _data.compileGetter)(getter) }, current: function() { return this.getter(this.callBase()) }, countable: function() { return this.iter.countable() }, count: function() { return this.iter.count() } }); const SliceIterator = WrappedIterator.inherit({ ctor: function(iter, skip, take) { this.callBase(iter); this.skip = Math.max(0, skip); this.take = Math.max(0, take); this.pos = 0 }, next: function() { if (this.pos >= this.skip + this.take) { return false } while (this.pos < this.skip && this.iter.next()) { this.pos++ } this.pos++; return this.iter.next() }, reset: function() { this.callBase(); this.pos = 0 }, countable: function() { return this.iter.countable() }, count: function() { return Math.min(this.iter.count() - this.skip, this.take) } }); const arrayQueryImpl = function(iter, queryOptions) { queryOptions = queryOptions || {}; if (!(iter instanceof Iterator)) { iter = new ArrayIterator(iter) } if (queryOptions.langParams) { iter.langParams = queryOptions.langParams } const handleError = function(error) { const handler = queryOptions.errorHandler; if (handler) { handler(error) }(0, _errors.handleError)(error) }; const aggregateCore = function(aggregator) { const d = (new _deferred.Deferred).fail(handleError); let seed; const step = aggregator.step; const finalize = aggregator.finalize; try { iter.reset(); if ("seed" in aggregator) { seed = aggregator.seed } else { seed = iter.next() ? iter.current() : NaN } let accumulator = seed; while (iter.next()) { accumulator = step(accumulator, iter.current()) } d.resolve(finalize ? finalize(accumulator) : accumulator) } catch (x) { d.reject(x) } return d.promise() }; const standardAggregate = function(name) { return aggregateCore(_utils.aggregators[name]) }; const select = function(getter) { if (!(0, _type.isFunction)(getter) && !Array.isArray(getter)) { getter = [].slice.call(arguments) } return chainQuery(new SelectIterator(iter, getter)) }; const selectProp = function(name) { return select((0, _data.compileGetter)(name)) }; function chainQuery(iter) { return arrayQueryImpl(iter, queryOptions) } return { toArray: function() { return iter.toArray() }, enumerate: function() { const d = (new _deferred.Deferred).fail(handleError); try { d.resolve(iter.toArray()) } catch (x) { d.reject(x) } return d.promise() }, setLangParams(options) { iter.langParams = options }, sortBy: function(getter, desc, compare) { return chainQuery(new SortIterator(iter, getter, desc, compare)) }, thenBy: function(getter, desc, compare) { if (iter instanceof SortIterator) { return chainQuery(iter.thenBy(getter, desc, compare)) } throw _errors.errors.Error("E4004") }, filter: function(criteria) { if (!Array.isArray(criteria)) { criteria = [].slice.call(arguments) } return chainQuery(new FilterIterator(iter, criteria)) }, slice: function(skip, take) { if (void 0 === take) { take = Number.MAX_VALUE } return chainQuery(new SliceIterator(iter, skip, take)) }, select: select, groupBy: function(getter) { return chainQuery(new GroupIterator(iter, getter)) }, aggregate: function(seed, step, finalize) { if (arguments.length < 2) { return aggregateCore({ step: arguments[0] }) } return aggregateCore({ seed: seed, step: step, finalize: finalize }) }, count: function() { if (iter.countable()) { const d = (new _deferred.Deferred).fail(handleError); try { d.resolve(iter.count()) } catch (x) { d.reject(x) } return d.promise() } return standardAggregate("count") }, sum: function(getter) { if (getter) { return selectProp(getter).sum() } return standardAggregate("sum") }, min: function(getter) { if (getter) { return selectProp(getter).min() } return standardAggregate("min") }, max: function(getter) { if (getter) { return selectProp(getter).max() } return standardAggregate("max") }, avg: function(getter) { if (getter) { return selectProp(getter).avg() } return standardAggregate("avg") } } }; var _default = arrayQueryImpl; exports.default = _default; module.exports = exports.default; module.exports.default = exports.default;