UNPKG

@progress/kendo-angular-pivotgrid

Version:
224 lines (223 loc) 7.77 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ const EMPTY_REGEX = /^\s*$/; /** * @hidden */ export const isPresent = (value) => value !== null && value !== undefined; /** * @hidden */ export const isBlank = (value) => value === null || value === undefined; /** * @hidden */ export const isNullOrEmptyString = (value) => isBlank(value) || EMPTY_REGEX.test(value); /** * @hidden * Returns whether two arrays contain the same values. * Assumes array elements are primitive types */ export const areSameArrays = (a1, a2) => { const areArrays = (isPresent(a1) && Array.isArray(a1) && isPresent(a2) && Array.isArray(a2)); const areOfEqualLength = a1.length === a2.length; if (!areArrays || !areOfEqualLength) { return false; } for (let i = 0; i < a1.length; i++) { if (a1[i] !== a2[i]) { return false; } } return true; }; /** * @hidden */ export const wheelDelta = (e, axis) => { const delta = e[`wheelDelta${axis}`]; if (e.wheelDelta && (delta === undefined || delta)) { return e.wheelDelta; } if (e.detail && e.axis === e[axis === 'X' ? 'HORIZONTAL_AXIS' : 'VERTICAL_AXIS']) { return (-e.detail) * 10; } return 0; }; /** * @hidden */ export const syncScroll = (source, targets) => { const sourceScrollTop = source.scrollTop; const sourceScrollLeft = source.scrollLeft; const targetScrollTop = targets[0].scrollTop; const targetScrollLeft = targets[1].scrollLeft; const syncVertically = sourceScrollTop !== targetScrollTop; const syncHorizontally = sourceScrollLeft !== targetScrollLeft; if (syncVertically) { targets[0].scrollTop = sourceScrollTop; } else if (syncHorizontally) { targets[1].scrollLeft = sourceScrollLeft; } }; /** * @hidden */ export const syncWheel = (event, tables, prop, axis) => { const delta = axis === 'Y' ? -(wheelDelta(event, axis)) : wheelDelta(event, axis); if (delta) { tables[0][prop] = tables[1][prop] += delta; } }; /** * @hidden */ const getDocument = element => element.ownerDocument.documentElement; /** * @hidden */ const getWindow = element => element.ownerDocument.defaultView; /** * @hidden */ export const offset = element => { const { clientTop, clientLeft } = getDocument(element); const { pageYOffset, pageXOffset } = getWindow(element); const { top, left } = element.getBoundingClientRect(); return { top: top + pageYOffset - clientTop, left: left + pageXOffset - clientLeft }; }; /** * @hidden */ export const matchAriaAttributes = (wrapper) => { const rowHeaderRows = wrapper.querySelectorAll('.k-pivotgrid-row-headers .k-pivotgrid-row'); const rowHeaderCols = rowHeaderRows.length ? Array.from(rowHeaderRows[0]?.children)?.reduce((acc, curr) => acc += (+curr.getAttribute('colspan')), 0) : 0; const colHeaderRows = wrapper.querySelectorAll('.k-pivotgrid-column-headers tr'); const colHeaderCells = wrapper.querySelectorAll('.k-pivotgrid-column-headers th'); const valueTableCells = wrapper.querySelectorAll('.k-pivotgrid-values td'); const emptyCell = wrapper.querySelector('.k-pivotgrid-empty-cell'); emptyCell.setAttribute('aria-rowspan', colHeaderRows.length.toString()); emptyCell.setAttribute('aria-colspan', rowHeaderCols.toString()); const firstColHeadersRow = colHeaderRows[0]; const firstColHeaderRowCellsIds = Array.from(firstColHeadersRow?.children).map(el => el.getAttribute('id')).join(' '); firstColHeadersRow.setAttribute('aria-owns', `${emptyCell.getAttribute('id')} ${firstColHeaderRowCellsIds}`); rowHeaderRows.forEach((row, index) => { const valueCellsIds = filterAndMap(Array.from(valueTableCells), c => c.getAttribute('id')?.split('-')[4] === (index + 1).toString(), c => c.getAttribute('id')); row.setAttribute('aria-owns', valueCellsIds.join(' ')); }); valueTableCells.forEach(cell => { const cellColIndex = +cell.getAttribute('id')?.split('-')[5]; const colHeaderCellsIds = filterAndMap(Array.from(colHeaderCells), c => { const headerCellColIndex = +c.getAttribute('id')?.split('-')[5]; const headerCellColspan = +c.getAttribute('colspan'); const colIndexIsEqual = cellColIndex === headerCellColIndex; const cellColIndexIsWithinHeaderCellRange = headerCellColIndex < cellColIndex && headerCellColspan > 1 && (headerCellColIndex + headerCellColspan - 1 >= cellColIndex); return colIndexIsEqual || cellColIndexIsWithinHeaderCellRange; }, c => c.getAttribute('id')); colHeaderCellsIds.length && cell.setAttribute('aria-describedby', colHeaderCellsIds.join(' ')); }); }; /** * @hidden */ export const position = (target, before) => { const targetRect = offset(target); const { offsetWidth, offsetHeight } = target; const left = targetRect.left + (before ? 0 : offsetWidth); const top = targetRect.top + offsetHeight / 2; return { left, top }; }; /** * @hidden */ export const filterAndMap = (arr, predicate, mapper) => arr.reduce((acc, curr) => predicate(curr) ? [...acc, mapper(curr)] : acc, []); /** * @hidden */ export const cloneDate = (date) => date ? new Date(date.getTime()) : null; /** * @hidden */ export function clone(obj) { const result = {}; cloneObject(obj, result); return result; } /** * @hidden */ export function cloneObject(obj, result) { for (const field in obj) { if (field === '__proto__' || field === 'constructor' || field === 'prototype') { continue; } if (obj.hasOwnProperty(field)) { const value = obj[field]; result[field] = cloneValue(value, result[field]); } } } /** * @hidden */ export function cloneValue(value, nextValue) { if (Array.isArray(value)) { return cloneArray(value); } else if (value instanceof Date) { return cloneDate(value); } else if (value && typeof value === 'object') { const newNextValue = nextValue || {}; cloneObject(value, newNextValue); return newNextValue; } return value; } /** * @hidden */ export function cloneArray(array) { return array.map(value => cloneValue(value, undefined)); } /** * @hidden */ export const swapItems = (arr, i1, i2) => { const temp = arr[i1]; arr[i1] = arr[i2]; arr[i2] = temp; }; /** * @hidden */ export const isVisible = (el, container, offsetY, rtl) => { const elTop = el.offsetTop; const elBottom = elTop + el.clientHeight; let rect; let containerRect; if (rtl) { rect = el.getBoundingClientRect(); containerRect = container.getBoundingClientRect(); } const elLeft = rtl ? rect.left : el.offsetLeft; const elRight = rtl ? rect.right : elLeft + el.clientWidth; const containerTop = container.scrollTop; const containerBottom = containerTop + container.clientHeight; const containerLeft = rtl ? containerRect.left : container.scrollLeft; const containerRight = rtl ? containerRect.right : containerLeft + container.clientWidth; const visibleY = elTop >= containerTop - offsetY && elBottom <= containerBottom - offsetY; const visibleX = rtl ? elRight <= containerRight && elLeft >= containerLeft : elLeft >= containerLeft && elRight <= containerRight; return { visibleX, visibleY }; };