UNPKG

3.66 kBJavaScriptView Raw
1
2export const Dropdown = {
3
4 _collection: {},
5
6 init(dropdown) {
7 dropdown = this._elOrId(dropdown);
8 if (dropdown._dropdown === undefined) {
9 dropdown._dropdown = true;
10 } else {
11 return false;
12 }
13
14 if (dropdown.id !== undefined) {
15 this._collection[dropdown.id] = dropdown;
16 }
17 const toggle_btn = this.getDropdownToggleBtn(dropdown);
18 if (toggle_btn !== null) {
19 this._makeUnclosableInside(dropdown);
20 this._attachToggleClickEvent(dropdown);
21 this._attachToggleBtnMethods(dropdown);
22 }
23 return true;
24 },
25
26 _elOrId(dropdown) {
27 if (typeof dropdown === 'string') {
28 return document.getElementById(dropdown);
29 }
30 return dropdown;
31 },
32
33 _attachToggleClickEvent(dropdown) {
34 this.getDropdownToggleBtn(dropdown).addEventListener('click', (e) => {
35 e.stopPropagation();
36 this.toggle(dropdown);
37 });
38 },
39
40 get(id) {
41 return this._collection[id];
42 },
43
44 getDropdownToggleBtn(dropdown) {
45 dropdown = this._elOrId(dropdown);
46 //return dropdown.getElementsByClassName('dropdown-toggle')[0];
47 return dropdown.querySelector('[data-toggle="dropdown"]');
48 },
49
50 getDropdownMenu(dropdown) {
51 dropdown = this._elOrId(dropdown);
52 return dropdown.getElementsByClassName('dropdown-menu')[0];
53 },
54
55 isClosableInside(dropdown) {
56 return dropdown.hasAttribute('data-close-inside');
57 },
58
59 _makeUnclosableInside(dropdown) {
60 if (this.isClosableInside(dropdown)) {
61 this.getDropdownMenu(dropdown).addEventListener('click', (e) => {
62 e.stopPropagation();
63 })
64 }
65 },
66
67 _getCloseEvent(dropdown) {
68 return new CustomEvent('close', {detail: {dropdown: dropdown}});
69 },
70
71 _getOpenEvent(dropdown) {
72 return new CustomEvent('open', {detail: {dropdown: dropdown}});
73 },
74
75 _bodyHandler(dropdown) {
76 if (dropdown.classList.contains('open')) {
77 this.close(dropdown);
78 }
79 },
80
81 _getUniqueBodyHandler(dropdown) {
82 if (dropdown._bodyHandler === undefined) {
83 dropdown._bodyHandler = this._bodyHandler.bind(this, dropdown);
84 }
85 return dropdown._bodyHandler;
86 },
87
88 close(dropdown) {
89 dropdown = this._elOrId(dropdown);
90 dropdown.classList.remove('open');
91 document.body.removeEventListener('click', this._getUniqueBodyHandler(dropdown));
92 this.getDropdownToggleBtn(dropdown).dispatchEvent(this._getCloseEvent(dropdown));
93 },
94
95 _attachToggleBtnMethods(dropdown) {
96 const toggle_btn = this.getDropdownToggleBtn(dropdown);
97 toggle_btn.close = function() {
98 this.close(dropdown);
99 };
100 toggle_btn.open = function() {
101 this.open(dropdown);
102 };
103 toggle_btn.toggle = function() {
104 this.toggle(dropdown);
105 };
106 },
107
108 open(dropdown) {
109 dropdown = this._elOrId(dropdown);
110 dropdown.classList.add('open');
111 document.body.addEventListener('click', this._getUniqueBodyHandler(dropdown));
112 this.getDropdownToggleBtn(dropdown).dispatchEvent(this._getOpenEvent(dropdown));
113 },
114
115 toggle(dropdown) {
116 dropdown = this._elOrId(dropdown);
117 if (!dropdown.classList.contains('open')) {
118 this.open(dropdown);
119 } else {
120 this.close(dropdown);
121 }
122 }
123
124};
125
126[].forEach.call(document.getElementsByClassName('dropdown'), dropdown => {
127 Dropdown.init(dropdown);
128});