import angular from 'angular' import _ from 'lodash' import template from './tree.html' interface ITreeItem { children: ITreeItem[] collapsed: boolean } angular.module('app').directive('mflyTree', function mflyTab() { return { link($scope: ScopeKeyValuePair) { const lastActiveItems: any[] = [] // if we're given an initial active node, attempt to find and activate it. if ($scope.initialActiveNode) { $scope.initialActiveNode.active = true lastActiveItems.push($scope.initialActiveNode) // expand the tree to show the active node if ($scope.initialActiveNode !== $scope.treeItem) { expandToActiveNode($scope.treeItem.children, $scope.initialActiveNode) } } $scope.rootClicked = (_event) => { onNodeClickCallback($scope.treeItem, _event) } $scope.rootAddClicked = () => { onNodeAddButtonClickCallback($scope.treeItem) } $scope.$on('nodeClicked', (_event, data) => { onNodeClickCallback(data.clickedItem, data.event) }) $scope.$on('nodeAddClicked', (_event, data) => { onNodeAddButtonClickCallback(data.clickedItem) }) function onNodeAddButtonClickCallback(item) { $scope.onNodeAddButtonClick({ addedNode: item }) } function onNodeClickCallback(item, event) { // allow multi selecting if enabled by the component and user is holding shift const isMultiSelecting: boolean = $scope.allowMultiNodeSelection && event.shiftKey // when not multi-selecting current item if it's not being clicked if (!isMultiSelecting) { if (item !== $scope.treeItem) { $scope.treeItem.active = false } } // when not multi-selecting deactive all lastActive items if (!isMultiSelecting) { lastActiveItems.forEach(i => { // exception - do NOT deactive if you are clicking a branch(folder) in itemOnly mode if (!$scope.itemOnlySelection || !item.isBranch){ i.active = false } }) } // if not clicking at branch in itemOnly mode then push into lastactive and flip if (!$scope.itemOnlySelection || !item.isBranch) { lastActiveItems.push(item) item.active = !item.active } $scope.onNodeClick({ clickedNode: item, isMultiSelecting }) } function expandToActiveNode(nodes, nodeToFind) { const foundNode = _.find(nodes, nodeToFind) if (foundNode) { return foundNode } else { return _.map(nodes, (node: ITreeItem) => { if (node.children && node.children.length > 0) { node.collapsed = false return expandToActiveNode(node.children, nodeToFind) } }) } } }, restrict: 'E', scope: { allowMultiNodeSelection: '<', initialActiveNode: '=', itemOnlySelection: '<', itemsOnlyAddButtons: '<', onNodeAddButtonClick: '&?', onNodeClick: '&', treeItem: '=' }, template, } })