@circlon/angular-tree-component
Version:
A simple yet powerful tree component for Angular
1,287 lines (1,279 loc) • 91.2 kB
JavaScript
import { Directive, TemplateRef, ViewContainerRef, Input, Injectable, ɵɵdefineInjectable, Component, ViewEncapsulation, ElementRef, EventEmitter, ContentChild, ViewChild, Output, HostListener, Renderer2, NgZone, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { autorun, reaction, computed as computed$1, observable as observable$1, action as action$1 } from 'mobx';
class TreeMobxAutorunDirective {
constructor(templateRef, viewContainer) {
this.templateRef = templateRef;
this.viewContainer = viewContainer;
this.templateBindings = {};
}
ngOnInit() {
this.view = this.viewContainer.createEmbeddedView(this.templateRef);
if (this.dispose) {
this.dispose();
}
if (this.shouldDetach()) {
this.view.detach();
}
this.autoDetect(this.view);
}
shouldDetach() {
return this.treeMobxAutorun && this.treeMobxAutorun.detach;
}
autoDetect(view) {
this.dispose = autorun(() => view.detectChanges());
}
ngOnDestroy() {
if (this.dispose) {
this.dispose();
}
}
}
TreeMobxAutorunDirective.decorators = [
{ type: Directive, args: [{ selector: '[treeMobxAutorun]' },] }
];
/** @nocollapse */
TreeMobxAutorunDirective.ctorParameters = () => [
{ type: TemplateRef },
{ type: ViewContainerRef }
];
TreeMobxAutorunDirective.propDecorators = {
treeMobxAutorun: [{ type: Input }]
};
const KEYS = {
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
ENTER: 13,
SPACE: 32,
CONTEXT_MENU: 32
};
const ɵ0 = (tree, node, $event) => node && node.toggleActivated(), ɵ1 = (tree, node, $event) => node && node.toggleActivated(true), ɵ2 = (tree, node, $event) => node && node.toggleSelected(), ɵ3 = (tree, node, $event) => node.setIsActive(true), ɵ4 = (tree, node, $event) => node.setIsActive(false), ɵ5 = (tree, node, $event) => node.setIsSelected(true), ɵ6 = (tree, node, $event) => node.setIsSelected(false), ɵ7 = (tree, node, $event) => node.focus(), ɵ8 = (tree, node, $event) => node.hasChildren && node.toggleExpanded(), ɵ9 = (tree, node, $event) => node.expand(), ɵ10 = (tree, node, $event) => node.collapse(), ɵ11 = (tree, node, $event) => tree.focusDrillDown(), ɵ12 = (tree, node, $event) => tree.focusDrillUp(), ɵ13 = (tree, node, $event) => tree.focusNextNode(), ɵ14 = (tree, node, $event) => tree.focusPreviousNode(), ɵ15 = (tree, node, $event, { from, to }) => {
// default action assumes from = node, to = {parent, index}
if ($event.ctrlKey) {
tree.copyNode(from, to);
}
else {
tree.moveNode(from, to);
}
};
const TREE_ACTIONS = {
TOGGLE_ACTIVE: ɵ0,
TOGGLE_ACTIVE_MULTI: ɵ1,
TOGGLE_SELECTED: ɵ2,
ACTIVATE: ɵ3,
DEACTIVATE: ɵ4,
SELECT: ɵ5,
DESELECT: ɵ6,
FOCUS: ɵ7,
TOGGLE_EXPANDED: ɵ8,
EXPAND: ɵ9,
COLLAPSE: ɵ10,
DRILL_DOWN: ɵ11,
DRILL_UP: ɵ12,
NEXT_NODE: ɵ13,
PREVIOUS_NODE: ɵ14,
MOVE_NODE: ɵ15
};
const defaultActionMapping = {
mouse: {
click: TREE_ACTIONS.TOGGLE_ACTIVE,
dblClick: null,
contextMenu: null,
expanderClick: TREE_ACTIONS.TOGGLE_EXPANDED,
checkboxClick: TREE_ACTIONS.TOGGLE_SELECTED,
drop: TREE_ACTIONS.MOVE_NODE
},
keys: {
[KEYS.RIGHT]: TREE_ACTIONS.DRILL_DOWN,
[KEYS.LEFT]: TREE_ACTIONS.DRILL_UP,
[KEYS.DOWN]: TREE_ACTIONS.NEXT_NODE,
[KEYS.UP]: TREE_ACTIONS.PREVIOUS_NODE,
[KEYS.SPACE]: TREE_ACTIONS.TOGGLE_ACTIVE,
[KEYS.ENTER]: TREE_ACTIONS.TOGGLE_ACTIVE
}
};
class TreeOptions {
constructor(options = {}) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35;
this.options = options;
this.actionMapping = {
mouse: {
click: (_d = (_c = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.actionMapping) === null || _b === void 0 ? void 0 : _b.mouse) === null || _c === void 0 ? void 0 : _c.click) !== null && _d !== void 0 ? _d : defaultActionMapping.mouse.click,
dblClick: (_h = (_g = (_f = (_e = this.options) === null || _e === void 0 ? void 0 : _e.actionMapping) === null || _f === void 0 ? void 0 : _f.mouse) === null || _g === void 0 ? void 0 : _g.dblClick) !== null && _h !== void 0 ? _h : defaultActionMapping.mouse.dblClick,
contextMenu: (_m = (_l = (_k = (_j = this.options) === null || _j === void 0 ? void 0 : _j.actionMapping) === null || _k === void 0 ? void 0 : _k.mouse) === null || _l === void 0 ? void 0 : _l.contextMenu) !== null && _m !== void 0 ? _m : defaultActionMapping.mouse.contextMenu,
expanderClick: (_r = (_q = (_p = (_o = this.options) === null || _o === void 0 ? void 0 : _o.actionMapping) === null || _p === void 0 ? void 0 : _p.mouse) === null || _q === void 0 ? void 0 : _q.expanderClick) !== null && _r !== void 0 ? _r : defaultActionMapping.mouse.expanderClick,
checkboxClick: (_v = (_u = (_t = (_s = this.options) === null || _s === void 0 ? void 0 : _s.actionMapping) === null || _t === void 0 ? void 0 : _t.mouse) === null || _u === void 0 ? void 0 : _u.checkboxClick) !== null && _v !== void 0 ? _v : defaultActionMapping.mouse.checkboxClick,
drop: (_z = (_y = (_x = (_w = this.options) === null || _w === void 0 ? void 0 : _w.actionMapping) === null || _x === void 0 ? void 0 : _x.mouse) === null || _y === void 0 ? void 0 : _y.drop) !== null && _z !== void 0 ? _z : defaultActionMapping.mouse.drop,
dragStart: (_3 = (_2 = (_1 = (_0 = this.options) === null || _0 === void 0 ? void 0 : _0.actionMapping) === null || _1 === void 0 ? void 0 : _1.mouse) === null || _2 === void 0 ? void 0 : _2.dragStart) !== null && _3 !== void 0 ? _3 : undefined,
drag: (_7 = (_6 = (_5 = (_4 = this.options) === null || _4 === void 0 ? void 0 : _4.actionMapping) === null || _5 === void 0 ? void 0 : _5.mouse) === null || _6 === void 0 ? void 0 : _6.drag) !== null && _7 !== void 0 ? _7 : undefined,
dragEnd: (_11 = (_10 = (_9 = (_8 = this.options) === null || _8 === void 0 ? void 0 : _8.actionMapping) === null || _9 === void 0 ? void 0 : _9.mouse) === null || _10 === void 0 ? void 0 : _10.dragEnd) !== null && _11 !== void 0 ? _11 : undefined,
dragOver: (_15 = (_14 = (_13 = (_12 = this.options) === null || _12 === void 0 ? void 0 : _12.actionMapping) === null || _13 === void 0 ? void 0 : _13.mouse) === null || _14 === void 0 ? void 0 : _14.dragOver) !== null && _15 !== void 0 ? _15 : undefined,
dragLeave: (_19 = (_18 = (_17 = (_16 = this.options) === null || _16 === void 0 ? void 0 : _16.actionMapping) === null || _17 === void 0 ? void 0 : _17.mouse) === null || _18 === void 0 ? void 0 : _18.dragLeave) !== null && _19 !== void 0 ? _19 : undefined,
dragEnter: (_23 = (_22 = (_21 = (_20 = this.options) === null || _20 === void 0 ? void 0 : _20.actionMapping) === null || _21 === void 0 ? void 0 : _21.mouse) === null || _22 === void 0 ? void 0 : _22.dragEnter) !== null && _23 !== void 0 ? _23 : undefined,
mouseOver: (_27 = (_26 = (_25 = (_24 = this.options) === null || _24 === void 0 ? void 0 : _24.actionMapping) === null || _25 === void 0 ? void 0 : _25.mouse) === null || _26 === void 0 ? void 0 : _26.mouseOver) !== null && _27 !== void 0 ? _27 : undefined,
mouseOut: (_31 = (_30 = (_29 = (_28 = this.options) === null || _28 === void 0 ? void 0 : _28.actionMapping) === null || _29 === void 0 ? void 0 : _29.mouse) === null || _30 === void 0 ? void 0 : _30.mouseOut) !== null && _31 !== void 0 ? _31 : undefined,
},
keys: {
[KEYS.RIGHT]: TREE_ACTIONS.DRILL_DOWN,
[KEYS.LEFT]: TREE_ACTIONS.DRILL_UP,
[KEYS.DOWN]: TREE_ACTIONS.NEXT_NODE,
[KEYS.UP]: TREE_ACTIONS.PREVIOUS_NODE,
[KEYS.SPACE]: TREE_ACTIONS.TOGGLE_ACTIVE,
[KEYS.ENTER]: TREE_ACTIONS.TOGGLE_ACTIVE
}
};
if ((_33 = (_32 = this.options) === null || _32 === void 0 ? void 0 : _32.actionMapping) === null || _33 === void 0 ? void 0 : _33.keys) {
this.actionMapping.keys = Object.assign(Object.assign({}, this.actionMapping.keys), this.options.actionMapping.keys);
}
if (options.rtl) {
this.actionMapping.keys[KEYS.RIGHT] = ((_34 = options.actionMapping) === null || _34 === void 0 ? void 0 : _34.keys[KEYS.RIGHT]) || TREE_ACTIONS.DRILL_UP;
this.actionMapping.keys[KEYS.LEFT] = ((_35 = options.actionMapping) === null || _35 === void 0 ? void 0 : _35.keys[KEYS.LEFT]) || TREE_ACTIONS.DRILL_DOWN;
}
}
get hasChildrenField() { return this.options.hasChildrenField || 'hasChildren'; }
get childrenField() { return this.options.childrenField || 'children'; }
get displayField() { return this.options.displayField || 'name'; }
get idField() { return this.options.idField || 'id'; }
get isExpandedField() { return this.options.isExpandedField || 'isExpanded'; }
get getChildren() { return this.options.getChildren; }
get levelPadding() { return this.options.levelPadding || 0; }
get useVirtualScroll() { return this.options.useVirtualScroll; }
get animateExpand() { return this.options.animateExpand; }
get animateSpeed() { return this.options.animateSpeed || 1; }
get animateAcceleration() { return this.options.animateAcceleration || 1.2; }
get scrollOnActivate() { return this.options.scrollOnActivate === undefined ? true : this.options.scrollOnActivate; }
get rtl() { return !!this.options.rtl; }
get rootId() { return this.options.rootId; }
get useCheckbox() { return this.options.useCheckbox; }
get useTriState() { return this.options.useTriState === undefined ? true : this.options.useTriState; }
get scrollContainer() { return this.options.scrollContainer; }
get allowDragoverStyling() { return this.options.allowDragoverStyling === undefined ? true : this.options.allowDragoverStyling; }
getNodeClone(node) {
if (this.options.getNodeClone) {
return this.options.getNodeClone(node);
}
// remove id from clone
// keeping ie11 compatibility
const nodeClone = Object.assign({}, node.data);
if (nodeClone.id) {
delete nodeClone.id;
}
return nodeClone;
}
allowDrop(element, to, $event) {
if (this.options.allowDrop instanceof Function) {
return this.options.allowDrop(element, to, $event);
}
else {
return this.options.allowDrop === undefined ? true : this.options.allowDrop;
}
}
allowDrag(node) {
if (this.options.allowDrag instanceof Function) {
return this.options.allowDrag(node);
}
else {
return this.options.allowDrag;
}
}
nodeClass(node) {
return this.options.nodeClass ? this.options.nodeClass(node) : '';
}
nodeHeight(node) {
if (node.data.virtual) {
return 0;
}
let nodeHeight = this.options.nodeHeight || 22;
if (typeof nodeHeight === 'function') {
nodeHeight = nodeHeight(node);
}
// account for drop slots:
return nodeHeight + (node.index === 0 ? 2 : 1) * this.dropSlotHeight;
}
get dropSlotHeight() {
return typeof this.options.dropSlotHeight === 'number' ? this.options.dropSlotHeight : 2;
}
}
const TREE_EVENTS = {
toggleExpanded: 'toggleExpanded',
activate: 'activate',
deactivate: 'deactivate',
nodeActivate: 'nodeActivate',
nodeDeactivate: 'nodeDeactivate',
select: 'select',
deselect: 'deselect',
focus: 'focus',
blur: 'blur',
initialized: 'initialized',
updateData: 'updateData',
moveNode: 'moveNode',
copyNode: 'copyNode',
event: 'event',
loadNodeChildren: 'loadNodeChildren',
changeFilter: 'changeFilter',
stateChange: 'stateChange'
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
class TreeNode {
constructor(data, parent, treeModel, index) {
this.data = data;
this.parent = parent;
this.treeModel = treeModel;
this.position = 0;
this.allowDrop = (element, $event) => {
return this.options.allowDrop(element, { parent: this, index: 0 }, $event);
};
this.allowDragoverStyling = () => {
return this.options.allowDragoverStyling;
};
if (this.id === undefined || this.id === null) {
this.id = uuid();
} // Make sure there's a unique id without overriding existing ids to work with immutable data structures
this.index = index;
if (this.getField('children')) {
this._initChildren();
}
this.autoLoadChildren();
}
get isHidden() { return this.treeModel.isHidden(this); }
;
get isExpanded() { return this.treeModel.isExpanded(this); }
;
get isActive() { return this.treeModel.isActive(this); }
;
get isFocused() { return this.treeModel.isNodeFocused(this); }
;
get isSelected() {
if (this.isSelectable()) {
return this.treeModel.isSelected(this);
}
else {
return this.children.some((node) => node.isSelected);
}
}
;
get isAllSelected() {
if (this.isSelectable()) {
return this.treeModel.isSelected(this);
}
else {
return this.children.every((node) => node.isAllSelected);
}
}
;
get isPartiallySelected() {
return this.isSelected && !this.isAllSelected;
}
get level() {
return this.parent ? this.parent.level + 1 : 0;
}
get path() {
return this.parent ? [...this.parent.path, this.id] : [];
}
get elementRef() {
throw `Element Ref is no longer supported since introducing virtual scroll\n
You may use a template to obtain a reference to the element`;
}
get originalNode() { return this._originalNode; }
;
// helper get functions:
get hasChildren() {
return !!(this.getField('hasChildren') || (this.children && this.children.length > 0));
}
get isCollapsed() { return !this.isExpanded; }
get isLeaf() { return !this.hasChildren; }
get isRoot() { return this.parent.data.virtual; }
get realParent() { return this.isRoot ? null : this.parent; }
// proxy functions:
get options() { return this.treeModel.options; }
fireEvent(event) { this.treeModel.fireEvent(event); }
// field accessors:
get displayField() {
return this.getField('display');
}
get id() {
return this.getField('id');
}
set id(value) {
this.setField('id', value);
}
getField(key) {
return this.data[this.options[`${key}Field`]];
}
setField(key, value) {
this.data[this.options[`${key}Field`]] = value;
}
// traversing:
_findAdjacentSibling(steps, skipHidden = false) {
const siblings = this._getParentsChildren(skipHidden);
const index = siblings.indexOf(this);
return siblings.length > index + steps ? siblings[index + steps] : null;
}
findNextSibling(skipHidden = false) {
return this._findAdjacentSibling(+1, skipHidden);
}
findPreviousSibling(skipHidden = false) {
return this._findAdjacentSibling(-1, skipHidden);
}
getVisibleChildren() {
return this.visibleChildren;
}
get visibleChildren() {
return (this.children || []).filter((node) => !node.isHidden);
}
getFirstChild(skipHidden = false) {
let children = skipHidden ? this.visibleChildren : this.children;
return children != null && children.length ? children[0] : null;
}
getLastChild(skipHidden = false) {
let children = skipHidden ? this.visibleChildren : this.children;
return children != null && children.length ? children[children.length - 1] : null;
}
findNextNode(goInside = true, skipHidden = false) {
return goInside && this.isExpanded && this.getFirstChild(skipHidden) ||
this.findNextSibling(skipHidden) ||
this.parent && this.parent.findNextNode(false, skipHidden);
}
findPreviousNode(skipHidden = false) {
let previousSibling = this.findPreviousSibling(skipHidden);
if (!previousSibling) {
return this.realParent;
}
return previousSibling._getLastOpenDescendant(skipHidden);
}
_getLastOpenDescendant(skipHidden = false) {
const lastChild = this.getLastChild(skipHidden);
return (this.isCollapsed || !lastChild)
? this
: lastChild._getLastOpenDescendant(skipHidden);
}
_getParentsChildren(skipHidden = false) {
const children = this.parent &&
(skipHidden ? this.parent.getVisibleChildren() : this.parent.children);
return children || [];
}
getIndexInParent(skipHidden = false) {
return this._getParentsChildren(skipHidden).indexOf(this);
}
isDescendantOf(node) {
if (this === node)
return true;
else
return this.parent && this.parent.isDescendantOf(node);
}
getNodePadding() {
return this.options.levelPadding * (this.level - 1) + 'px';
}
getClass() {
return [this.options.nodeClass(this), `tree-node-level-${this.level}`].join(' ');
}
onDrop($event) {
this.mouseAction('drop', $event.event, {
from: $event.element,
to: { parent: this, index: 0, dropOnNode: true }
});
}
allowDrag() {
return this.options.allowDrag(this);
}
// helper methods:
loadNodeChildren() {
if (!this.options.getChildren) {
return Promise.resolve(); // Not getChildren method - for using redux
}
return Promise.resolve(this.options.getChildren(this))
.then((children) => {
if (children) {
this.setField('children', children);
this._initChildren();
if (this.options.useTriState && this.treeModel.isSelected(this)) {
this.setIsSelected(true);
}
this.children.forEach((child) => {
if (child.getField('isExpanded') && child.hasChildren) {
child.expand();
}
});
}
}).then(() => {
this.fireEvent({
eventName: TREE_EVENTS.loadNodeChildren,
node: this
});
});
}
expand() {
if (!this.isExpanded) {
this.toggleExpanded();
}
return this;
}
collapse() {
if (this.isExpanded) {
this.toggleExpanded();
}
return this;
}
doForAll(fn) {
Promise.resolve(fn(this)).then(() => {
if (this.children) {
this.children.forEach((child) => child.doForAll(fn));
}
});
}
expandAll() {
this.doForAll((node) => node.expand());
}
collapseAll() {
this.doForAll((node) => node.collapse());
}
ensureVisible() {
if (this.realParent) {
this.realParent.expand();
this.realParent.ensureVisible();
}
return this;
}
toggleExpanded() {
this.setIsExpanded(!this.isExpanded);
return this;
}
setIsExpanded(value) {
if (this.hasChildren) {
this.treeModel.setExpandedNode(this, value);
}
return this;
}
;
autoLoadChildren() {
this.handler =
reaction(() => this.isExpanded, (isExpanded) => {
if (!this.children && this.hasChildren && isExpanded) {
this.loadNodeChildren();
}
}, { fireImmediately: true });
}
dispose() {
if (this.children) {
this.children.forEach((child) => child.dispose());
}
if (this.handler) {
this.handler();
}
this.parent = null;
this.children = null;
}
setIsActive(value, multi = false) {
this.treeModel.setActiveNode(this, value, multi);
if (value) {
this.focus(this.options.scrollOnActivate);
}
return this;
}
isSelectable() {
return this.isLeaf || !this.children || !this.options.useTriState;
}
setIsSelected(value) {
if (this.isSelectable()) {
this.treeModel.setSelectedNode(this, value);
}
else {
this.visibleChildren.forEach((child) => child.setIsSelected(value));
}
return this;
}
toggleSelected() {
this.setIsSelected(!this.isSelected);
return this;
}
toggleActivated(multi = false) {
this.setIsActive(!this.isActive, multi);
return this;
}
setActiveAndVisible(multi = false) {
this.setIsActive(true, multi)
.ensureVisible();
setTimeout(this.scrollIntoView.bind(this));
return this;
}
scrollIntoView(force = false) {
this.treeModel.virtualScroll.scrollIntoView(this, force);
}
focus(scroll = true) {
let previousNode = this.treeModel.getFocusedNode();
this.treeModel.setFocusedNode(this);
if (scroll) {
this.scrollIntoView();
}
if (previousNode) {
this.fireEvent({ eventName: TREE_EVENTS.blur, node: previousNode });
}
this.fireEvent({ eventName: TREE_EVENTS.focus, node: this });
return this;
}
blur() {
let previousNode = this.treeModel.getFocusedNode();
this.treeModel.setFocusedNode(null);
if (previousNode) {
this.fireEvent({ eventName: TREE_EVENTS.blur, node: this });
}
return this;
}
setIsHidden(value) {
this.treeModel.setIsHidden(this, value);
}
hide() {
this.setIsHidden(true);
}
show() {
this.setIsHidden(false);
}
mouseAction(actionName, $event, data = null) {
this.treeModel.setFocus(true);
const actionMapping = this.options.actionMapping.mouse;
const mouseAction = actionMapping[actionName];
if (mouseAction) {
mouseAction(this.treeModel, this, $event, data);
}
}
getSelfHeight() {
return this.options.nodeHeight(this);
}
_initChildren() {
this.children = this.getField('children')
.map((c, index) => new TreeNode(c, this, this.treeModel, index));
}
}
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "isHidden", null);
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "isExpanded", null);
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "isActive", null);
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "isFocused", null);
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "isSelected", null);
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "isAllSelected", null);
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "isPartiallySelected", null);
__decorate([
observable$1,
__metadata("design:type", Array)
], TreeNode.prototype, "children", void 0);
__decorate([
observable$1,
__metadata("design:type", Number)
], TreeNode.prototype, "index", void 0);
__decorate([
observable$1,
__metadata("design:type", Object)
], TreeNode.prototype, "position", void 0);
__decorate([
observable$1,
__metadata("design:type", Number)
], TreeNode.prototype, "height", void 0);
__decorate([
computed$1,
__metadata("design:type", Number),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "level", null);
__decorate([
computed$1,
__metadata("design:type", Array),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "path", null);
__decorate([
computed$1,
__metadata("design:type", Object),
__metadata("design:paramtypes", [])
], TreeNode.prototype, "visibleChildren", null);
__decorate([
action$1,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], TreeNode.prototype, "setIsSelected", null);
__decorate([
action$1,
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TreeNode.prototype, "_initChildren", null);
function uuid() {
return Math.floor(Math.random() * 10000000000000);
}
var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata$1 = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
class TreeModel {
constructor() {
this.options = new TreeOptions();
this.eventNames = Object.keys(TREE_EVENTS);
this.expandedNodeIds = {};
this.selectedLeafNodeIds = {};
this.activeNodeIds = {};
this.hiddenNodeIds = {};
this.focusedNodeId = null;
this.firstUpdate = true;
this.subscriptions = [];
}
// events
fireEvent(event) {
event.treeModel = this;
this.events[event.eventName].emit(event);
this.events.event.emit(event);
}
subscribe(eventName, fn) {
const subscription = this.events[eventName].subscribe(fn);
this.subscriptions.push(subscription);
}
// getters
getFocusedNode() {
return this.focusedNode;
}
getActiveNode() {
return this.activeNodes[0];
}
getActiveNodes() {
return this.activeNodes;
}
getVisibleRoots() {
return this.virtualRoot.visibleChildren;
}
getFirstRoot(skipHidden = false) {
const root = skipHidden ? this.getVisibleRoots() : this.roots;
return root != null && root.length ? root[0] : null;
}
getLastRoot(skipHidden = false) {
const root = skipHidden ? this.getVisibleRoots() : this.roots;
return root != null && root.length ? root[root.length - 1] : null;
}
get isFocused() {
return TreeModel.focusedTree === this;
}
isNodeFocused(node) {
return this.focusedNode === node;
}
isEmptyTree() {
return this.roots && this.roots.length === 0;
}
get focusedNode() {
return this.focusedNodeId ? this.getNodeById(this.focusedNodeId) : null;
}
get expandedNodes() {
const nodes = Object.keys(this.expandedNodeIds)
.filter((id) => this.expandedNodeIds[id])
.map((id) => this.getNodeById(id));
return nodes.filter(Boolean);
}
get activeNodes() {
const nodes = Object.keys(this.activeNodeIds)
.filter((id) => this.activeNodeIds[id])
.map((id) => this.getNodeById(id));
return nodes.filter(Boolean);
}
get hiddenNodes() {
const nodes = Object.keys(this.hiddenNodeIds)
.filter((id) => this.hiddenNodeIds[id])
.map((id) => this.getNodeById(id));
return nodes.filter(Boolean);
}
get selectedLeafNodes() {
const nodes = Object.keys(this.selectedLeafNodeIds)
.filter((id) => this.selectedLeafNodeIds[id])
.map((id) => this.getNodeById(id));
return nodes.filter(Boolean);
}
// locating nodes
getNodeByPath(path, startNode = null) {
if (!path)
return null;
startNode = startNode || this.virtualRoot;
if (path.length === 0)
return startNode;
if (!startNode.children)
return null;
const childId = path.shift();
const childNode = startNode.children.find(c => c.id === childId);
if (!childNode)
return null;
return this.getNodeByPath(path, childNode);
}
getNodeById(id) {
const idStr = id.toString();
return this.getNodeBy((node) => node.id.toString() === idStr);
}
getNodeBy(predicate, startNode = null) {
startNode = startNode || this.virtualRoot;
if (!startNode.children)
return null;
const found = startNode.children.find(predicate);
if (found) { // found in children
return found;
}
else { // look in children's children
for (let child of startNode.children) {
const foundInChildren = this.getNodeBy(predicate, child);
if (foundInChildren)
return foundInChildren;
}
}
}
isExpanded(node) {
return this.expandedNodeIds[node.id];
}
isHidden(node) {
return this.hiddenNodeIds[node.id];
}
isActive(node) {
return this.activeNodeIds[node.id];
}
isSelected(node) {
return this.selectedLeafNodeIds[node.id];
}
ngOnDestroy() {
this.dispose();
this.unsubscribeAll();
}
dispose() {
// Dispose reactions of the replaced nodes
if (this.virtualRoot) {
this.virtualRoot.dispose();
}
}
unsubscribeAll() {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
this.subscriptions = [];
}
// actions
setData({ nodes, options = null, events = null }) {
if (options) {
this.options = new TreeOptions(options);
}
if (events) {
this.events = events;
}
if (nodes) {
this.nodes = nodes;
}
this.update();
}
update() {
// Rebuild tree:
let virtualRootConfig = {
id: this.options.rootId,
virtual: true,
[this.options.childrenField]: this.nodes
};
this.dispose();
this.virtualRoot = new TreeNode(virtualRootConfig, null, this, 0);
this.roots = this.virtualRoot.children;
// Fire event:
if (this.firstUpdate) {
if (this.roots) {
this.firstUpdate = false;
this._calculateExpandedNodes();
}
}
else {
this.fireEvent({ eventName: TREE_EVENTS.updateData });
}
}
setFocusedNode(node) {
this.focusedNodeId = node ? node.id : null;
}
setFocus(value) {
TreeModel.focusedTree = value ? this : null;
}
doForAll(fn) {
this.roots.forEach((root) => root.doForAll(fn));
}
focusNextNode() {
let previousNode = this.getFocusedNode();
let nextNode = previousNode ? previousNode.findNextNode(true, true) : this.getFirstRoot(true);
if (nextNode)
nextNode.focus();
}
focusPreviousNode() {
let previousNode = this.getFocusedNode();
let nextNode = previousNode ? previousNode.findPreviousNode(true) : this.getLastRoot(true);
if (nextNode)
nextNode.focus();
}
focusDrillDown() {
let previousNode = this.getFocusedNode();
if (previousNode && previousNode.isCollapsed && previousNode.hasChildren) {
previousNode.toggleExpanded();
}
else {
let nextNode = previousNode ? previousNode.getFirstChild(true) : this.getFirstRoot(true);
if (nextNode)
nextNode.focus();
}
}
focusDrillUp() {
let previousNode = this.getFocusedNode();
if (!previousNode)
return;
if (previousNode.isExpanded) {
previousNode.toggleExpanded();
}
else {
let nextNode = previousNode.realParent;
if (nextNode)
nextNode.focus();
}
}
setActiveNode(node, value, multi = false) {
if (multi) {
this._setActiveNodeMulti(node, value);
}
else {
this._setActiveNodeSingle(node, value);
}
if (value) {
node.focus(this.options.scrollOnActivate);
this.fireEvent({ eventName: TREE_EVENTS.activate, node });
this.fireEvent({ eventName: TREE_EVENTS.nodeActivate, node }); // For IE11
}
else {
this.fireEvent({ eventName: TREE_EVENTS.deactivate, node });
this.fireEvent({ eventName: TREE_EVENTS.nodeDeactivate, node }); // For IE11
}
}
setSelectedNode(node, value) {
this.selectedLeafNodeIds = Object.assign({}, this.selectedLeafNodeIds, { [node.id]: value });
if (value) {
node.focus();
this.fireEvent({ eventName: TREE_EVENTS.select, node });
}
else {
this.fireEvent({ eventName: TREE_EVENTS.deselect, node });
}
}
setExpandedNode(node, value) {
this.expandedNodeIds = Object.assign({}, this.expandedNodeIds, { [node.id]: value });
this.fireEvent({ eventName: TREE_EVENTS.toggleExpanded, node, isExpanded: value });
}
expandAll() {
this.roots.forEach((root) => root.expandAll());
}
collapseAll() {
this.roots.forEach((root) => root.collapseAll());
}
setIsHidden(node, value) {
this.hiddenNodeIds = Object.assign({}, this.hiddenNodeIds, { [node.id]: value });
}
setHiddenNodeIds(nodeIds) {
this.hiddenNodeIds = nodeIds.reduce((hiddenNodeIds, id) => Object.assign(hiddenNodeIds, {
[id]: true
}), {});
}
performKeyAction(node, $event) {
const keyAction = this.options.actionMapping.keys[$event.keyCode];
if (keyAction) {
$event.preventDefault();
keyAction(this, node, $event);
return true;
}
else {
return false;
}
}
filterNodes(filter, autoShow = true) {
let filterFn;
if (!filter) {
return this.clearFilter();
}
// support function and string filter
if (filter && typeof filter.valueOf() === 'string') {
filterFn = (node) => node.displayField.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
}
else if (filter && typeof filter === 'function') {
filterFn = filter;
}
else {
console.error('Don\'t know what to do with filter', filter);
console.error('Should be either a string or function');
return;
}
const ids = {};
this.roots.forEach((node) => this._filterNode(ids, node, filterFn, autoShow));
this.hiddenNodeIds = ids;
this.fireEvent({ eventName: TREE_EVENTS.changeFilter });
}
clearFilter() {
this.hiddenNodeIds = {};
this.fireEvent({ eventName: TREE_EVENTS.changeFilter });
}
moveNode(node, to) {
const fromIndex = node.getIndexInParent();
const fromParent = node.parent;
if (!this.canMoveNode(node, to, fromIndex))
return;
const fromChildren = fromParent.getField('children');
// If node doesn't have children - create children array
if (!to.parent.getField('children')) {
to.parent.setField('children', []);
}
const toChildren = to.parent.getField('children');
const originalNode = fromChildren.splice(fromIndex, 1)[0];
// Compensate for index if already removed from parent:
let toIndex = (fromParent === to.parent && to.index > fromIndex) ? to.index - 1 : to.index;
toChildren.splice(toIndex, 0, originalNode);
fromParent.treeModel.update();
if (to.parent.treeModel !== fromParent.treeModel) {
to.parent.treeModel.update();
}
this.fireEvent({
eventName: TREE_EVENTS.moveNode,
node: originalNode,
to: { parent: to.parent.data, index: toIndex },
from: { parent: fromParent.data, index: fromIndex }
});
}
copyNode(node, to) {
const fromIndex = node.getIndexInParent();
if (!this.canMoveNode(node, to, fromIndex))
return;
// If node doesn't have children - create children array
if (!to.parent.getField('children')) {
to.parent.setField('children', []);
}
const toChildren = to.parent.getField('children');
const nodeCopy = this.options.getNodeClone(node);
toChildren.splice(to.index, 0, nodeCopy);
node.treeModel.update();
if (to.parent.treeModel !== node.treeModel) {
to.parent.treeModel.update();
}
this.fireEvent({ eventName: TREE_EVENTS.copyNode, node: nodeCopy, to: { parent: to.parent.data, index: to.index } });
}
getState() {
return {
expandedNodeIds: this.expandedNodeIds,
selectedLeafNodeIds: this.selectedLeafNodeIds,
activeNodeIds: this.activeNodeIds,
hiddenNodeIds: this.hiddenNodeIds,
focusedNodeId: this.focusedNodeId
};
}
setState(state) {
if (!state)
return;
Object.assign(this, {
expandedNodeIds: state.expandedNodeIds || {},
selectedLeafNodeIds: state.selectedLeafNodeIds || {},
activeNodeIds: state.activeNodeIds || {},
hiddenNodeIds: state.hiddenNodeIds || {},
focusedNodeId: state.focusedNodeId
});
}
subscribeToState(fn) {
autorun(() => fn(this.getState()));
}
canMoveNode(node, to, fromIndex = undefined) {
const fromNodeIndex = fromIndex || node.getIndexInParent();
// same node:
if (node.parent === to.parent && fromIndex === to.index) {
return false;
}
return !to.parent.isDescendantOf(node);
}
calculateExpandedNodes() {
this._calculateExpandedNodes();
}
// private methods
_filterNode(ids, node, filterFn, autoShow) {
// if node passes function then it's visible
let isVisible = filterFn(node);
if (node.children) {
// if one of node's children passes filter then this node is also visible
node.children.forEach((child) => {
if (this._filterNode(ids, child, filterFn, autoShow)) {
isVisible = true;
}
});
}
// mark node as hidden
if (!isVisible) {
ids[node.id] = true;
}
// auto expand parents to make sure the filtered nodes are visible
if (autoShow && isVisible) {
node.ensureVisible();
}
return isVisible;
}
_calculateExpandedNodes(startNode = null) {
startNode = startNode || this.virtualRoot;
if (startNode.data[this.options.isExpandedField]) {
this.expandedNodeIds = Object.assign({}, this.expandedNodeIds, { [startNode.id]: true });
}
if (startNode.children) {
startNode.children.forEach((child) => this._calculateExpandedNodes(child));
}
}
_setActiveNodeSingle(node, value) {
// Deactivate all other nodes:
this.activeNodes
.filter((activeNode) => activeNode !== node)
.forEach((activeNode) => {
this.fireEvent({ eventName: TREE_EVENTS.deactivate, node: activeNode });
this.fireEvent({ eventName: TREE_EVENTS.nodeDeactivate, node: activeNode }); // For IE11
});
if (value) {
this.activeNodeIds = { [node.id]: true };
}
else {
this.activeNodeIds = {};
}
}
_setActiveNodeMulti(node, value) {
this.activeNodeIds = Object.assign({}, this.activeNodeIds, { [node.id]: value });
}
}
TreeModel.focusedTree = null;
TreeModel.decorators = [
{ type: Injectable }
];
__decorate$1([
observable$1,
__metadata$1("design:type", Array)
], TreeModel.prototype, "roots", void 0);
__decorate$1([
observable$1,
__metadata$1("design:type", Object)
], TreeModel.prototype, "expandedNodeIds", void 0);
__decorate$1([
observable$1,
__metadata$1("design:type", Object)
], TreeModel.prototype, "selectedLeafNodeIds", void 0);
__decorate$1([
observable$1,
__metadata$1("design:type", Object)
], TreeModel.prototype, "activeNodeIds", void 0);
__decorate$1([
observable$1,
__metadata$1("design:type", Object)
], TreeModel.prototype, "hiddenNodeIds", void 0);
__decorate$1([
observable$1,
__metadata$1("design:type", Object)
], TreeModel.prototype, "focusedNodeId", void 0);
__decorate$1([
observable$1,
__metadata$1("design:type", TreeNode)
], TreeModel.prototype, "virtualRoot", void 0);
__decorate$1([
computed$1,
__metadata$1("design:type", Object),
__metadata$1("design:paramtypes", [])
], TreeModel.prototype, "focusedNode", null);
__decorate$1([
computed$1,
__metadata$1("design:type", Object),
__metadata$1("design:paramtypes", [])
], TreeModel.prototype, "expandedNodes", null);
__decorate$1([
computed$1,
__metadata$1("design:type", Object),
__metadata$1("design:paramtypes", [])
], TreeModel.prototype, "activeNodes", null);
__decorate$1([
computed$1,
__metadata$1("design:type", Object),
__metadata$1("design:paramtypes", [])
], TreeModel.prototype, "hiddenNodes", null);
__decorate$1([
computed$1,
__metadata$1("design:type", Object),
__metadata$1("design:paramtypes", [])
], TreeModel.prototype, "selectedLeafNodes", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setData", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "update", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setFocusedNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setFocus", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "doForAll", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "focusNextNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "focusPreviousNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "focusDrillDown", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "focusDrillUp", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object, Object, Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setActiveNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object, Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setSelectedNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object, Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setExpandedNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "expandAll", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "collapseAll", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object, Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setIsHidden", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setHiddenNodeIds", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object, Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "filterNodes", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", []),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "clearFilter", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object, Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "moveNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object, Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "copyNode", null);
__decorate$1([
action$1,
__metadata$1("design:type", Function),
__metadata$1("design:paramtypes", [Object]),
__metadata$1("design:returntype", void 0)
], TreeModel.prototype, "setState", null);
class TreeDraggedElement {
constructor() {
this._draggedElement = null;
}
set(draggedElement) {
this._draggedElement = draggedElement;
}
get() {
return this._draggedElement;
}
isDragging() {
return !!this.get();
}
}
/** @nocollapse */ TreeDraggedElement.ɵprov = ɵɵdefineInjectable({ factory: function TreeDraggedElement_Factory() { return new TreeDraggedElement(); }, token: TreeDraggedElement, providedIn: "root" });
TreeDraggedElement.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.len