react-bootstrap
Version:
Bootstrap 3 components build with React
109 lines (93 loc) • 2.82 kB
JavaScript
/**
* Shortcut to compute element style
*
* @param {HTMLElement} elem
* @returns {CssStyle}
*/
function getComputedStyles(elem) {
return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
}
/**
* Get elements offset
*
* TODO: REMOVE JQUERY!
*
* @param {HTMLElement} DOMNode
* @returns {{top: number, left: number}}
*/
function getOffset(DOMNode) {
if (window.jQuery) {
return window.jQuery(DOMNode).offset();
}
var docElem = document.documentElement;
var box = { top: 0, left: 0 };
// If we don't have gBCR, just use 0,0 rather than error
// BlackBerry 5, iOS 3 (original iPhone)
if ( typeof DOMNode.getBoundingClientRect !== 'undefined' ) {
box = DOMNode.getBoundingClientRect();
}
return {
top: box.top + window.pageYOffset - docElem.clientTop,
left: box.left + window.pageXOffset - docElem.clientLeft
};
}
/**
* Get elements position
*
* TODO: REMOVE JQUERY!
*
* @param {HTMLElement} elem
* @param {HTMLElement?} offsetParent
* @returns {{top: number, left: number}}
*/
function getPosition(elem, offsetParent) {
if (window.jQuery) {
return window.jQuery(elem).position();
}
var offset,
parentOffset = {top: 0, left: 0};
// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
if (getComputedStyles(elem).position === 'fixed' ) {
// We assume that getBoundingClientRect is available when computed position is fixed
offset = elem.getBoundingClientRect();
} else {
if (!offsetParent) {
// Get *real* offsetParent
offsetParent = offsetParent(elem);
}
// Get correct offsets
offset = getOffset(elem);
if ( offsetParent.nodeName !== 'HTML') {
parentOffset = getOffset(offsetParent);
}
// Add offsetParent borders
parentOffset.top += parseInt(getComputedStyles(offsetParent).borderTopWidth, 10);
parentOffset.left += parseInt(getComputedStyles(offsetParent).borderLeftWidth, 10);
}
// Subtract parent offsets and element margins
return {
top: offset.top - parentOffset.top - parseInt(getComputedStyles(elem).marginTop, 10),
left: offset.left - parentOffset.left - parseInt(getComputedStyles(elem).marginLeft, 10)
};
}
/**
* Get parent element
*
* @param {HTMLElement?} elem
* @returns {HTMLElement}
*/
function offsetParent(elem) {
var docElem = document.documentElement;
var offsetParent = elem.offsetParent || docElem;
while ( offsetParent && ( offsetParent.nodeName !== 'HTML' &&
getComputedStyles(offsetParent).position === 'static' ) ) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent || docElem;
}
module.exports = {
getComputedStyles: getComputedStyles,
getOffset: getOffset,
getPosition: getPosition,
offsetParent: offsetParent
};