import { $defined } from '@wisemapping/core-js'; // quick hand-made version of $.css() export const getStyle = (elem, prop) => { const result = window.getComputedStyle(elem)[prop]; if (typeof result === 'string' && /px$/.test(result)) { return parseFloat(result); } return result; }; // offset and position utils extracted and adapted from jquery source // https://github.com/jquery/jquery/blob/main/src/offset.js export const getOffset = (elem) => { if (!elem || !elem.getClientRects().length) { return { top: 0, left: 0 }; } // Get document-relative position by adding viewport scroll to viewport-relative gBCR const rect = elem.getBoundingClientRect(); const win = elem.ownerDocument.defaultView; return { top: rect.top + win.pageYOffset, left: rect.left + win.pageXOffset, }; }; export const getPosition = (elem) => { let offsetParent; let offset; let doc; let parentOffset = { top: 0, left: 0 }; // position:fixed elements are offset from the viewport, which itself always has zero offset if (getStyle(elem, 'position') === 'fixed') { // Assume position:fixed implies availability of getBoundingClientRect offset = elem.getBoundingClientRect(); } else { offset = getOffset(elem); // Account for the *real* offset parent, which can be the document or its root element // when a statically positioned element is identified doc = elem.ownerDocument; offsetParent = elem.offsetParent || doc.documentElement; while (offsetParent && (offsetParent === doc.body || offsetParent === doc.documentElement) && getStyle(offsetParent, 'position') === 'static') { offsetParent = offsetParent.parentNode; } if (offsetParent && offsetParent !== elem && offsetParent.nodeType === 1) { // Incorporate borders into its offset, since they are outside its content origin parentOffset = getOffset(offsetParent); parentOffset.top += getStyle(offsetParent, 'borderTopWidth'); parentOffset.left += getStyle(offsetParent, 'borderLeftWidth'); } } // Subtract parent offsets and element margins return { top: offset.top - parentOffset.top - getStyle(elem, 'marginTop'), left: offset.left - parentOffset.left - getStyle(elem, 'marginLeft'), }; };