import getStyleComputedProperty from './getStyleComputedProperty'; import getBordersSize from './getBordersSize'; import getWindowSizes from './getWindowSizes'; import getScroll from './getScroll'; import getClientRect from './getClientRect'; import isIE10 from './isIE10'; /** * Get bounding client rect of given element * @method * @memberof Popper.Utils * @param {HTMLElement} element * @return {Object} client rect */ export default function getBoundingClientRect(element) { let rect = {}; // IE10 10 FIX: Please, don't ask, the element isn't // considered in DOM in some circumstances... // This isn't reproducible in IE10 compatibility mode of IE11 if (isIE10()) { try { rect = element.getBoundingClientRect(); const scrollTop = getScroll(element, 'top'); const scrollLeft = getScroll(element, 'left'); rect.top += scrollTop; rect.left += scrollLeft; rect.bottom += scrollTop; rect.right += scrollLeft; } catch (err) {} } else { rect = element.getBoundingClientRect(); } const result = { left: rect.left, top: rect.top, width: rect.right - rect.left, height: rect.bottom - rect.top, }; // subtract scrollbar size from sizes const sizes = element.nodeName === 'HTML' ? getWindowSizes() : {}; const width = sizes.width || element.clientWidth || result.right - result.left; const height = sizes.height || element.clientHeight || result.bottom - result.top; let horizScrollbar = element.offsetWidth - width; let vertScrollbar = element.offsetHeight - height; // if an hypothetical scrollbar is detected, we must be sure it's not a `border` // we make this check conditional for performance reasons if (horizScrollbar || vertScrollbar) { const styles = getStyleComputedProperty(element); horizScrollbar -= getBordersSize(styles, 'x'); vertScrollbar -= getBordersSize(styles, 'y'); result.width -= horizScrollbar; result.height -= vertScrollbar; } return getClientRect(result); }