UNPKG

react-tooltip

Version:
273 lines (242 loc) 7.97 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (e, target, node, place, desiredPlace, effect, offset) { var _getDimensions = getDimensions(node), tipWidth = _getDimensions.width, tipHeight = _getDimensions.height; var _getDimensions2 = getDimensions(target), targetWidth = _getDimensions2.width, targetHeight = _getDimensions2.height; var _getCurrentOffset = getCurrentOffset(e, target, effect), mouseX = _getCurrentOffset.mouseX, mouseY = _getCurrentOffset.mouseY; var defaultOffset = getDefaultPosition(effect, targetWidth, targetHeight, tipWidth, tipHeight); var _calculateOffset = calculateOffset(offset), extraOffset_X = _calculateOffset.extraOffset_X, extraOffset_Y = _calculateOffset.extraOffset_Y; var windowWidth = window.innerWidth; var windowHeight = window.innerHeight; var _getParent = getParent(node), parentTop = _getParent.parentTop, parentLeft = _getParent.parentLeft; // Get the edge offset of the tooltip var getTipOffsetLeft = function getTipOffsetLeft(place) { var offset_X = defaultOffset[place].l; return mouseX + offset_X + extraOffset_X; }; var getTipOffsetRight = function getTipOffsetRight(place) { var offset_X = defaultOffset[place].r; return mouseX + offset_X + extraOffset_X; }; var getTipOffsetTop = function getTipOffsetTop(place) { var offset_Y = defaultOffset[place].t; return mouseY + offset_Y + extraOffset_Y; }; var getTipOffsetBottom = function getTipOffsetBottom(place) { var offset_Y = defaultOffset[place].b; return mouseY + offset_Y + extraOffset_Y; }; // // Functions to test whether the tooltip's sides are inside // the client window for a given orientation p // // _____________ // | | <-- Right side // | p = 'left' |\ // | |/ |\ // |_____________| |_\ <-- Mouse // / \ | // | // | // Bottom side // var outsideLeft = function outsideLeft(p) { return getTipOffsetLeft(p) < 0; }; var outsideRight = function outsideRight(p) { return getTipOffsetRight(p) > windowWidth; }; var outsideTop = function outsideTop(p) { return getTipOffsetTop(p) < 0; }; var outsideBottom = function outsideBottom(p) { return getTipOffsetBottom(p) > windowHeight; }; // Check whether the tooltip with orientation p is completely inside the client window var outside = function outside(p) { return outsideLeft(p) || outsideRight(p) || outsideTop(p) || outsideBottom(p); }; var inside = function inside(p) { return !outside(p); }; var placesList = ['top', 'bottom', 'left', 'right']; var insideList = []; for (var i = 0; i < 4; i++) { var p = placesList[i]; if (inside(p)) { insideList.push(p); } } var isNewState = false; var newPlace = void 0; if (inside(desiredPlace) && desiredPlace !== place) { isNewState = true; newPlace = desiredPlace; } else if (insideList.length > 0 && outside(desiredPlace) && outside(place)) { isNewState = true; newPlace = insideList[0]; } if (isNewState) { return { isNewState: true, newState: { place: newPlace } }; } return { isNewState: false, position: { left: parseInt(getTipOffsetLeft(place) - parentLeft, 10), top: parseInt(getTipOffsetTop(place) - parentTop, 10) } }; }; var getDimensions = function getDimensions(node) { var _node$getBoundingClie = node.getBoundingClientRect(), height = _node$getBoundingClie.height, width = _node$getBoundingClie.width; return { height: parseInt(height, 10), width: parseInt(width, 10) }; }; // Get current mouse offset /** * Calculate the position of tooltip * * @params * - `e` {Event} the event of current mouse * - `target` {Element} the currentTarget of the event * - `node` {DOM} the react-tooltip object * - `place` {String} top / right / bottom / left * - `effect` {String} float / solid * - `offset` {Object} the offset to default position * * @return {Object} * - `isNewState` {Bool} required * - `newState` {Object} * - `position` {Object} {left: {Number}, top: {Number}} */ var getCurrentOffset = function getCurrentOffset(e, currentTarget, effect) { var boundingClientRect = currentTarget.getBoundingClientRect(); var targetTop = boundingClientRect.top; var targetLeft = boundingClientRect.left; var _getDimensions3 = getDimensions(currentTarget), targetWidth = _getDimensions3.width, targetHeight = _getDimensions3.height; if (effect === 'float') { return { mouseX: e.clientX, mouseY: e.clientY }; } return { mouseX: targetLeft + targetWidth / 2, mouseY: targetTop + targetHeight / 2 }; }; // List all possibility of tooltip final offset // This is useful in judging if it is necessary for tooltip to switch position when out of window var getDefaultPosition = function getDefaultPosition(effect, targetWidth, targetHeight, tipWidth, tipHeight) { var top = void 0; var right = void 0; var bottom = void 0; var left = void 0; var disToMouse = 3; var triangleHeight = 2; var cursorHeight = 12; // Optimize for float bottom only, cause the cursor will hide the tooltip if (effect === 'float') { top = { l: -(tipWidth / 2), r: tipWidth / 2, t: -(tipHeight + disToMouse + triangleHeight), b: -disToMouse }; bottom = { l: -(tipWidth / 2), r: tipWidth / 2, t: disToMouse + cursorHeight, b: tipHeight + disToMouse + triangleHeight + cursorHeight }; left = { l: -(tipWidth + disToMouse + triangleHeight), r: -disToMouse, t: -(tipHeight / 2), b: tipHeight / 2 }; right = { l: disToMouse, r: tipWidth + disToMouse + triangleHeight, t: -(tipHeight / 2), b: tipHeight / 2 }; } else if (effect === 'solid') { top = { l: -(tipWidth / 2), r: tipWidth / 2, t: -(targetHeight / 2 + tipHeight + triangleHeight), b: -(targetHeight / 2) }; bottom = { l: -(tipWidth / 2), r: tipWidth / 2, t: targetHeight / 2, b: targetHeight / 2 + tipHeight + triangleHeight }; left = { l: -(tipWidth + targetWidth / 2 + triangleHeight), r: -(targetWidth / 2), t: -(tipHeight / 2), b: tipHeight / 2 }; right = { l: targetWidth / 2, r: tipWidth + targetWidth / 2 + triangleHeight, t: -(tipHeight / 2), b: tipHeight / 2 }; } return { top: top, bottom: bottom, left: left, right: right }; }; // Consider additional offset into position calculation var calculateOffset = function calculateOffset(offset) { var extraOffset_X = 0; var extraOffset_Y = 0; if (Object.prototype.toString.apply(offset) === '[object String]') { offset = JSON.parse(offset.toString().replace(/\'/g, '\"')); } for (var key in offset) { if (key === 'top') { extraOffset_Y -= parseInt(offset[key], 10); } else if (key === 'bottom') { extraOffset_Y += parseInt(offset[key], 10); } else if (key === 'left') { extraOffset_X -= parseInt(offset[key], 10); } else if (key === 'right') { extraOffset_X += parseInt(offset[key], 10); } } return { extraOffset_X: extraOffset_X, extraOffset_Y: extraOffset_Y }; }; // Get the offset of the parent elements var getParent = function getParent(currentTarget) { var currentParent = currentTarget; while (currentParent) { if (window.getComputedStyle(currentParent).getPropertyValue('transform') !== 'none') break; currentParent = currentParent.parentElement; } var parentTop = currentParent && currentParent.getBoundingClientRect().top || 0; var parentLeft = currentParent && currentParent.getBoundingClientRect().left || 0; return { parentTop: parentTop, parentLeft: parentLeft }; };