/* Project: angular-gantt v1.3.3 - Gantt chart component for AngularJS Authors: Marco Schweighauser, RĂ©mi Alvergnat License: MIT Homepage: https://www.angular-gantt.com Github: https://github.com/angular-gantt/angular-gantt.git */ (function(){ 'use strict'; angular.module('gantt.tooltips', ['gantt', 'gantt.tooltips.templates']).directive('ganttTooltips', ['$compile', '$document', function($compile, $document) { return { restrict: 'E', require: '^gantt', scope: { enabled: '=?', dateFormat: '=?', content: '=?', delay: '=?' }, link: function(scope, element, attrs, ganttCtrl) { var api = ganttCtrl.gantt.api; // Load options from global options attribute. if (scope.options && typeof(scope.options.tooltips) === 'object') { for (var option in scope.options.tooltips) { scope[option] = scope.options.tooltips[option]; } } if (scope.enabled === undefined) { scope.enabled = true; } if (scope.dateFormat === undefined) { scope.dateFormat = 'MMM DD, HH:mm'; } if (scope.delay === undefined) { scope.delay = 500; } if (scope.content === undefined) { scope.content = '{{task.model.name}}'+ ''+ '{{task.isMilestone() === true && getFromLabel() || getFromLabel() + \' - \' + getToLabel()}}'+ ''; } scope.api = api; api.directives.on.new(scope, function(directiveName, taskScope, taskElement) { if (directiveName === 'ganttTask') { var tooltipScope = taskScope.$new(); tooltipScope.pluginScope = scope; var ifElement = $document[0].createElement('div'); angular.element(ifElement).attr('data-ng-if', 'pluginScope.enabled'); var tooltipElement = $document[0].createElement('gantt-tooltip'); if (attrs.templateUrl !== undefined) { angular.element(tooltipElement).attr('data-template-url', attrs.templateUrl); } if (attrs.template !== undefined) { angular.element(tooltipElement).attr('data-template', attrs.template); } angular.element(ifElement).append(tooltipElement); taskElement.append($compile(ifElement)(tooltipScope)); } }); } }; }]); }()); (function() { 'use strict'; angular.module('gantt.tooltips').directive('ganttTooltip', ['$log','$timeout', '$compile', '$document', '$templateCache', 'ganttDebounce', 'ganttSmartEvent', function($log, $timeout, $compile, $document, $templateCache, debounce, smartEvent) { // This tooltip displays more information about a task return { restrict: 'E', templateUrl: function(tElement, tAttrs) { var templateUrl; if (tAttrs.templateUrl === undefined) { templateUrl = 'plugins/tooltips/tooltip.tmpl.html'; } else { templateUrl = tAttrs.templateUrl; } if (tAttrs.template !== undefined) { $templateCache.put(templateUrl, tAttrs.template); } return templateUrl; }, scope: true, replace: true, controller: ['$scope', '$element', 'ganttUtils', function($scope, $element, utils) { var bodyElement = angular.element($document[0].body); var parentElement = $scope.task.$element; var showTooltipPromise; var visible = false; var mouseEnterX; var mouseMoveHandler; var getViewPortWidth = function() { var d = $document[0]; return d.documentElement.clientWidth || d.documentElement.getElementById('body')[0].clientWidth; }; var updateTooltip = function(x) { // Check if info is overlapping with view port if (x + $element[0].offsetWidth > getViewPortWidth()) { $element.css('left', (x + 20 - $element[0].offsetWidth) + 'px'); $scope.isRightAligned = true; } else { $element.css('left', (x - 20) + 'px'); $scope.isRightAligned = false; } }; var showTooltip = function(x) { visible = true; mouseMoveHandler.bind(); $scope.displayed = true; $scope.$evalAsync(function() { var restoreNgHide; if ($element.hasClass('ng-hide')) { $element.removeClass('ng-hide'); restoreNgHide = true; } $scope.elementHeight = $element[0].offsetHeight; if (restoreNgHide) { $element.addClass('ng-hide'); } $scope.taskRect = parentElement[0].getBoundingClientRect(); updateTooltip(x); }); }; var hideTooltip = function() { visible = false; mouseMoveHandler.unbind(); $scope.$evalAsync(function() { $scope.displayed = false; }); }; var displayTooltip = function(newValue, showDelayed) { if (showTooltipPromise) { $timeout.cancel(showTooltipPromise); } var taskTooltips = $scope.task.model.tooltips; var rowTooltips = $scope.task.row.model.tooltips; if (typeof(taskTooltips) === 'boolean') { taskTooltips = {enabled: taskTooltips}; } if (typeof(rowTooltips) === 'boolean') { rowTooltips = {enabled: rowTooltips}; } var enabled = utils.firstProperty([taskTooltips, rowTooltips], 'enabled', $scope.pluginScope.enabled); if (enabled && !visible && mouseEnterX !== undefined && newValue) { var content = utils.firstProperty([taskTooltips, rowTooltips], 'content', $scope.pluginScope.content); $scope.content = content; if (showDelayed) { showTooltipPromise = $timeout(function() { showTooltip(mouseEnterX); }, $scope.pluginScope.delay, false); } else { showTooltip(mouseEnterX); } } else if (!newValue) { if (!$scope.task.active) { hideTooltip(); } } }; mouseMoveHandler = smartEvent($scope, bodyElement, 'mousemove', debounce(function(e) { if (!visible) { mouseEnterX = e.clientX; displayTooltip(true, false); } else { // check if mouse goes outside the parent if( !$scope.taskRect || e.clientX < $scope.taskRect.left || e.clientX > $scope.taskRect.right || e.clientY > $scope.taskRect.bottom || e.clientY < $scope.taskRect.top ) { displayTooltip(false, false); } updateTooltip(e.clientX); } }, 5, false)); $scope.getFromLabel = function() { var taskTooltips = $scope.task.model.tooltips; var rowTooltips = $scope.task.row.model.tooltips; if (typeof(taskTooltips) === 'boolean') { taskTooltips = {enabled: taskTooltips}; } if (typeof(rowTooltips) === 'boolean') { rowTooltips = {enabled: rowTooltips}; } var dateFormat = utils.firstProperty([taskTooltips, rowTooltips], 'dateFormat', $scope.pluginScope.dateFormat); return $scope.task.model.from.format(dateFormat); }; $scope.getToLabel = function() { var taskTooltips = $scope.task.model.tooltips; var rowTooltips = $scope.task.row.model.tooltips; if (typeof(taskTooltips) === 'boolean') { taskTooltips = {enabled: taskTooltips}; } if (typeof(rowTooltips) === 'boolean') { rowTooltips = {enabled: rowTooltips}; } var dateFormat = utils.firstProperty([taskTooltips, rowTooltips], 'dateFormat', $scope.pluginScope.dateFormat); return $scope.task.model.to.format(dateFormat); }; $scope.task.getContentElement().bind('mousemove', function(evt) { mouseEnterX = evt.clientX; }); $scope.task.getContentElement().bind('mouseenter', function(evt) { mouseEnterX = evt.clientX; displayTooltip(true, true); }); $scope.task.getContentElement().bind('mouseleave', function() { displayTooltip(false); }); if ($scope.pluginScope.api.tasks.on.moveBegin) { $scope.pluginScope.api.tasks.on.moveBegin($scope, function(task) { if (task === $scope.task) { displayTooltip(true); } }); $scope.pluginScope.api.tasks.on.moveEnd($scope, function(task) { if (task === $scope.task) { displayTooltip(false); } }); $scope.pluginScope.api.tasks.on.resizeBegin($scope, function(task) { if (task === $scope.task) { displayTooltip(true); } }); $scope.pluginScope.api.tasks.on.resizeEnd($scope, function(task) { if (task === $scope.task) { displayTooltip(false); } }); } if ($scope.task.isMoving) { // Display tooltip because task has been moved to a new row displayTooltip(true, false); } $scope.gantt.api.directives.raise.new('ganttTooltip', $scope, $element); $scope.$on('$destroy', function() { $scope.gantt.api.directives.raise.destroy('ganttTooltip', $scope, $element); }); }] }; }]); }()); angular.module('gantt.tooltips.templates', []).run(['$templateCache', function ($templateCache) { $templateCache.put('plugins/tooltips/tooltip.tmpl.html', '