devongovett-react-overlays
Version:
Utilities for creating robust overlay components
147 lines (110 loc) • 4.55 kB
JavaScript
'use strict';
exports.__esModule = true;
exports.default = calculatePosition;
var _offset = require('dom-helpers/query/offset');
var _offset2 = _interopRequireDefault(_offset);
var _position = require('dom-helpers/query/position');
var _position2 = _interopRequireDefault(_position);
var _scrollTop = require('dom-helpers/query/scrollTop');
var _scrollTop2 = _interopRequireDefault(_scrollTop);
var _scrollLeft = require('dom-helpers/query/scrollLeft');
var _scrollLeft2 = _interopRequireDefault(_scrollLeft);
var _ownerDocument = require('./ownerDocument');
var _ownerDocument2 = _interopRequireDefault(_ownerDocument);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var AXIS = {
top: 'top',
bottom: 'top',
left: 'left',
right: 'left'
};
var CROSS_AXIS = {
top: 'left',
left: 'top'
};
var AXIS_SIZE = {
top: 'height',
left: 'width'
};
function getContainerDimensions(containerNode) {
var width = void 0,
height = void 0;
var scroll = {};
if (containerNode.tagName === 'BODY') {
width = window.innerWidth;
height = window.innerHeight;
scroll.top = (0, _scrollTop2.default)((0, _ownerDocument2.default)(containerNode).documentElement) || (0, _scrollTop2.default)(containerNode);
scroll.left = (0, _scrollLeft2.default)((0, _ownerDocument2.default)(containerNode).documentElement) || (0, _scrollLeft2.default)(containerNode);
} else {
var _getOffset = (0, _offset2.default)(containerNode);
width = _getOffset.width;
height = _getOffset.height;
scroll.top = (0, _scrollTop2.default)(containerNode);
scroll.left = (0, _scrollLeft2.default)(containerNode);
}
return { width: width, height: height, scroll: scroll };
}
function getDelta(axis, offset, size, container, padding) {
var containerDimensions = getContainerDimensions(container);
var containerScroll = containerDimensions.scroll[axis];
var containerHeight = containerDimensions[AXIS_SIZE[axis]];
var startEdgeOffset = offset - padding - containerScroll;
var endEdgeOffset = offset + padding - containerScroll + size;
if (startEdgeOffset < 0) {
return -startEdgeOffset;
} else if (endEdgeOffset > containerHeight) {
return containerHeight - endEdgeOffset;
} else {
return 0;
}
}
function parsePlacement(input) {
var _input$split = input.split(' '),
placement = _input$split[0],
crossPlacement = _input$split[1];
var axis = AXIS[placement] || 'right';
var crossAxis = CROSS_AXIS[axis];
if (!AXIS[crossPlacement]) {
crossPlacement = 'center';
}
var size = AXIS_SIZE[axis];
var crossSize = AXIS_SIZE[crossAxis];
return { placement: placement, crossPlacement: crossPlacement, axis: axis, crossAxis: crossAxis, size: size, crossSize: crossSize };
}
function calculatePosition(placementInput, overlayNode, target, container, padding) {
var childOffset = container.tagName === 'BODY' ? (0, _offset2.default)(target) : (0, _position2.default)(target, container);
var overlaySize = (0, _offset2.default)(overlayNode);
var style = window.getComputedStyle(overlayNode);
overlaySize.width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10) || 0;
overlaySize.height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10) || 0;
var _parsePlacement = parsePlacement(placementInput),
placement = _parsePlacement.placement,
crossPlacement = _parsePlacement.crossPlacement,
axis = _parsePlacement.axis,
crossAxis = _parsePlacement.crossAxis,
size = _parsePlacement.size,
crossSize = _parsePlacement.crossSize;
var position = {};
var arrowPosition = {};
position[crossAxis] = childOffset[crossAxis];
if (crossPlacement === 'center') {
position[crossAxis] += (childOffset[crossSize] - overlaySize[crossSize]) / 2;
} else if (crossPlacement !== crossAxis) {
position[crossAxis] += childOffset[crossSize] - overlaySize[crossSize];
}
if (placement === axis) {
position[axis] = childOffset[axis] - overlaySize[size];
} else {
position[axis] = childOffset[axis] + childOffset[size];
}
var delta = getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], container, padding);
position[crossAxis] += delta;
arrowPosition[crossAxis] = 50 * (1 - 2 * delta / overlaySize[crossSize]) + '%';
return {
positionLeft: position.left,
positionTop: position.top,
arrowOffsetLeft: arrowPosition.left,
arrowOffsetTop: arrowPosition.top
};
}
module.exports = exports['default'];