UNPKG

angular-gantt

Version:

Gantt chart component for AngularJS

471 lines (393 loc) 17.8 kB
/* Project: angular-gantt v1.2.9 - 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.tree', ['gantt', 'gantt.tree.templates', 'ui.tree']).directive('ganttTree', ['ganttUtils', '$compile', '$document', function(utils, $compile, $document) { // Provides the row sort functionality to any Gantt row // Uses the sortableState to share the current row return { restrict: 'E', require: '^gantt', scope: { enabled: '=?', header: '=?', content: '=?', headerContent: '=?', keepAncestorOnFilterRow: '=?' }, link: function(scope, element, attrs, ganttCtrl) { var api = ganttCtrl.gantt.api; // Load options from global options attribute. if (scope.options && typeof(scope.options.sortable) === 'object') { for (var option in scope.options.sortable) { scope[option] = scope.options[option]; } } if (scope.enabled === undefined) { scope.enabled = true; } if (scope.header === undefined) { scope.header = 'Name'; } if (scope.headerContent === undefined) { scope.headerContent = '{{getHeader()}}'; } if (scope.keepAncestorOnFilterRow === undefined) { scope.keepAncestorOnFilterRow = false; } api.directives.on.new(scope, function(directiveName, sideContentScope, sideContentElement) { if (directiveName === 'ganttSideContent') { var labelsScope = sideContentScope.$new(); labelsScope.pluginScope = scope; var ifElement = $document[0].createElement('div'); angular.element(ifElement).attr('data-ng-if', 'pluginScope.enabled'); angular.element(ifElement).addClass('side-element'); var labelsElement = $document[0].createElement('gantt-side-content-tree'); angular.element(ifElement).append(labelsElement); sideContentElement.append($compile(ifElement)(labelsScope)); } }); } }; }]); }()); (function(){ 'use strict'; angular.module('gantt.tree').directive('ganttRowTreeLabel', ['GanttDirectiveBuilder', function(Builder) { var builder = new Builder('ganttRowTreeLabel'); builder.restrict = 'A'; builder.templateUrl = undefined; return builder.build(); }]); }()); (function(){ 'use strict'; angular.module('gantt.tree').directive('ganttSideContentTree', ['GanttDirectiveBuilder', function(Builder) { var builder = new Builder('ganttSideContentTree', 'plugins/tree/sideContentTree.tmpl.html'); return builder.build(); }]); }()); (function(){ 'use strict'; angular.module('gantt.tree').controller('GanttTreeController', ['$scope', '$filter', 'GanttHierarchy', function($scope, $filter, Hierarchy) { $scope.rootRows = []; $scope.getHeader = function() { return $scope.pluginScope.header; }; var hierarchy = new Hierarchy(); $scope.pluginScope.$watchGroup(['keepAncestorOnFilterRow', 'enabled'], function(value) { var keepAncestor = value[0] && value[1]; if (keepAncestor) { var filterImpl = function(sortedRows, filterRow, filterRowComparator) { hierarchy.refresh(sortedRows); var leaves = []; angular.forEach(sortedRows, function(row) { var children = hierarchy.children(row); if (!children || children.length === 0) { leaves.push(row); } }); var filteredLeaves = $filter('filter')(leaves, filterRow, filterRowComparator); var filterRowKeepAncestor = function(row) { if (filteredLeaves.indexOf(row) > -1) { return true; } var descendants = hierarchy.descendants(row); for (var i=0; i < descendants.length; i++) { if (filteredLeaves.indexOf(descendants[i]) > -1) { return true; } } return false; }; return $filter('filter')(sortedRows, filterRowKeepAncestor, filterRowComparator); }; $scope.gantt.rowsManager.setFilterImpl(filterImpl); } else { $scope.gantt.rowsManager.setFilterImpl(false); } }); var isVisible = function(row) { var parentRow = $scope.parent(row); while (parentRow !== undefined) { if (parentRow !== undefined && parentRow._collapsed) { return false; } parentRow = $scope.parent(parentRow); } return true; }; var filterRowsFunction = function(rows) { return rows.filter(function(row) { return isVisible(row); }); }; var sortRowsFunction = function(rows) { var sortedRows = []; var rootRows = []; var hasParent = false; angular.forEach(rows, function(row) { var rowParent = $scope.parent(row); if (rowParent === undefined) { rootRows.push(row); } else { hasParent = true; } }); var handleChildren = function(row) { sortedRows.push(row); var children = $scope.children(row); if (children !== undefined && children.length > 0) { var sortedChildren = children.sort(function(a, b) { return rows.indexOf(a) - rows.indexOf(b); }); angular.forEach(sortedChildren, function(child) { handleChildren(child); }); } }; angular.forEach(rootRows, function(row) { handleChildren(row); }); return sortedRows; }; $scope.gantt.api.rows.addRowSorter(sortRowsFunction); $scope.gantt.api.rows.addRowFilter(filterRowsFunction); $scope.$on('$destroy', function() { $scope.gantt.api.rows.removeRowSorter(sortRowsFunction); $scope.gantt.api.rows.removeRowFilter(filterRowsFunction); }); var refresh = function() { $scope.rootRows = hierarchy.refresh($scope.gantt.rowsManager.filteredRows); if ($scope.gantt.rowsManager.filteredRows.length > 0) { $scope.gantt.api.rows.sort(); $scope.gantt.api.rows.refresh(); } }; $scope.gantt.api.rows.on.remove($scope, refresh); $scope.gantt.api.rows.on.add($scope, refresh); var isRowCollapsed = function(rowId) { var row; if (typeof rowId === 'string') { row = $scope.gantt.rowsManager.rowsMap[rowId]; } else { row = rowId; } if (row === undefined) { return undefined; } if (row._collapsed === undefined) { return false; } return row._collapsed; }; var expandRow = function(rowId) { var row; if (typeof rowId === 'string') { row = $scope.gantt.rowsManager.rowsMap[rowId]; } else { row = rowId; } if (row === undefined) { return; } var rowScope = $scope.nodeScopes[row.model.id]; if (rowScope.collapsed) { rowScope.toggle(); } }; var collapseRow = function(rowId) { var row; if (typeof rowId === 'string') { row = $scope.gantt.rowsManager.rowsMap[rowId]; } else { row = rowId; } if (row === undefined) { return; } var rowScope = $scope.nodeScopes[row.model.id]; if (!rowScope.collapsed) { rowScope.toggle(); } }; var getHierarchy = function() { return hierarchy; }; $scope.getHeaderContent = function() { return $scope.pluginScope.headerContent; }; $scope.gantt.api.registerMethod('tree', 'refresh', refresh, this); $scope.gantt.api.registerMethod('tree', 'isCollapsed', isRowCollapsed, this); $scope.gantt.api.registerMethod('tree', 'expand', expandRow, this); $scope.gantt.api.registerMethod('tree', 'collapse', collapseRow, this); $scope.gantt.api.registerEvent('tree', 'collapsed'); $scope.gantt.api.registerMethod('tree', 'getHierarchy', getHierarchy, this); $scope.$watchCollection('gantt.rowsManager.filteredRows', function() { refresh(); }); $scope.children = function(row) { if (row === undefined) { return $scope.rootRows; } return hierarchy.children(row); }; $scope.parent = function(row) { return hierarchy.parent(row); }; $scope.nodeScopes = {}; }]).controller('GanttUiTreeController', ['$scope', function($scope) { var collapseAll = function() { $scope.collapseAll(); }; var expandAll = function() { $scope.expandAll(); }; $scope.gantt.api.registerMethod('tree', 'collapseAll', collapseAll, $scope); $scope.gantt.api.registerMethod('tree', 'expandAll', expandAll, $scope); }]).controller('GanttTreeNodeController', ['$scope', function($scope) { $scope.$parent.nodeScopes[$scope.row.model.id] = $scope; $scope.$on('$destroy', function() { delete $scope.$parent.nodeScopes[$scope.row.model.id]; }); $scope.$watch('children(row)', function(newValue) { if (newValue) { // Children rows may have been filtered out // So we need to filter the raw hierarchy before displaying children in tree. var visibleRows = $scope.row.rowsManager.filteredRows; var filteredChildrenRows = []; for (var i=0; i < newValue.length; i++) { var childRow = newValue[i]; if (visibleRows.indexOf(childRow) > -1) { filteredChildrenRows.push(childRow); } } $scope.$parent.childrenRows = filteredChildrenRows; } else { $scope.$parent.childrenRows = newValue; } }); $scope.isCollapseDisabled = function(){ return !$scope.$parent.childrenRows || $scope.$parent.childrenRows.length === 0; }; $scope.getValue = function() { return $scope.row.model.name; }; $scope.getRowContent = function() { if ($scope.row.model.content !== undefined) { return $scope.row.model.content; } if ($scope.pluginScope.content !== undefined) { return $scope.pluginScope.content; } var content = $scope.row.rowsManager.gantt.options.value('rowContent'); if (content === undefined) { content = '{{row.model.name}}'; } return content; }; $scope.$watch('collapsed', function(newValue) { if ($scope.$modelValue._collapsed !== newValue) { var oldValue = $scope.$modelValue._collapsed; $scope.$modelValue._collapsed = newValue; // $modelValue contains the Row object if (oldValue !== undefined && newValue !== oldValue) { $scope.gantt.api.tree.raise.collapsed($scope, $scope.$modelValue, newValue); $scope.gantt.api.rows.refresh(); } } }); }]); }()); (function(){ 'use strict'; angular.module('gantt.tree').directive('ganttTreeBody', ['GanttDirectiveBuilder', 'ganttLayout', function(Builder, layout) { var builder = new Builder('ganttTreeBody', 'plugins/tree/treeBody.tmpl.html'); builder.controller = function($scope) { var hScrollBarHeight = layout.getScrollBarHeight(); $scope.getLabelsCss = function() { var css = {}; if ($scope.maxHeight) { var bodyScrollBarHeight = $scope.gantt.scroll.isHScrollbarVisible() ? hScrollBarHeight : 0; css['max-height'] = $scope.maxHeight - bodyScrollBarHeight - $scope.gantt.header.getHeight() + 'px'; } return css; }; }; return builder.build(); }]); }()); (function(){ 'use strict'; angular.module('gantt.tree').directive('ganttTreeHeader', ['GanttDirectiveBuilder', function(Builder) { var builder = new Builder('ganttTreeHeader', 'plugins/tree/treeHeader.tmpl.html'); return builder.build(); }]); }()); angular.module('gantt.tree.templates', []).run(['$templateCache', function($templateCache) { $templateCache.put('plugins/tree/sideContentTree.tmpl.html', '<div class="gantt-side-content-tree" ng-controller="GanttTreeController">\n' + ' <gantt-tree-header>\n' + ' </gantt-tree-header>\n' + ' <gantt-tree-body>\n' + ' </gantt-tree-body>\n' + '</div>\n' + ''); $templateCache.put('plugins/tree/treeBody.tmpl.html', '<div class="gantt-tree-body" ng-style="getLabelsCss()">\n' + ' <div gantt-vertical-scroll-receiver>\n' + ' <div class="gantt-row-label-background">\n' + ' <div class="gantt-row-label gantt-row-height"\n' + ' ng-class="row.model.classes"\n' + ' ng-style="{\'height\': row.model.height}"\n' + ' ng-repeat="row in gantt.rowsManager.visibleRows track by row.model.id">\n' + ' &nbsp;\n' + ' </div>\n' + ' </div>\n' + ' <div ui-tree ng-controller="GanttUiTreeController" data-drag-enabled="false" data-empty-place-holder-enabled="false">\n' + ' <ol class="gantt-tree-root" ui-tree-nodes ng-model="rootRows">\n' + ' <li ng-repeat="row in rootRows" ui-tree-node\n' + ' ng-include="\'plugins/tree/treeBodyChildren.tmpl.html\'">\n' + ' </li>\n' + ' </ol>\n' + ' </div>\n' + ' </div>\n' + '</div>\n' + ''); $templateCache.put('plugins/tree/treeBodyChildren.tmpl.html', '<div ng-controller="GanttTreeNodeController"\n' + ' class="gantt-row-label gantt-row-height"\n' + ' ng-class="row.model.classes"\n' + ' ng-style="{\'height\': row.model.height}">\n' + ' <div class="gantt-valign-container">\n' + ' <div class="gantt-valign-content">\n' + ' <a ng-disabled="isCollapseDisabled()" data-nodrag\n' + ' class="gantt-tree-handle-button btn btn-xs"\n' + ' ng-class="{\'gantt-tree-collapsed\': collapsed, \'gantt-tree-expanded\': !collapsed}"\n' + ' ng-click="!isCollapseDisabled() && toggle()"><span\n' + ' class="gantt-tree-handle glyphicon glyphicon-chevron-down"\n' + ' ng-class="{\n' + ' \'glyphicon-chevron-right\': collapsed, \'glyphicon-chevron-down\': !collapsed,\n' + ' \'gantt-tree-collapsed\': collapsed, \'gantt-tree-expanded\': !collapsed}"></span>\n' + ' </a>\n' + ' <span gantt-row-label class="gantt-label-text" gantt-bind-compile-html="getRowContent()"/>\n' + ' </div>\n' + ' </div>\n' + '</div>\n' + '<ol ui-tree-nodes ng-class="{hidden: collapsed}" ng-model="childrenRows">\n' + ' <li ng-repeat="row in childrenRows" ui-tree-node>\n' + ' <div ng-include="\'plugins/tree/treeBodyChildren.tmpl.html\'"></div>\n' + ' </li>\n' + '</ol>\n' + ''); $templateCache.put('plugins/tree/treeHeader.tmpl.html', '<div class="gantt-tree-header" ng-style="{height: $parent.ganttHeaderHeight + \'px\'}">\n' + ' <div ng-if="$parent.ganttHeaderHeight" class="gantt-row-label gantt-row-label-header gantt-tree-row gantt-tree-header-row"><span class="gantt-label-text" gantt-bind-compile-html="getHeaderContent()"/></div>\n' + '</div>\n' + ''); }]); //# sourceMappingURL=angular-gantt-tree-plugin.js.map