UNPKG

2.19 kBPlain TextView Raw
1import {customAttribute} from 'aurelia-templating';
2import {bindingMode} from 'aurelia-binding';
3import {TaskQueue} from 'aurelia-task-queue';
4import {DOM} from 'aurelia-pal';
5
6/**
7 * CustomAttribute that binds provided DOM element's focus attribute with a property on the viewmodel.
8 */
9@customAttribute('focus', bindingMode.twoWay)
10export class Focus {
11 /**
12 *@internal
13 */
14 element: any;
15 /**
16 *@internal
17 */
18 taskQueue: any;
19 /**
20 *@internal
21 */
22 isAttached: boolean;
23 /**
24 *@internal
25 */
26 needsApply: boolean;
27 /**
28 *@internal
29 */
30 value: any;
31
32 /**@internal */
33 static inject() {
34 return [DOM.Element, TaskQueue];
35 }
36 /**
37 * Creates an instance of Focus.
38 * @paramelement Target element on where attribute is placed on.
39 * @param taskQueue The TaskQueue instance.
40 */
41 constructor(element, taskQueue) {
42 this.element = element;
43 this.taskQueue = taskQueue;
44 this.isAttached = false;
45 this.needsApply = false;
46 }
47
48 /**
49 * Invoked everytime the bound value changes.
50 */
51 valueChanged() {
52 if (this.isAttached) {
53 this._apply();
54 } else {
55 this.needsApply = true;
56 }
57 }
58
59 /**
60 * @internal
61 */
62 _apply() {
63 if (this.value) {
64 this.taskQueue.queueMicroTask(() => {
65 if (this.value) {
66 this.element.focus();
67 }
68 });
69 } else {
70 this.element.blur();
71 }
72 }
73
74 /**
75 * Invoked when the attribute is attached to the DOM.
76 */
77 attached() {
78 this.isAttached = true;
79 if (this.needsApply) {
80 this.needsApply = false;
81 this._apply();
82 }
83 this.element.addEventListener('focus', this);
84 this.element.addEventListener('blur', this);
85 }
86
87 /**
88 * Invoked when the attribute is detached from the DOM.
89 */
90 detached() {
91 this.isAttached = false;
92 this.element.removeEventListener('focus', this);
93 this.element.removeEventListener('blur', this);
94 }
95
96 handleEvent(e) {
97 if (e.type === 'focus') {
98 this.value = true;
99 } else if (DOM.activeElement !== this.element) {
100 this.value = false;
101 }
102 }
103}