UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

308 lines (307 loc) • 9.88 kB
/** * DevExtreme (esm/__internal/core/utils/m_common.js) * Version: 24.2.7 * Build date: Mon Apr 28 2025 * * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import _extends from "@babel/runtime/helpers/esm/extends"; import config from "../../../core/config"; import Guid from "../../../core/guid"; import { toComparable } from "../../../core/utils/data"; import { Deferred, when } from "../../../core/utils/deferred"; import { each } from "../../../core/utils/iterator"; import { isDefined, isFunction, isObject, isString, type } from "../../../core/utils/type"; export const uiLayerInitialized = new Deferred; export const ensureDefined = function(value, defaultValue) { return isDefined(value) ? value : defaultValue }; export const executeAsync = function(action, context) { const deferred = new Deferred; const normalizedContext = context || this; const task = { promise: deferred.promise(), abort() { clearTimeout(timerId); deferred.rejectWith(normalizedContext) } }; const timerId = (arguments[2] || setTimeout)((function() { const result = action.call(normalizedContext); if (result && result.done && isFunction(result.done)) { result.done((function() { deferred.resolveWith(normalizedContext) })) } else { deferred.resolveWith(normalizedContext) } }), "number" === typeof context ? context : 0); return task }; const delayedFuncs = []; const delayedNames = []; const delayedDeferreds = []; let executingName; const deferExecute = function(name, func, deferred) { if (executingName && executingName !== name) { delayedFuncs.push(func); delayedNames.push(name); deferred = deferred || new Deferred; delayedDeferreds.push(deferred); return deferred } const oldExecutingName = executingName; const currentDelayedCount = delayedDeferreds.length; executingName = name; let result = func(); if (!result) { if (delayedDeferreds.length > currentDelayedCount) { result = when.apply(this, delayedDeferreds.slice(currentDelayedCount)) } else if (deferred) { deferred.resolve() } } executingName = oldExecutingName; if (deferred && result && result.done) { result.done(deferred.resolve).fail(deferred.reject) } if (!executingName && delayedFuncs.length) { ("render" === delayedNames.shift() ? deferRender : deferUpdate)(delayedFuncs.shift(), delayedDeferreds.shift()) } return result || when() }; export const deferRender = function(func, deferred) { return deferExecute("render", func, deferred) }; export const deferUpdate = function(func, deferred) { return deferExecute("update", func, deferred) }; export const deferRenderer = function(func) { return function() { const that = this; return deferExecute("render", (function() { return func.call(that) })) } }; export const deferUpdater = function(func) { return function() { const that = this; return deferExecute("update", (function() { return func.call(that) })) } }; export const findBestMatches = (targetFilter, items, mapFn) => { const bestMatches = []; let maxMatchCount = 0; each(items, ((index, itemSrc) => { let matchCount = 0; const item = mapFn ? mapFn(itemSrc) : itemSrc; each(targetFilter, ((paramName, targetValue) => { const value = item[paramName]; if (void 0 === value) { return } if (match(value, targetValue)) { matchCount++; return } matchCount = -1; return false })); if (matchCount < maxMatchCount) { return } if (matchCount > maxMatchCount) { bestMatches.length = 0; maxMatchCount = matchCount } bestMatches.push(itemSrc) })); return bestMatches }; const match = function(value, targetValue) { if (Array.isArray(value) && Array.isArray(targetValue)) { let mismatch = false; each(value, ((index, valueItem) => { if (valueItem !== targetValue[index]) { mismatch = true; return false } })); if (mismatch) { return false } return true } if (value === targetValue) { return true } return false }; export const splitPair = function(raw) { switch (type(raw)) { case "string": return raw.split(/\s+/, 2); case "object": return [raw.x ?? raw.h, raw.y ?? raw.v]; case "number": return [raw]; case "array": return raw; default: return null } }; export const normalizeKey = function(id) { let key = isString(id) ? id : id.toString(); const arr = key.match(/[^a-zA-Z0-9_]/g); arr && each(arr, ((_, sign) => { key = key.replace(sign, `__${sign.charCodeAt()}__`) })); return key }; export const denormalizeKey = function(key) { const arr = key.match(/__\d+__/g); arr && arr.forEach((char => { const charCode = parseInt(char.replace("__", "")); key = key.replace(char, String.fromCharCode(charCode)) })); return key }; export const pairToObject = function(raw, preventRound) { const pair = splitPair(raw); let h = preventRound ? parseFloat(pair && pair[0]) : parseInt(pair && pair[0], 10); let v = preventRound ? parseFloat(pair && pair[1]) : parseInt(pair && pair[1], 10); if (!isFinite(h)) { h = 0 } if (!isFinite(v)) { v = h } return { h: h, v: v } }; export const getKeyHash = function(key) { if (key instanceof Guid) { return key.toString() } if (isObject(key) || Array.isArray(key)) { try { const keyHash = JSON.stringify(key); return "{}" === keyHash ? key : keyHash } catch (e) { return key } } return key }; export const escapeRegExp = function(string) { return string.replace(/[[\]{}\-()*+?.\\^$|\s]/g, "\\$&") }; export const applyServerDecimalSeparator = function(value) { const separator = config().serverDecimalSeparator; if (isDefined(value)) { value = value.toString().replace(".", separator) } return value }; export const noop = function() {}; export const asyncNoop = function() { return (new Deferred).resolve().promise() }; export const grep = function(elements, checkFunction, invert) { const result = []; let check; const expectedCheck = !invert; for (let i = 0; i < elements.length; i++) { check = !!checkFunction(elements[i], i); if (check === expectedCheck) { result.push(elements[i]) } } return result }; const compareArrays = (array1, array2, depth, options) => { if (array1.length !== array2.length) { return false } return !array1.some(((item, idx) => !compareByValue(item, array2[idx], depth + 1, _extends({}, options, { strict: true })))) }; const compareObjects = (object1, object2, depth, options) => { const keys1 = Object.keys(object1); const keys2 = Object.keys(object2); if (keys1.length !== keys2.length) { return false } const keys2Set = new Set(keys2); return !keys1.some((key => !keys2Set.has(key) || !compareByValue(object1[key], object2[key], depth + 1, options))) }; const DEFAULT_EQUAL_BY_VALUE_OPTS = { maxDepth: 3, strict: true }; const compareByValue = (value1, value2, depth, options) => { const { strict: strict, maxDepth: maxDepth } = options; const comparable1 = toComparable(value1, true); const comparable2 = toComparable(value2, true); const comparisonResult = strict ? comparable1 === comparable2 : comparable1 == comparable2; switch (true) { case comparisonResult: case depth >= maxDepth: return true; case isObject(comparable1) && isObject(comparable2): return compareObjects(comparable1, comparable2, depth, options); case Array.isArray(comparable1) && Array.isArray(comparable2): return compareArrays(comparable1, comparable2, depth, options); default: return false } }; export const equalByValue = function(value1, value2) { let options = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : DEFAULT_EQUAL_BY_VALUE_OPTS; const compareOptions = _extends({}, DEFAULT_EQUAL_BY_VALUE_OPTS, options); return compareByValue(value1, value2, 0, compareOptions) }; export default { ensureDefined: ensureDefined, executeAsync: executeAsync, deferRender: deferRender, deferUpdate: deferUpdate, deferRenderer: deferRenderer, deferUpdater: deferUpdater, findBestMatches: findBestMatches, splitPair: splitPair, normalizeKey: normalizeKey, denormalizeKey: denormalizeKey, pairToObject: pairToObject, getKeyHash: getKeyHash, escapeRegExp: escapeRegExp, applyServerDecimalSeparator: applyServerDecimalSeparator, noop: noop, asyncNoop: asyncNoop, grep: grep, equalByValue: equalByValue };