]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/context-menu/context-menu.directive.ts
LP1945498 Responsive navbar for Angular staff
[working/Evergreen.git] / Open-ILS / src / eg2 / src / app / share / context-menu / context-menu.directive.ts
1 import {Input, Output, EventEmitter, Directive} from '@angular/core';
2 import {NgbPopover} from '@ng-bootstrap/ng-bootstrap';
3 import {ContextMenuService, ContextMenu, ContextMenuEntry} from './context-menu.service';
4
5
6 /* Import all of this stuff so we can pass it to our parent
7  * class via its constructor */
8 /* eslint-disable no-duplicate-imports */
9 import {
10     Inject, Injector, Renderer2, ElementRef, ViewContainerRef,
11     NgZone, ChangeDetectorRef, ApplicationRef
12 } from '@angular/core';
13 import {DOCUMENT} from '@angular/common';
14 import {NgbPopoverConfig} from '@ng-bootstrap/ng-bootstrap';
15 /* eslint-enable no-duplicate-imports */
16 /* --- */
17
18 @Directive({
19     selector: '[egContextMenu]',
20     exportAs: 'egContextMenu'
21 })
22 export class ContextMenuDirective extends NgbPopover {
23
24     // Only one active menu is allowed at a time.
25     static activeDirective: ContextMenuDirective;
26     static menuId = 0;
27
28     triggers = 'contextmenu';
29     popoverClass = 'eg-context-menu';
30
31     menuEntries: ContextMenuEntry[] = [];
32     menu: ContextMenu;
33
34     @Input() set egContextMenu(menuEntries: ContextMenuEntry[]) {
35         this.menuEntries = menuEntries;
36     }
37
38     @Output() menuItemSelected: EventEmitter<ContextMenuEntry>;
39
40     constructor(
41         p1: ElementRef<HTMLElement>, p2: Renderer2, p3: Injector,
42         p5: ViewContainerRef, p6: NgbPopoverConfig,
43         p7: NgZone, @Inject(DOCUMENT) p8: any, p9: ChangeDetectorRef,
44         p10: ApplicationRef, private menuService: ContextMenuService) {
45
46         // relay injected services to parent
47         super(p1, p2, p3, p5, p6, p7, p8, p9, p10);
48
49         this.menuItemSelected = new EventEmitter<ContextMenuEntry>();
50
51         this.menuService.menuItemSelected.subscribe(
52             (entry: ContextMenuEntry) => {
53
54                 // Only broadcast entry selection to my listeners if I'm
55                 // hosting the menu where the selection occurred.
56
57                 if (this.activeMenuIsMe()) {
58                     this.menuItemSelected.emit(entry);
59
60                     // Item selection via keyboard fails to close the menu.
61                     // Force it closed.
62                     this.cleanup();
63                 }
64             });
65     }
66
67     activeMenuIsMe(): boolean {
68         return (
69             this.menu &&
70             this.menuService.activeMenu &&
71             this.menu.id === this.menuService.activeMenu.id
72         );
73     }
74
75     // Close the active menu
76     cleanup() {
77         if (ContextMenuDirective.activeDirective) {
78             ContextMenuDirective.activeDirective.close();
79             ContextMenuDirective.activeDirective = null;
80             this.menuService.activeMenu = null;
81         }
82     }
83
84     open() {
85
86         // In certain scenarios (e.g. right-clicking on another context
87         // menu) an open popover will stay open.  Force it closed here.
88         this.cleanup();
89
90         if (!this.menuEntries ||
91              this.menuEntries.length === 0) {
92             return;
93         }
94
95         this.menu = new ContextMenu();
96         this.menu.id = ContextMenuDirective.menuId++;
97         this.menu.entries = this.menuEntries;
98
99         this.menuService.activeMenu = this.menu;
100         this.menuService.showMenuRequest.emit(this.menu);
101         this.ngbPopover = this.menuService.menuTemplate;
102
103         ContextMenuDirective.activeDirective = this;
104
105         super.open();
106     }
107 }
108
109