Angular 1.5 On-Hover Popover Example

by dominathan

HTML

<div ng-app="popoverApp" ng-controller="Ctrl">
  <div on-popover-hover class="button">Hover For Popover
    <p ng-show="showPopover" class="popover bottom">
      <strong class="strong">You did it!</strong> Move your cursor toward the popover. It'll stay open as long as you are moving toward it, within the path between the button and the popover.
    </p>
  </div>
</div>

SCSS

body {
  font-family: sans-serif;
  padding: 30px;
}

.button {
  background: #000;
  border-radius: 6px;
  color: #eee;
  cursor: default;
  display: table;
  margin: 0 auto;
  padding: 6px 12px;
}

.popover {
  animation: popover-in .3s forwards;
  background: #000;
  border-radius: 6px;
  color: #eee;
  left: 0;
  line-height: 1.4;
  margin: 0 auto;
  opacity: 0;
  padding: 30px;
  position: absolute;
  right: 0;
  text-align: center;
  top: 120px;
  transform-origin: 50% 0;
  width: 300px;
}

.strong {
  display: block;
  font-weight: bold;
  margin-bottom: 6px;
}

@keyframes popover-in {
  0% {
    opacity: 0;
    transform: scale3d(.95,.95,1);
  }
  
  100% {
    opacity: 1;
    transform: scale3d(1,1,1);
  }
}

JavaScript

function pointInPolygon(point, vs) {
  // ray-casting algorithm based on
  // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html

  var x = point[0],
    y = point[1];

  var inside = false;
  for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
    var xi = vs[i][0],
      yi = vs[i][1];
    var xj = vs[j][0],
      yj = vs[j][1];

    var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
    if (intersect) inside = !inside;
  }

  return inside;
};
angular.module('popoverApp', [])
  .controller('Ctrl', function($scope) {})
  .directive('onPopoverHover', function($compile, $document) {
    return {
      restrict: '',
      link: function($scope, buttonElement, attrs) {
        function openPopover() {
          $scope.showPopover = true;
          $scope.$apply()
        }

        function closePopover() {
          $scope.showPopover = false;
          cleanupPopover();
          $scope.$apply()
        }
        var popoverElement = angular.element(buttonElement.children()[0]);
        var popoverClientRect = popoverElement[0].getBoundingClientRect();
        var elementClientRect = buttonElement[0].getBoundingClientRect();

        var popoverRect = {
          topLeft: [popoverClientRect.left, popoverClientRect.top],
          topRight: [popoverClientRect.right, popoverClientRect.top],
          bottomLeft: [popoverClientRect.left, popoverClientRect.bottom],
          bottomRight: [popoverClientRect.right, popoverClientRect.bottom]
        };
        var elementRect = {
          topLeft: [elementClientRect.left, elementClientRect.top],
          topRight: [elementClientRect.right, elementClientRect.top],
          bottomLeft: [elementClientRect.left, elementClientRect.bottom],
          bottomRight: [elementClientRect.right, elementClientRect.bottom]
        };
        buttonElement.on('mouseenter', onButtonEnter);

        function getPath() {
          if (popoverElement.hasClass('bottom')) {
...