0b6302f81d06df18baa9e68c0fbcf363f6983fa8
[working/Evergreen.git] / Open-ILS / src / eg2 / src / app / share / accesskey / accesskey.service.ts
1 import {Injectable, EventEmitter, HostListener} from '@angular/core';
2
3 export interface AccessKeyAssignment {
4     key: string;      // keyboard command
5     desc: string;     // human-friendly description
6     ctx: string;      // template context
7     action: Function; // handler function
8 }
9
10 @Injectable()
11 export class AccessKeyService {
12
13     // Assignments stored as an array with most recently assigned
14     // items toward the front.  Most recent items have precedence.
15     assignments: AccessKeyAssignment[] = [];
16
17     constructor() {}
18
19     assign(assn: AccessKeyAssignment): void {
20         this.assignments.unshift(assn);
21     }
22
23     /**
24      * Compress a set of single-fire keyboard events into single
25      * string.  For example:  Control and 't' becomes 'ctrl+t'.
26      */
27     compressKeys(evt: KeyboardEvent): string {
28         if (!evt.key) {
29             return null;
30         }
31         let s = '';
32         if (evt.ctrlKey || evt.metaKey) { s += 'ctrl+'; }
33         if (evt.altKey) { s += 'alt+'; }
34         s += evt.key.toLowerCase();
35
36         return s;
37     }
38
39     /**
40      * Checks for a key assignment and fires the assigned action.
41      */
42     fire(evt: KeyboardEvent): void {
43         const keySpec = this.compressKeys(evt);
44         for (const i in this.assignments) { // for-loop to exit early
45             if (keySpec === this.assignments[i].key) {
46                 const assign = this.assignments[i];
47                 console.debug(`AccessKey assignment found for ${assign.key}`);
48                 // Allow the current digest cycle to complete before
49                 // firing the access key action.
50                 setTimeout(assign.action, 0);
51                 evt.preventDefault();
52                 return;
53             }
54         }
55     }
56
57     /**
58      * Returns a simplified key assignment list containing just
59      * the key spec and the description.  Useful for inspecting
60      * without exposing the actions.
61      */
62     infoIze(): any[] {
63         return this.assignments.map(a => {
64             return {key: a.key, desc: a.desc, ctx: a.ctx};
65         });
66     }
67
68 }
69