ng2-tree
Version:
angular2 component for visualizing data that can be naturally represented as a tree
109 lines • 12.9 kB
JavaScript
import { Component, EventEmitter, Inject, Input, Output, Renderer2, ViewChild } from '@angular/core';
import { NodeMenuService } from './node-menu.service';
import { NodeMenuAction, NodeMenuItemAction } from './menu.events';
import { isEscapePressed, isLeftButtonClicked } from '../utils/event.utils';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "./node-menu.service";
export class NodeMenuComponent {
renderer;
nodeMenuService;
menuItemSelected = new EventEmitter();
menuItems;
menuContainer;
availableMenuItems = [
{
name: 'New tag',
action: NodeMenuItemAction.NewTag,
cssClass: 'new-tag'
},
{
name: 'New folder',
action: NodeMenuItemAction.NewFolder,
cssClass: 'new-folder'
},
{
name: 'Rename',
action: NodeMenuItemAction.Rename,
cssClass: 'rename'
},
{
name: 'Remove',
action: NodeMenuItemAction.Remove,
cssClass: 'remove'
}
];
disposersForGlobalListeners = [];
constructor(renderer, nodeMenuService) {
this.renderer = renderer;
this.nodeMenuService = nodeMenuService;
}
ngOnInit() {
this.availableMenuItems = this.menuItems || this.availableMenuItems;
this.disposersForGlobalListeners.push(this.renderer.listen('document', 'keyup', this.closeMenu.bind(this)));
this.disposersForGlobalListeners.push(this.renderer.listen('document', 'mousedown', this.closeMenu.bind(this)));
}
ngOnDestroy() {
this.disposersForGlobalListeners.forEach((dispose) => dispose());
}
onMenuItemSelected(e, selectedMenuItem) {
if (isLeftButtonClicked(e)) {
this.menuItemSelected.emit({
nodeMenuItemAction: selectedMenuItem.action,
nodeMenuItemSelected: selectedMenuItem.name
});
this.nodeMenuService.fireMenuEvent(e.target, NodeMenuAction.Close);
}
}
closeMenu(e) {
const mouseClicked = e instanceof MouseEvent;
// Check if the click is fired on an element inside a menu
const containingTarget = this.menuContainer.nativeElement !== e.target && this.menuContainer.nativeElement.contains(e.target);
if ((mouseClicked && !containingTarget) || isEscapePressed(e)) {
this.nodeMenuService.fireMenuEvent(e.target, NodeMenuAction.Close);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeMenuComponent, deps: [{ token: Renderer2 }, { token: NodeMenuService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NodeMenuComponent, selector: "node-menu", inputs: { menuItems: "menuItems" }, outputs: { menuItemSelected: "menuItemSelected" }, viewQueries: [{ propertyName: "menuContainer", first: true, predicate: ["menuContainer"], descendants: true }], ngImport: i0, template: `
<div class="node-menu">
<ul class="node-menu-content" #menuContainer>
<li class="node-menu-item" *ngFor="let menuItem of availableMenuItems"
(click)="onMenuItemSelected($event, menuItem)">
<div class="node-menu-item-icon {{menuItem.cssClass}}"></div>
<span class="node-menu-item-value">{{menuItem.name}}</span>
</li>
</ul>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeMenuComponent, decorators: [{
type: Component,
args: [{
selector: 'node-menu',
template: `
<div class="node-menu">
<ul class="node-menu-content" #menuContainer>
<li class="node-menu-item" *ngFor="let menuItem of availableMenuItems"
(click)="onMenuItemSelected($event, menuItem)">
<div class="node-menu-item-icon {{menuItem.cssClass}}"></div>
<span class="node-menu-item-value">{{menuItem.name}}</span>
</li>
</ul>
</div>
`
}]
}], ctorParameters: function () { return [{ type: i0.Renderer2, decorators: [{
type: Inject,
args: [Renderer2]
}] }, { type: i2.NodeMenuService, decorators: [{
type: Inject,
args: [NodeMenuService]
}] }]; }, propDecorators: { menuItemSelected: [{
type: Output
}], menuItems: [{
type: Input
}], menuContainer: [{
type: ViewChild,
args: ['menuContainer', { static: false }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1tZW51LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tZW51L25vZGUtbWVudS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDeEgsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQTZCLE1BQU0sZUFBZSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7OztBQWdCNUUsTUFBTSxPQUFPLGlCQUFpQjtJQW1DQztJQUNNO0lBbEM1QixnQkFBZ0IsR0FBNEMsSUFBSSxZQUFZLEVBQTZCLENBQUM7SUFFakcsU0FBUyxDQUFpQjtJQUduQyxhQUFhLENBQU07SUFFbkIsa0JBQWtCLEdBQW1CO1FBQzFDO1lBQ0UsSUFBSSxFQUFFLFNBQVM7WUFDZixNQUFNLEVBQUUsa0JBQWtCLENBQUMsTUFBTTtZQUNqQyxRQUFRLEVBQUUsU0FBUztTQUNwQjtRQUNEO1lBQ0UsSUFBSSxFQUFFLFlBQVk7WUFDbEIsTUFBTSxFQUFFLGtCQUFrQixDQUFDLFNBQVM7WUFDcEMsUUFBUSxFQUFFLFlBQVk7U0FDdkI7UUFDRDtZQUNFLElBQUksRUFBRSxRQUFRO1lBQ2QsTUFBTSxFQUFFLGtCQUFrQixDQUFDLE1BQU07WUFDakMsUUFBUSxFQUFFLFFBQVE7U0FDbkI7UUFDRDtZQUNFLElBQUksRUFBRSxRQUFRO1lBQ2QsTUFBTSxFQUFFLGtCQUFrQixDQUFDLE1BQU07WUFDakMsUUFBUSxFQUFFLFFBQVE7U0FDbkI7S0FDRixDQUFDO0lBRU0sMkJBQTJCLEdBQW1CLEVBQUUsQ0FBQztJQUV6RCxZQUM2QixRQUFtQixFQUNiLGVBQWdDO1FBRHRDLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDYixvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7SUFDaEUsQ0FBQztJQUVHLFFBQVE7UUFDYixJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUM7UUFDcEUsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1RyxJQUFJLENBQUMsMkJBQTJCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xILENBQUM7SUFFTSxXQUFXO1FBQ2hCLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFtQixFQUFFLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQy9FLENBQUM7SUFFTSxrQkFBa0IsQ0FBQyxDQUFhLEVBQUUsZ0JBQThCO1FBQ3JFLElBQUksbUJBQW1CLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDMUIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQztnQkFDekIsa0JBQWtCLEVBQUUsZ0JBQWdCLENBQUMsTUFBTTtnQkFDM0Msb0JBQW9CLEVBQUUsZ0JBQWdCLENBQUMsSUFBSTthQUM1QyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsTUFBcUIsRUFBRSxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDbkY7SUFDSCxDQUFDO0lBRU8sU0FBUyxDQUFDLENBQTZCO1FBQzdDLE1BQU0sWUFBWSxHQUFHLENBQUMsWUFBWSxVQUFVLENBQUM7UUFDN0MsMERBQTBEO1FBQzFELE1BQU0sZ0JBQWdCLEdBQ3BCLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxLQUFLLENBQUMsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV2RyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxlQUFlLENBQUMsQ0FBa0IsQ0FBQyxFQUFFO1lBQzlFLElBQUksQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxNQUFxQixFQUFFLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNuRjtJQUNILENBQUM7d0dBckVVLGlCQUFpQixrQkFtQ2xCLFNBQVMsYUFDVCxlQUFlOzRGQXBDZCxpQkFBaUIsd1BBWmxCOzs7Ozs7Ozs7O0dBVVQ7OzRGQUVVLGlCQUFpQjtrQkFkN0IsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsV0FBVztvQkFDckIsUUFBUSxFQUFFOzs7Ozs7Ozs7O0dBVVQ7aUJBQ0Y7OzBCQW9DSSxNQUFNOzJCQUFDLFNBQVM7OzBCQUNoQixNQUFNOzJCQUFDLGVBQWU7NENBbENsQixnQkFBZ0I7c0JBRHRCLE1BQU07Z0JBR1MsU0FBUztzQkFBeEIsS0FBSztnQkFHQyxhQUFhO3NCQURuQixTQUFTO3VCQUFDLGVBQWUsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBJbnB1dCwgT25EZXN0cm95LCBPbkluaXQsIE91dHB1dCwgUmVuZGVyZXIyLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5vZGVNZW51U2VydmljZSB9IGZyb20gJy4vbm9kZS1tZW51LnNlcnZpY2UnO1xuaW1wb3J0IHsgTm9kZU1lbnVBY3Rpb24sIE5vZGVNZW51SXRlbUFjdGlvbiwgTm9kZU1lbnVJdGVtU2VsZWN0ZWRFdmVudCB9IGZyb20gJy4vbWVudS5ldmVudHMnO1xuaW1wb3J0IHsgaXNFc2NhcGVQcmVzc2VkLCBpc0xlZnRCdXR0b25DbGlja2VkIH0gZnJvbSAnLi4vdXRpbHMvZXZlbnQudXRpbHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdub2RlLW1lbnUnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJub2RlLW1lbnVcIj5cbiAgICAgIDx1bCBjbGFzcz1cIm5vZGUtbWVudS1jb250ZW50XCIgI21lbnVDb250YWluZXI+XG4gICAgICAgIDxsaSBjbGFzcz1cIm5vZGUtbWVudS1pdGVtXCIgKm5nRm9yPVwibGV0IG1lbnVJdGVtIG9mIGF2YWlsYWJsZU1lbnVJdGVtc1wiXG4gICAgICAgICAgKGNsaWNrKT1cIm9uTWVudUl0ZW1TZWxlY3RlZCgkZXZlbnQsIG1lbnVJdGVtKVwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJub2RlLW1lbnUtaXRlbS1pY29uIHt7bWVudUl0ZW0uY3NzQ2xhc3N9fVwiPjwvZGl2PlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibm9kZS1tZW51LWl0ZW0tdmFsdWVcIj57e21lbnVJdGVtLm5hbWV9fTwvc3Bhbj5cbiAgICAgICAgPC9saT5cbiAgICAgIDwvdWw+XG4gICAgPC9kaXY+XG4gIGBcbn0pXG5leHBvcnQgY2xhc3MgTm9kZU1lbnVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgbWVudUl0ZW1TZWxlY3RlZDogRXZlbnRFbWl0dGVyPE5vZGVNZW51SXRlbVNlbGVjdGVkRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxOb2RlTWVudUl0ZW1TZWxlY3RlZEV2ZW50PigpO1xuXG4gIEBJbnB1dCgpIHB1YmxpYyBtZW51SXRlbXM6IE5vZGVNZW51SXRlbVtdO1xuXG4gIEBWaWV3Q2hpbGQoJ21lbnVDb250YWluZXInLCB7IHN0YXRpYzogZmFsc2UgfSlcbiAgcHVibGljIG1lbnVDb250YWluZXI6IGFueTtcblxuICBwdWJsaWMgYXZhaWxhYmxlTWVudUl0ZW1zOiBOb2RlTWVudUl0ZW1bXSA9IFtcbiAgICB7XG4gICAgICBuYW1lOiAnTmV3IHRhZycsXG4gICAgICBhY3Rpb246IE5vZGVNZW51SXRlbUFjdGlvbi5OZXdUYWcsXG4gICAgICBjc3NDbGFzczogJ25ldy10YWcnXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnTmV3IGZvbGRlcicsXG4gICAgICBhY3Rpb246IE5vZGVNZW51SXRlbUFjdGlvbi5OZXdGb2xkZXIsXG4gICAgICBjc3NDbGFzczogJ25ldy1mb2xkZXInXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnUmVuYW1lJyxcbiAgICAgIGFjdGlvbjogTm9kZU1lbnVJdGVtQWN0aW9uLlJlbmFtZSxcbiAgICAgIGNzc0NsYXNzOiAncmVuYW1lJ1xuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ1JlbW92ZScsXG4gICAgICBhY3Rpb246IE5vZGVNZW51SXRlbUFjdGlvbi5SZW1vdmUsXG4gICAgICBjc3NDbGFzczogJ3JlbW92ZSdcbiAgICB9XG4gIF07XG5cbiAgcHJpdmF0ZSBkaXNwb3NlcnNGb3JHbG9iYWxMaXN0ZW5lcnM6ICgoKSA9PiB2b2lkKVtdID0gW107XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoUmVuZGVyZXIyKSBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgQEluamVjdChOb2RlTWVudVNlcnZpY2UpIHByaXZhdGUgbm9kZU1lbnVTZXJ2aWNlOiBOb2RlTWVudVNlcnZpY2VcbiAgKSB7fVxuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmF2YWlsYWJsZU1lbnVJdGVtcyA9IHRoaXMubWVudUl0ZW1zIHx8IHRoaXMuYXZhaWxhYmxlTWVudUl0ZW1zO1xuICAgIHRoaXMuZGlzcG9zZXJzRm9yR2xvYmFsTGlzdGVuZXJzLnB1c2godGhpcy5yZW5kZXJlci5saXN0ZW4oJ2RvY3VtZW50JywgJ2tleXVwJywgdGhpcy5jbG9zZU1lbnUuYmluZCh0aGlzKSkpO1xuICAgIHRoaXMuZGlzcG9zZXJzRm9yR2xvYmFsTGlzdGVuZXJzLnB1c2godGhpcy5yZW5kZXJlci5saXN0ZW4oJ2RvY3VtZW50JywgJ21vdXNlZG93bicsIHRoaXMuY2xvc2VNZW51LmJpbmQodGhpcykpKTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRpc3Bvc2Vyc0Zvckdsb2JhbExpc3RlbmVycy5mb3JFYWNoKChkaXNwb3NlOiAoKSA9PiB2b2lkKSA9PiBkaXNwb3NlKCkpO1xuICB9XG5cbiAgcHVibGljIG9uTWVudUl0ZW1TZWxlY3RlZChlOiBNb3VzZUV2ZW50LCBzZWxlY3RlZE1lbnVJdGVtOiBOb2RlTWVudUl0ZW0pOiB2b2lkIHtcbiAgICBpZiAoaXNMZWZ0QnV0dG9uQ2xpY2tlZChlKSkge1xuICAgICAgdGhpcy5tZW51SXRlbVNlbGVjdGVkLmVtaXQoe1xuICAgICAgICBub2RlTWVudUl0ZW1BY3Rpb246IHNlbGVjdGVkTWVudUl0ZW0uYWN0aW9uLFxuICAgICAgICBub2RlTWVudUl0ZW1TZWxlY3RlZDogc2VsZWN0ZWRNZW51SXRlbS5uYW1lXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5ub2RlTWVudVNlcnZpY2UuZmlyZU1lbnVFdmVudChlLnRhcmdldCBhcyBIVE1MRWxlbWVudCwgTm9kZU1lbnVBY3Rpb24uQ2xvc2UpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VNZW51KGU6IE1vdXNlRXZlbnQgfCBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgbW91c2VDbGlja2VkID0gZSBpbnN0YW5jZW9mIE1vdXNlRXZlbnQ7XG4gICAgLy8gQ2hlY2sgaWYgdGhlIGNsaWNrIGlzIGZpcmVkIG9uIGFuIGVsZW1lbnQgaW5zaWRlIGEgbWVudVxuICAgIGNvbnN0IGNvbnRhaW5pbmdUYXJnZXQgPVxuICAgICAgdGhpcy5tZW51Q29udGFpbmVyLm5hdGl2ZUVsZW1lbnQgIT09IGUudGFyZ2V0ICYmIHRoaXMubWVudUNvbnRhaW5lci5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGUudGFyZ2V0KTtcblxuICAgIGlmICgobW91c2VDbGlja2VkICYmICFjb250YWluaW5nVGFyZ2V0KSB8fCBpc0VzY2FwZVByZXNzZWQoZSBhcyBLZXlib2FyZEV2ZW50KSkge1xuICAgICAgdGhpcy5ub2RlTWVudVNlcnZpY2UuZmlyZU1lbnVFdmVudChlLnRhcmdldCBhcyBIVE1MRWxlbWVudCwgTm9kZU1lbnVBY3Rpb24uQ2xvc2UpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5vZGVNZW51SXRlbSB7XG4gIG5hbWU6IHN0cmluZztcbiAgYWN0aW9uOiBOb2RlTWVudUl0ZW1BY3Rpb247XG4gIGNzc0NsYXNzPzogc3RyaW5nO1xufVxuIl19