KamaKAzii
11/24/2016 - 6:01 AM

interactive_tutorial_directive.js

angular.module("personal-banker").directive("interactiveTutorial", function(env, $timeout, $document, $q, $rootScope, UserTip) {
  return {
    restrict: "E",
    templateUrl: env.templates["amf-ui-library/templates/directives/interactive_tutorial.html"],
    link: function(scope, elem, attrs) {
      elem.on("click", function(e) {
        return e.stopPropagation();
      });
      scope.currentStep = 0;
      $rootScope.$on("$stateChangeSuccess", function(e) {
        if (scope.tutorialActive && !scope.tutorialData.allowStateChange) {
          return scope.stopTutorial();
        }
      });
      scope.$on("it:startTutorial", function(e, tutorialData) {
        return scope.startTutorial(tutorialData);
      });
      scope.$on("it:stopTutorial", function() {
        return scope.stopTutorial();
      });
      scope.$on("it:nextStep", function() {
        return scope.nextStep();
      });
      scope.$on("it:previousStep", function() {
        return scope.previousStep();
      });
      scope.$on("tb:finishedTutorial", function() {
        return scope.setTutorialTipAsDone();
      });
      scope.setTutorialTipAsDone = function() {
        return UserTip.hide(scope.tutorialData.name);
      };
      scope.startTutorial = function(tutorialData) {
        var onTutorialStart;
        $rootScope.$broadcast("it:tutorialStarted");
        scope.tutorialData = tutorialData;
        scope.tutorialActive = true;
        scope.currentStep = 0;
        onTutorialStart = scope.tutorialData.onTutorialStart;
        if (onTutorialStartFunc) {
          onTutorialStartFunc();
        }
        return scope.nextStep();
      };
      scope.stopTutorial = function() {
        var onLeaveHighlightFunc, onTutorialStopFunc;
        scope.tutorial = null;
        scope.tutorialActive = false;
        scope.showSpotlight = false;
        scope.showTutorialBox = false;
        onLeaveHighlightFunc = scope.tutorialData.steps[scope.currentStep - 1].onLeaveHighlight;
        if (onLeaveHighlightFunc) {
          onLeaveHighlightFunc();
        }
        onTutorialStopFunc = scope.tutorialData.onTutorialStop;
        if (onTutorialStopFunc) {
          onTutorialStopFunc();
        }
        return $rootScope.$broadcast("it:tutorialStopped");
      };
      scope.nextStep = function() {
        var data, onLeaveHighlightFunc;
        scope.currentStep++;
        if (scope.currentStep > scope.tutorialData.steps.length) {
          scope.currentStep--;
          return;
        }
        scope.showTutorialBox = false;
        if (scope.currentStep !== 1) {
          onLeaveHighlightFunc = scope.tutorialData.steps[scope.currentStep - 2].onLeaveHighlight;
        }
        if (onLeaveHighlightFunc) {
          onLeaveHighlightFunc();
        }
        data = scope.tutorialData.steps[scope.currentStep - 1];
        data = scope.tutorialData.steps[scope.currentStep - 1];
        return $timeout((function() {
          return scope.highlightElement(data);
        }), 50);
      };
      scope.previousStep = function() {
        var data, onLeaveHighlightFunc;
        scope.currentStep--;
        if (scope.currentStep === 0) {
          scope.currentStep++;
          return;
        }
        onLeaveHighlightFunc = scope.tutorialData.steps[scope.currentStep].onLeaveHighlight;
        if (onLeaveHighlightFunc) {
          onLeaveHighlightFunc();
        }
        scope.showTutorialBox = false;
        data = scope.tutorialData.steps[scope.currentStep - 1];
        return $timeout((function() {
          return scope.highlightElement(data);
        }), 50);
      };
      scope.asyncEnsureSpotInViewport = function(scrollTop, pHeight, spot, $mainContentWrapper) {
        var adjustedValues, animationOpts, bottomOfSpot, bottomOfViewport, deferred, scrollDuration, scrollTo;
        deferred = $q.defer();
        adjustedValues = {};
        scrollDuration = 500;
        bottomOfSpot = spot.y + (spot.radius * 2);
        bottomOfViewport = pHeight + scrollTop;
        animationOpts = {
          duration: scrollDuration,
          complete: function() {
            return deferred.resolve(adjustedValues);
          }
        };
        scrollTo = scrollTop;
        if (spot.y < 0) {
          adjustedValues.y = 0;
          scrollTo = scrollTop + spot.y;
        } else if (bottomOfSpot > pHeight) {
          adjustedValues.y = pHeight - (spot.radius * 2);
          scrollTo = scrollTop + (bottomOfSpot - pHeight);
        } else {
          animationOpts.duration = 0;
        }
        $mainContentWrapper.animate({
          scrollTop: scrollTo
        }, animationOpts);
        return deferred.promise;
      };
      scope.calculateSpotAdjustments = function(adjustments, tMidPtCoords, spot) {
        var adjustedSpot, align;
        if (adjustments.maxDiameter >= spot.dim) {
          return spot;
        }
        adjustedSpot = {};
        align = adjustments.align || "center";
        switch (align) {
          case "left":
            adjustedSpot.dim = adjustments.maxDiameter;
            adjustedSpot.radius = adjustments.maxDiameter / 2;
            adjustedSpot.x = spot.x;
            adjustedSpot.y = spot.y + ((spot.dim / 2) - (adjustments.maxDiameter / 2));
            break;
          case "center":
            adjustedSpot.dim = adjustments.maxDiameter;
            adjustedSpot.radius = adjustments.maxDiameter / 2;
            adjustedSpot.x = spot.x + ((spot.dim / 2) - (adjustments.maxDiameter / 2));
            adjustedSpot.y = spot.y + ((spot.dim / 2) - (adjustments.maxDiameter / 2));
            break;
          case "right":
            adjustedSpot.dim = adjustments.maxDiameter;
            adjustedSpot.radius = adjustments.maxDiameter / 2;
            adjustedSpot.x = spot.x + spot.dim - adjustments.maxDiameter;
            adjustedSpot.y = spot.y + ((spot.dim / 2) - (adjustments.maxDiameter / 2));
        }
        return adjustedSpot;
      };
      return scope.highlightElement = function(data) {
        var $mainContentWrapper, $page, $target, pHeight, pWidth, promiseForSpotInViewport, scrollTop, spot, spotPad, tHeight, tMidPtCoords, tOffsetX, tOffsetY, tRadius, tWidth;
        spotPad = 10;
        $target = $(data.selector).eq(0);
        $page = $($document);
        $mainContentWrapper = $(".main-app__header-and-content").eq(0);
        tWidth = $target.outerWidth();
        tHeight = $target.outerHeight();
        tOffsetX = $target.offset().left;
        tOffsetY = $target.offset().top;
        scrollTop = $mainContentWrapper.scrollTop();
        tMidPtCoords = {
          left: tOffsetX + (tWidth / 2),
          top: tOffsetY + (tHeight / 2)
        };
        pWidth = $page.width();
        pHeight = $page.height();
        tRadius = Math.sqrt(Math.pow(tWidth / 2, 2) + Math.pow(tHeight / 2, 2));
        spot = {};
        spot.radius = tRadius + spotPad;
        spot.dim = spot.radius * 2;
        spot.x = tMidPtCoords.left - spot.radius;
        spot.y = tMidPtCoords.top - spot.radius;
        if (data.adjustments) {
          spot = scope.calculateSpotAdjustments(data.adjustments, tMidPtCoords, spot);
        }
        promiseForSpotInViewport = scope.asyncEnsureSpotInViewport(scrollTop, pHeight, spot, $mainContentWrapper);
        return promiseForSpotInViewport.then(function(adjustedValues) {
          return $timeout(function() {
            var $boxBottom, $boxCenter, $boxLeft, $boxMiddleWrapper, $boxRight, $boxTop, boxBottomHeight, boxCenterHeight, boxLeftWidth, boxMiddleWrapperWidth, boxRightWidth, boxTopHeight, showContent;
            if (adjustedValues.y !== void 0) {
              spot.y = adjustedValues.y;
            }
            scope.showSpotlight = true;
            showContent = function() {
              scope.showTutorialBox = true;
              if (data.onHighlight) {
                return data.onHighlight();
              }
            };
            $timeout(showContent, 700);
            scope.tutorialTarget = {
              spot: spot,
              title: data.title,
              content: data.content
            };
            if (data.hideBack) {
              scope.tutorialTarget.hideBack = true;
            }
            boxLeftWidth = spot.x;
            boxMiddleWrapperWidth = spot.dim;
            boxTopHeight = spot.y;
            boxCenterHeight = spot.dim;
            boxBottomHeight = pHeight - boxCenterHeight - boxTopHeight;
            boxRightWidth = pWidth - boxMiddleWrapperWidth - boxLeftWidth;
            $boxLeft = elem.find(".it__box--left");
            $boxMiddleWrapper = elem.find(".it__box-middle-wrapper");
            $boxTop = elem.find(".it__box--top");
            $boxCenter = elem.find(".it__box--center");
            $boxBottom = elem.find(".it__box--bottom");
            $boxRight = elem.find(".it__box--right");
            $boxLeft.css("width", boxLeftWidth + "px");
            $boxMiddleWrapper.css("width", boxMiddleWrapperWidth + "px");
            $boxTop.css("height", boxTopHeight + "px");
            $boxBottom.css("height", boxBottomHeight + "px");
            $boxCenter.css("height", boxCenterHeight + "px");
            return $boxRight.css("width", boxRightWidth + "px");
          });
        });
      };
    }
  };
});