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 };
 | 
						|
}; |