309 lines
9.8 KiB
JavaScript
309 lines
9.8 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
exports.default = function (e, target, node, place, effect, offset) {
|
|
var tipWidth = node.clientWidth;
|
|
var tipHeight = node.clientHeight;
|
|
|
|
var _getCurrentOffset = getCurrentOffset(e, target, effect),
|
|
mouseX = _getCurrentOffset.mouseX,
|
|
mouseY = _getCurrentOffset.mouseY;
|
|
|
|
var defaultOffset = getDefaultPosition(effect, target.clientWidth, target.clientHeight, 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;
|
|
};
|
|
|
|
// Judge if the tooltip has over the window(screen)
|
|
var outsideVertical = function outsideVertical() {
|
|
var result = false;
|
|
var newPlace = void 0;
|
|
if (getTipOffsetTop('left') < 0 && getTipOffsetBottom('left') <= windowHeight && getTipOffsetBottom('bottom') <= windowHeight) {
|
|
result = true;
|
|
newPlace = 'bottom';
|
|
} else if (getTipOffsetBottom('left') > windowHeight && getTipOffsetTop('left') >= 0 && getTipOffsetTop('top') >= 0) {
|
|
result = true;
|
|
newPlace = 'top';
|
|
}
|
|
return { result: result, newPlace: newPlace };
|
|
};
|
|
var outsideLeft = function outsideLeft() {
|
|
var _outsideVertical = outsideVertical(),
|
|
result = _outsideVertical.result,
|
|
newPlace = _outsideVertical.newPlace; // Deal with vertical as first priority
|
|
|
|
|
|
if (result && outsideHorizontal().result) {
|
|
return { result: false // No need to change, if change to vertical will out of space
|
|
};
|
|
}
|
|
if (!result && getTipOffsetLeft('left') < 0 && getTipOffsetRight('right') <= windowWidth) {
|
|
result = true; // If vertical ok, but let out of side and right won't out of side
|
|
newPlace = 'right';
|
|
}
|
|
return { result: result, newPlace: newPlace };
|
|
};
|
|
var outsideRight = function outsideRight() {
|
|
var _outsideVertical2 = outsideVertical(),
|
|
result = _outsideVertical2.result,
|
|
newPlace = _outsideVertical2.newPlace;
|
|
|
|
if (result && outsideHorizontal().result) {
|
|
return { result: false // No need to change, if change to vertical will out of space
|
|
};
|
|
}
|
|
if (!result && getTipOffsetRight('right') > windowWidth && getTipOffsetLeft('left') >= 0) {
|
|
result = true;
|
|
newPlace = 'left';
|
|
}
|
|
return { result: result, newPlace: newPlace };
|
|
};
|
|
|
|
var outsideHorizontal = function outsideHorizontal() {
|
|
var result = false;
|
|
var newPlace = void 0;
|
|
if (getTipOffsetLeft('top') < 0 && getTipOffsetRight('top') <= windowWidth && getTipOffsetRight('right') <= windowWidth) {
|
|
result = true;
|
|
newPlace = 'right';
|
|
} else if (getTipOffsetRight('top') > windowWidth && getTipOffsetLeft('top') >= 0 && getTipOffsetLeft('left') >= 0) {
|
|
result = true;
|
|
newPlace = 'left';
|
|
}
|
|
return { result: result, newPlace: newPlace };
|
|
};
|
|
var outsideTop = function outsideTop() {
|
|
var _outsideHorizontal = outsideHorizontal(),
|
|
result = _outsideHorizontal.result,
|
|
newPlace = _outsideHorizontal.newPlace;
|
|
|
|
if (result && outsideVertical().result) {
|
|
return { result: false };
|
|
}
|
|
if (!result && getTipOffsetTop('top') < 0 && getTipOffsetBottom('bottom') <= windowHeight) {
|
|
result = true;
|
|
newPlace = 'bottom';
|
|
}
|
|
return { result: result, newPlace: newPlace };
|
|
};
|
|
var outsideBottom = function outsideBottom() {
|
|
var _outsideHorizontal2 = outsideHorizontal(),
|
|
result = _outsideHorizontal2.result,
|
|
newPlace = _outsideHorizontal2.newPlace;
|
|
|
|
if (result && outsideVertical().result) {
|
|
return { result: false };
|
|
}
|
|
if (!result && getTipOffsetBottom('bottom') > windowHeight && getTipOffsetTop('top') >= 0) {
|
|
result = true;
|
|
newPlace = 'top';
|
|
}
|
|
return { result: result, newPlace: newPlace };
|
|
};
|
|
|
|
// Return new state to change the placement to the reverse if possible
|
|
var outsideLeftResult = outsideLeft();
|
|
var outsideRightResult = outsideRight();
|
|
var outsideTopResult = outsideTop();
|
|
var outsideBottomResult = outsideBottom();
|
|
|
|
if (place === 'left' && outsideLeftResult.result) {
|
|
return {
|
|
isNewState: true,
|
|
newState: { place: outsideLeftResult.newPlace }
|
|
};
|
|
} else if (place === 'right' && outsideRightResult.result) {
|
|
return {
|
|
isNewState: true,
|
|
newState: { place: outsideRightResult.newPlace }
|
|
};
|
|
} else if (place === 'top' && outsideTopResult.result) {
|
|
return {
|
|
isNewState: true,
|
|
newState: { place: outsideTopResult.newPlace }
|
|
};
|
|
} else if (place === 'bottom' && outsideBottomResult.result) {
|
|
return {
|
|
isNewState: true,
|
|
newState: { place: outsideBottomResult.newPlace }
|
|
};
|
|
}
|
|
|
|
// Return tooltip offset position
|
|
return {
|
|
isNewState: false,
|
|
position: {
|
|
left: parseInt(getTipOffsetLeft(place) - parentLeft, 10),
|
|
top: parseInt(getTipOffsetTop(place) - parentTop, 10)
|
|
}
|
|
};
|
|
};
|
|
|
|
// Get current mouse offset
|
|
var getCurrentOffset = function getCurrentOffset(e, currentTarget, effect) {
|
|
var boundingClientRect = currentTarget.getBoundingClientRect();
|
|
var targetTop = boundingClientRect.top;
|
|
var targetLeft = boundingClientRect.left;
|
|
var targetWidth = currentTarget.clientWidth;
|
|
var targetHeight = currentTarget.clientHeight;
|
|
|
|
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
|
|
/**
|
|
* 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 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 };
|
|
}; |