]> BookStack Code Mirror - bookstack/blob - resources/assets/js/components/dropdown.js
Adds autofocus on the email field of the standard login page.
[bookstack] / resources / assets / js / components / dropdown.js
1 /**
2  * Dropdown
3  * Provides some simple logic to create simple dropdown menus.
4  */
5 class DropDown {
6
7     constructor(elem) {
8         this.container = elem;
9         this.menu = elem.querySelector('.dropdown-menu, [dropdown-menu]');
10         this.moveMenu = elem.hasAttribute('dropdown-move-menu');
11         this.toggle = elem.querySelector('[dropdown-toggle]');
12         this.body = document.body;
13         this.setupListeners();
14     }
15
16     show(event) {
17         this.hideAll();
18
19         this.menu.style.display = 'block';
20         this.menu.classList.add('anim', 'menuIn');
21
22         if (this.moveMenu) {
23             // Move to body to prevent being trapped within scrollable sections
24             this.rect = this.menu.getBoundingClientRect();
25             this.body.appendChild(this.menu);
26             this.menu.style.position = 'fixed';
27             this.menu.style.left = `${this.rect.left}px`;
28             this.menu.style.top = `${this.rect.top}px`;
29             this.menu.style.width = `${this.rect.width}px`;
30         }
31
32         // Set listener to hide on mouse leave or window click
33         this.menu.addEventListener('mouseleave', this.hide.bind(this));
34         window.addEventListener('click', event => {
35             if (!this.menu.contains(event.target)) {
36                 this.hide();
37             }
38         });
39
40         // Focus on first input if existing
41         let input = this.menu.querySelector('input');
42         if (input !== null) input.focus();
43
44         event.stopPropagation();
45     }
46
47     hideAll() {
48         for (let dropdown of window.components.dropdown) {
49             dropdown.hide();
50         }
51     }
52
53     hide() {
54         this.menu.style.display = 'none';
55         this.menu.classList.remove('anim', 'menuIn');
56         if (this.moveMenu) {
57             this.menu.style.position = '';
58             this.menu.style.left = '';
59             this.menu.style.top = '';
60             this.menu.style.width = '';
61             this.container.appendChild(this.menu);
62         }
63     }
64
65     setupListeners() {
66         // Hide menu on option click
67         this.container.addEventListener('click', event => {
68              let possibleChildren = Array.from(this.menu.querySelectorAll('a'));
69              if (possibleChildren.indexOf(event.target) !== -1) this.hide();
70         });
71         // Show dropdown on toggle click
72         this.toggle.addEventListener('click', this.show.bind(this));
73         // Hide menu on enter press
74         this.container.addEventListener('keypress', event => {
75                 if (event.keyCode !== 13) return true;
76                 event.preventDefault();
77                 this.hide();
78                 return false;
79         });
80     }
81
82 }
83
84 export default DropDown;