1
|
|
|
import {define} from "../globals/globals"; |
2
|
|
|
import {DropdownInterface} from "../interfaces/DropdownInterface"; |
3
|
|
|
import {DropdownOptions} from "../types/DropdownOptions"; |
4
|
|
|
|
5
|
|
|
(function (root, factory) { |
6
|
|
|
if (typeof define === 'function' && define.amd) { |
7
|
|
|
define([], factory); |
8
|
|
|
} else if (typeof module === 'object' && module.exports) { |
9
|
|
|
module.exports = factory(); |
10
|
|
|
} else { |
11
|
|
|
root!.Dropdown = factory(); |
12
|
|
|
} |
13
|
|
|
}(typeof self !== 'undefined' ? self : this, function () { |
14
|
|
|
|
15
|
|
|
class Dropdown implements DropdownInterface { |
16
|
|
|
public $el: HTMLElement; |
17
|
|
|
public options: DropdownOptions; |
18
|
|
|
static $toggle: Array<HTMLElement>; |
19
|
|
|
static $content: HTMLElement; |
20
|
|
|
|
21
|
|
|
constructor($el: string | HTMLElement, options:DropdownOptions) { |
22
|
|
|
if (!$el) { |
23
|
|
|
return; |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
this.$el = (typeof $el === 'string' ? document.querySelector($el) : $el) as HTMLElement; |
27
|
|
|
|
28
|
|
|
if(options) { |
29
|
|
|
this.options = options; |
30
|
|
|
this.options.togglers = options.togglers as NodeListOf<HTMLElement>; |
31
|
|
|
this.options.bodyClose = typeof options.bodyClose === 'undefined' ? true : options.bodyClose as boolean; |
32
|
|
|
this.options.opened = options.opened || false as boolean; |
33
|
|
|
this.options.content = options.content as any; |
34
|
|
|
this.options.onOpen = options.onOpen as Function; |
35
|
|
|
this.options.onClose = options.onClose as Function; |
36
|
|
|
this.options.class = options.class || {} as object; |
37
|
|
|
this.options.class.container = options.class.container || 'dropdown' as string; |
38
|
|
|
this.options.class.content = options.class.content || 'dropdown__content' as string; |
39
|
|
|
this.options.class.toggle = options.class.toggle || 'dropdown__toggle' as string; |
40
|
|
|
this.options.class.open = options.class.open || 'open' as string; |
41
|
|
|
} |
42
|
|
|
else { |
43
|
|
|
this.mergeOptions(); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
this.init(); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
private mergeOptions(): void { |
50
|
|
|
let defaults = { |
51
|
|
|
bodyClose: true, |
52
|
|
|
opened: false, |
53
|
|
|
onOpen: function () {}, |
54
|
|
|
onClose: function () {}, |
55
|
|
|
class: { |
56
|
|
|
container: 'dropdown', |
57
|
|
|
content: 'dropdown__content', |
58
|
|
|
toggle: 'dropdown__toggle', |
59
|
|
|
open: 'open' |
60
|
|
|
} |
61
|
|
|
}; |
62
|
|
|
|
63
|
|
|
this.options = Object.assign(this, defaults) |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
protected init(): void { |
67
|
|
|
this.initDom(); |
68
|
|
|
this.initEvents(); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
private initDom(): void { |
72
|
|
|
let that = this; |
73
|
|
|
|
74
|
|
|
if (!that.options.togglers) { |
75
|
|
|
Dropdown.$toggle = [that.$el.querySelector('a.toggler')] as Array<HTMLElement>; |
76
|
|
|
} |
77
|
|
|
else { |
78
|
|
|
Dropdown.$toggle = []; |
79
|
|
|
|
80
|
|
|
for (let i = 0; i < (that.options.togglers as NodeListOf<HTMLElement>).length; i++) { |
81
|
|
|
Dropdown.$toggle[Dropdown.$toggle.length] = (that.options.togglers as NodeListOf<HTMLElement>)[i]; |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
if (that.options.content as string) { |
86
|
|
|
Dropdown.$content = that.options.content; |
87
|
|
|
} |
88
|
|
|
else { |
89
|
|
|
Dropdown.$content = that.$el.querySelector('.dropdown__content') as HTMLElement; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
that.$el.classList.add(that.options.class.container as string); |
93
|
|
|
|
94
|
|
|
if (that.options.opened) { |
95
|
|
|
that.open(); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
for (let i = 0; i < Dropdown.$toggle.length; i++) { |
99
|
|
|
Dropdown.$toggle[i].classList.add(that.options.class.toggle as string); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
Dropdown.$content.classList.add(that.options.class.content as string); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
protected initEvents(): void { |
106
|
|
|
let that = this; |
107
|
|
|
|
108
|
|
|
for (let i = 0; i < Dropdown.$toggle.length; i++) { |
109
|
|
|
Dropdown.$toggle[i].addEventListener('click', function (event:Event) { |
110
|
|
|
that.eventToggleClick(event); |
111
|
|
|
}); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
if (that.options.bodyClose as boolean) { |
115
|
|
|
document.addEventListener('click', function (event:Event) { |
116
|
|
|
that.eventBodyClick(event); |
117
|
|
|
}); |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
protected eventToggleClick(event: Event): void { |
122
|
|
|
event.preventDefault(); |
123
|
|
|
|
124
|
|
|
let that = this; |
125
|
|
|
|
126
|
|
|
if (that.$el.classList.contains(that.options.class.open as string)) { |
127
|
|
|
that.close(); |
128
|
|
|
} |
129
|
|
|
else { |
130
|
|
|
that.open(); |
131
|
|
|
} |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
protected eventBodyClick(event: Event): void { |
135
|
|
|
let that = this; |
136
|
|
|
|
137
|
|
|
if (!that.elementInDropdown(event.target) ) { |
138
|
|
|
that.close(); |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
protected elementInDropdown($el: any): boolean { |
143
|
|
|
let that = this, |
144
|
|
|
parent = $el; |
145
|
|
|
|
146
|
|
|
while (parent) { |
147
|
|
|
if (parent === that.$el) { |
148
|
|
|
return true; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
parent = parent.parentNode as Element; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
return false; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
public open(): void { |
158
|
|
|
this.$el.classList.add(this.options.class.open); |
159
|
|
|
|
160
|
|
|
if(this.options.onOpen) { |
161
|
|
|
this.options.onOpen.call(this); |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
public close(): void { |
166
|
|
|
this.$el.classList.remove(this.options.class.open); |
167
|
|
|
|
168
|
|
|
if(this.options.onClose) { |
169
|
|
|
this.options.onClose.call(this); |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
return Dropdown; |
175
|
|
|
})); |