@syncfusion/react-base
Version:
A common package of core React base, methods and class definitions
161 lines (160 loc) • 6.28 kB
JavaScript
import { select } from './dom';
import { isNullOrUndefined } from './util';
let left;
let top;
let width;
let height;
/**
* Sets the permitted drag area boundaries based on the defined dragArea.
*
* @private
* @param {HTMLElement | string} dragArea - The element or selector string defining the drag area
* @param {Element} helperElement - The helper element used in dragging
* @param {PositionCoordinates} borderWidth - The border width of the drag area
* @param {PositionCoordinates} padding - The padding of the drag area
* @param {PositionCoordinates} dragLimit - The object to store the calculated drag limits
* @returns {void}
*/
export function setDragArea(dragArea, helperElement, borderWidth, padding, dragLimit) {
let eleWidthBound;
let eleHeightBound;
let top = 0;
let left = 0;
let ele;
const type = typeof dragArea;
if (type === 'string') {
ele = select(dragArea);
}
else {
ele = dragArea;
}
if (ele) {
const elementArea = ele.getBoundingClientRect();
eleWidthBound = ele.scrollWidth ? ele.scrollWidth : elementArea.right - elementArea.left;
eleHeightBound = ele.scrollHeight ? (dragArea && !isNullOrUndefined(helperElement) && helperElement.classList.contains('sf-treeview')) ? ele.clientHeight : ele.scrollHeight : elementArea.bottom - elementArea.top;
const keys = ['Top', 'Left', 'Bottom', 'Right'];
const styles = getComputedStyle(ele);
for (let i = 0; i < keys.length; i++) {
const key = keys[parseInt(i.toString(), 10)];
const tborder = styles['border' + key + 'Width'];
const tpadding = styles['padding' + key];
const lowerKey = key.toLowerCase();
borderWidth[`${lowerKey}`] = isNaN(parseFloat(tborder)) ? 0 : parseFloat(tborder);
padding[`${lowerKey}`] = isNaN(parseFloat(tpadding)) ? 0 : parseFloat(tpadding);
}
if (dragArea && !isNullOrUndefined(helperElement) && helperElement.classList.contains('sf-treeview')) {
top = elementArea.top + document.scrollingElement.scrollTop;
}
else {
top = elementArea.top;
}
left = elementArea.left;
dragLimit.left = left + borderWidth.left + padding.left;
dragLimit.top = ele.offsetTop + borderWidth.top + padding.top;
dragLimit.right = left + eleWidthBound - (borderWidth.right + padding.right);
dragLimit.bottom = top + eleHeightBound - (borderWidth.bottom + padding.bottom);
}
}
/**
* Retrieves the document's full height or width, considering the scroll and offset values.
*
* @private
* @param {string} str - The dimension type ('Height' or 'Width') to calculate.
* @returns {number} - The maximum value across scroll, offset, and client dimensions.
*/
export function getDocumentWidthHeight(str) {
const docBody = document.body;
const docEle = document.documentElement;
return Math.max(docBody['scroll' + str], docEle['scroll' + str], docBody['offset' + str], docEle['offset' + str], docEle['client' + str]);
}
/**
* Determines if a given element is within the bounds of the viewport.
*
* @private
* @param {HTMLElement} el - The element to check.
* @returns {boolean} - True if the element is in the viewport, false otherwise.
*/
export function elementInViewport(el) {
top = el.offsetTop;
left = el.offsetLeft;
width = el.offsetWidth;
height = el.offsetHeight;
while (el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (top >= window.pageYOffset &&
left >= window.pageXOffset &&
(top + height) <= (window.pageYOffset + window.innerHeight) &&
(left + width) <= (window.pageXOffset + window.innerWidth));
}
/**
* Gets the coordinates of a mouse or touch event.
*
* @private
* @param {MouseEvent | TouchEvent} evt - The event object.
* @returns {Coordinates} - The x and y coordinates of the page and client.
*/
export function getCoordinates(evt) {
if (evt.type.indexOf('touch') > -1) {
return evt.changedTouches[0];
}
return evt;
}
/**
* Calculates the parent position of the element relative to the document.
*
* @private
* @param {Element} ele - The element for which the parent position is calculated.
* @returns {IPosition} - The calculated left and top position.
*/
export function calculateParentPosition(ele) {
if (isNullOrUndefined(ele)) {
return { left: 0, top: 0 };
}
const rect = ele.getBoundingClientRect();
const style = getComputedStyle(ele);
return {
left: (rect.left + window.pageXOffset) - parseInt(style.marginLeft, 10),
top: (rect.top + window.pageYOffset) - parseInt(style.marginTop, 10)
};
}
/**
* Retrieves all elements from a point defined by event coordinates.
*
* @private
* @param {MouseEvent | TouchEvent} evt - The event object containing coordinates.
* @returns {Element[]} - An array of elements located at the event's point.
*/
export function getPathElements(evt) {
const elementTop = evt.clientX > 0 ? evt.clientX : 0;
const elementLeft = evt.clientY > 0 ? evt.clientY : 0;
return document.elementsFromPoint(elementTop, elementLeft);
}
/**
* Identifies the scrollable parent of the current node element.
*
* @private
* @param {Element[]} nodes - The path of elements to check.
* @param {boolean} reverse - Whether to reverse the array to check from bottom to top.
* @returns {Element | null} - The first scrollable parent element or null.
*/
export function getScrollParent(nodes, reverse) {
const nodeList = reverse ? [...nodes].reverse() : nodes;
for (const node of nodeList) {
const computedStyle = window.getComputedStyle(node);
const overflowY = computedStyle.overflowY;
if ((overflowY === 'auto' || overflowY === 'scroll') &&
node.scrollHeight > node.clientHeight) {
return node;
}
}
const scrollingElement = document.scrollingElement;
const docOverflowY = window.getComputedStyle(scrollingElement).overflowY;
if (docOverflowY === 'visible') {
scrollingElement.style.overflow = 'auto';
return scrollingElement;
}
return null;
}