4b5916b2b7b37e0d946baa74043b90ee1cad11d9
[evergreen-equinox.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 import {
9     Inject, Injector, Renderer2, ElementRef, TemplateRef, ViewContainerRef,
10     ComponentFactoryResolver, NgZone, ChangeDetectorRef, ApplicationRef
11 } from '@angular/core';
12 import {DOCUMENT} from '@angular/common';
13 import {NgbPopoverConfig} from '@ng-bootstrap/ng-bootstrap';
14 /* --- */
15
16 @Directive({
17   selector: '[egContextMenu]',
18   exportAs: 'egContextMenu'
19 })
20 export class ContextMenuDirective extends NgbPopover {
21
22     // Only one active menu is allowed at a time.
23     static activeDirective: ContextMenuDirective;
24     static menuId = 0;
25
26     triggers = 'contextmenu';
27     popoverClass = 'eg-context-menu';
28
29     menuEntries: ContextMenuEntry[] = [];
30     menu: ContextMenu;
31
32     @Input() set egContextMenu(menuEntries: ContextMenuEntry[]) {
33         this.menuEntries = menuEntries;
34     }
35
36     @Output() menuItemSelected: EventEmitter<ContextMenuEntry>;
37
38     constructor(
39         p1: ElementRef<HTMLElement>, p2: Renderer2, p3: Injector,
40         p5: ViewContainerRef, p6: NgbPopoverConfig,
41         p7: NgZone, @Inject(DOCUMENT) p8: any, p9: ChangeDetectorRef,
42         p10: ApplicationRef, private menuService: ContextMenuService) {
43
44         // XXX
45         // The 2nd parameter is removed in a future version of ng-bootstrap,
46         // because it refers to a private service (NgbRTL), which we cannot
47         // instantiate.  Passing null for now so it compiles, but this breaks
48         // the context menu.
49         // https://github.com/ng-bootstrap/ng-bootstrap/commit/7f2146d84822eb1870f5a141626f261d1ecc5799
50         //
51         // relay injected services to parent
52         super(p1, null, p2, p3, p5, p6, p7, p8, p9, p10);
53
54         this.menuItemSelected = new EventEmitter<ContextMenuEntry>();
55
56         this.menuService.menuItemSelected.subscribe(
57             (entry: ContextMenuEntry) => {
58
59             // Only broadcast entry selection to my listeners if I'm
60             // hosting the menu where the selection occurred.
61
62             if (this.activeMenuIsMe()) {
63                 this.menuItemSelected.emit(entry);
64
65                 // Item selection via keyboard fails to close the menu.
66                 // Force it closed.
67                 this.cleanup();
68             }
69         });
70     }
71
72     activeMenuIsMe(): boolean {
73         return (
74             this.menu &&
75             this.menuService.activeMenu &&
76             this.menu.id === this.menuService.activeMenu.id
77         );
78     }
79
80     // Close the active menu
81     cleanup() {
82         if (ContextMenuDirective.activeDirective) {
83             ContextMenuDirective.activeDirective.close();
84             ContextMenuDirective.activeDirective = null;
85             this.menuService.activeMenu = null;
86         }
87     }
88
89     open() {
90
91         // In certain scenarios (e.g. right-clicking on another context
92         // menu) an open popover will stay open.  Force it closed here.
93         this.cleanup();
94
95         if (!this.menuEntries ||
96              this.menuEntries.length === 0) {
97              return;
98         }
99
100         this.menu = new ContextMenu();
101         this.menu.id = ContextMenuDirective.menuId++;
102         this.menu.entries = this.menuEntries;
103
104         this.menuService.activeMenu = this.menu;
105         this.menuService.showMenuRequest.emit(this.menu);
106         this.ngbPopover = this.menuService.menuTemplate;
107
108         ContextMenuDirective.activeDirective = this;
109
110         super.open();
111     }
112 }
113
114