@lemonadejs/dropdown 3.0.3 → 3.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +57 -165
- package/dist/index.js +600 -332
- package/dist/react.js +37 -32
- package/dist/style.css +242 -178
- package/dist/vue.js +45 -32
- package/package.json +22 -23
package/dist/index.js
CHANGED
|
@@ -1,333 +1,601 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Implementar o page up and down
|
|
3
|
-
* botao reset e done
|
|
4
|
-
* traducoes
|
|
5
|
-
*/
|
|
6
|
-
if (!lemonade && typeof (require) === 'function') {
|
|
7
|
-
var lemonade = require('lemonadejs');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
if (!Modal && typeof (require) === 'function') {
|
|
11
|
-
var Modal = require('@lemonadejs/modal');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
//
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
self.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Implementar o page up and down
|
|
3
|
+
* botao reset e done
|
|
4
|
+
* traducoes
|
|
5
|
+
*/
|
|
6
|
+
if (!lemonade && typeof (require) === 'function') {
|
|
7
|
+
var lemonade = require('lemonadejs');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!Modal && typeof (require) === 'function') {
|
|
11
|
+
var Modal = require('@lemonadejs/modal');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
; (function (global, factory) {
|
|
15
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
16
|
+
typeof define === 'function' && define.amd ? define(factory) :
|
|
17
|
+
global.Dropdown = factory();
|
|
18
|
+
}(this, (function () {
|
|
19
|
+
|
|
20
|
+
// Default row height
|
|
21
|
+
let defaultRowHeight = 26;
|
|
22
|
+
|
|
23
|
+
const lazyLoading = function(self) {
|
|
24
|
+
/**
|
|
25
|
+
* Compare two arrays to see if contains exact the same elements
|
|
26
|
+
* @param {number[]} a1
|
|
27
|
+
* @param {number[]} a2
|
|
28
|
+
*/
|
|
29
|
+
const compareArray = function (a1, a2) {
|
|
30
|
+
if (! a1 || ! a2) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let i = a1.length;
|
|
35
|
+
if (i !== a2.length) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
while (i--) {
|
|
39
|
+
if (a1[i] !== a2[i]) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get the position from top of a row by its index
|
|
48
|
+
* @param item
|
|
49
|
+
* @returns {number}
|
|
50
|
+
*/
|
|
51
|
+
const getRowPosition = function(item) {
|
|
52
|
+
// Position from top
|
|
53
|
+
let top = 0;
|
|
54
|
+
if (item) {
|
|
55
|
+
let items = self.rows;
|
|
56
|
+
if (items && items.length) {
|
|
57
|
+
let index = self.rows.indexOf(item);
|
|
58
|
+
// Go through the items
|
|
59
|
+
for (let j = 0; j < index; j++) {
|
|
60
|
+
top += items[j].height || defaultRowHeight;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return top;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const updateScroll = function() {
|
|
68
|
+
let items = self.rows;
|
|
69
|
+
if (items) {
|
|
70
|
+
// Total of items in the container
|
|
71
|
+
let numOfItems = items.length;
|
|
72
|
+
// Position from top
|
|
73
|
+
let height = 0;
|
|
74
|
+
// Go through the items
|
|
75
|
+
for (let j = 0; j < numOfItems; j++) {
|
|
76
|
+
height += items[j].height || defaultRowHeight;
|
|
77
|
+
}
|
|
78
|
+
// Update height
|
|
79
|
+
scroll.style.height = height + 'px';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const getVisibleRows = function(reset) {
|
|
84
|
+
let items = self.rows;
|
|
85
|
+
if (items) {
|
|
86
|
+
let rows = [];
|
|
87
|
+
// Total of items in the container
|
|
88
|
+
let numOfItems = items.length;
|
|
89
|
+
// Height
|
|
90
|
+
let height = 0;
|
|
91
|
+
// Controls
|
|
92
|
+
let y = el.scrollTop;
|
|
93
|
+
let h = y + (el.offsetHeight || self.height);
|
|
94
|
+
// Go through the items
|
|
95
|
+
for (let j = 0; j < numOfItems; j++) {
|
|
96
|
+
if (items[j].visible !== false) {
|
|
97
|
+
// Height
|
|
98
|
+
let rowHeight = items[j].height || defaultRowHeight;
|
|
99
|
+
// Return on partial width
|
|
100
|
+
if (height + rowHeight > y && height < h) {
|
|
101
|
+
rows.push(items[j]);
|
|
102
|
+
}
|
|
103
|
+
height += rowHeight;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Update visible rows
|
|
108
|
+
if (reset || ! compareArray(rows, self.result)) {
|
|
109
|
+
self.result = rows;
|
|
110
|
+
// Adjust scroll height
|
|
111
|
+
let adjustScroll = reset;
|
|
112
|
+
// Adjust scrolling
|
|
113
|
+
for (let i = 0; i < rows.length; i++) {
|
|
114
|
+
// Item
|
|
115
|
+
let item = rows[i];
|
|
116
|
+
// Item height
|
|
117
|
+
let h = item.el.offsetHeight;
|
|
118
|
+
// Update row height
|
|
119
|
+
if (! item.height || h !== item.height) {
|
|
120
|
+
// Keep item height
|
|
121
|
+
item.height = h;
|
|
122
|
+
// Adjust total height
|
|
123
|
+
adjustScroll = true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Update scroll if the height of one element has been changed
|
|
128
|
+
if (adjustScroll) {
|
|
129
|
+
updateScroll();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Adjust position of the first element
|
|
134
|
+
let position = getRowPosition(self.result[0]);
|
|
135
|
+
let diff = position - el.scrollTop;
|
|
136
|
+
if (diff > 0) {
|
|
137
|
+
diff = 0;
|
|
138
|
+
}
|
|
139
|
+
self.container.style.top = diff + 'px';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Move the position to the top and re-render based on the scroll
|
|
145
|
+
* @param reset
|
|
146
|
+
*/
|
|
147
|
+
const render = function (reset) {
|
|
148
|
+
// Move scroll to the top
|
|
149
|
+
el.scrollTop = 0;
|
|
150
|
+
// Append first batch
|
|
151
|
+
getVisibleRows(reset);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
self.adjustPosition = function(item) {
|
|
155
|
+
if (item.el) {
|
|
156
|
+
let calc = item.el.offsetTop + item.el.offsetHeight;
|
|
157
|
+
if (calc > el.offsetHeight) {
|
|
158
|
+
let size = calc - el.offsetHeight;
|
|
159
|
+
if (size < defaultRowHeight) {
|
|
160
|
+
size = defaultRowHeight;
|
|
161
|
+
}
|
|
162
|
+
el.scrollTop -= -1 * size;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Controls
|
|
168
|
+
const scrollControls = function() {
|
|
169
|
+
// Get all items that should be visible based on the position of the scroll
|
|
170
|
+
getVisibleRows(false);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Element for scrolling
|
|
174
|
+
let el = self.container.parentNode;
|
|
175
|
+
el.classList.add('lm-lazy');
|
|
176
|
+
// Div to represent the height of the content
|
|
177
|
+
const scroll = document.createElement('div');
|
|
178
|
+
scroll.classList.add('lm-lazy-scroll');
|
|
179
|
+
// Force the height and add scrolling
|
|
180
|
+
el.appendChild(scroll);
|
|
181
|
+
el.addEventListener('scroll', scrollControls);
|
|
182
|
+
el.addEventListener('wheel', scrollControls);
|
|
183
|
+
self.container.classList.add('lm-lazy-items');
|
|
184
|
+
|
|
185
|
+
self.goto = function(item) {
|
|
186
|
+
el.scrollTop = getRowPosition(item);
|
|
187
|
+
// Get all items that should be visible based on the position of the scroll
|
|
188
|
+
getVisibleRows(false);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return (prop) => {
|
|
192
|
+
if (prop === 'rows') {
|
|
193
|
+
render(true);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const Dropdown = function () {
|
|
199
|
+
let self = this;
|
|
200
|
+
let value = [];
|
|
201
|
+
let cursor = null;
|
|
202
|
+
|
|
203
|
+
if (! self.width) {
|
|
204
|
+
self.width = 260;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Lazy loading global instance
|
|
208
|
+
let lazyloading = null;
|
|
209
|
+
|
|
210
|
+
const setData = function() {
|
|
211
|
+
// Re-order to make sure groups are in sequence
|
|
212
|
+
self.data.sort((a, b) => {
|
|
213
|
+
// Compare groups
|
|
214
|
+
if (a.group && b.group) {
|
|
215
|
+
return a.group.localeCompare(b.group);
|
|
216
|
+
}
|
|
217
|
+
return 0;
|
|
218
|
+
});
|
|
219
|
+
let group = '';
|
|
220
|
+
// Define group headers
|
|
221
|
+
self.data.map((v) => {
|
|
222
|
+
// Compare groups
|
|
223
|
+
if (v.group && v.group !== group) {
|
|
224
|
+
v.header = true;
|
|
225
|
+
group = v.group;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
// Estimate width
|
|
229
|
+
let width = self.width;
|
|
230
|
+
// Width && values
|
|
231
|
+
self.data.map(function (s) {
|
|
232
|
+
// Estimated width of the element
|
|
233
|
+
width = Math.max(width, s.text.length * 8);
|
|
234
|
+
});
|
|
235
|
+
// Adjust the width
|
|
236
|
+
let w = self.input.offsetWidth;
|
|
237
|
+
if (width < w) {
|
|
238
|
+
width = w;
|
|
239
|
+
}
|
|
240
|
+
// Estimated with based on the text
|
|
241
|
+
if (self.width < width) {
|
|
242
|
+
self.width = width;
|
|
243
|
+
}
|
|
244
|
+
self.el.style.width = self.width + 'px';
|
|
245
|
+
// Height
|
|
246
|
+
self.height = 400;
|
|
247
|
+
// Animation for mobile
|
|
248
|
+
if (document.documentElement.clientWidth < 800) {
|
|
249
|
+
self.animation = true;
|
|
250
|
+
}
|
|
251
|
+
// Data to be listed
|
|
252
|
+
self.rows = self.data;
|
|
253
|
+
// Set the initial value
|
|
254
|
+
if (typeof(self.value) !== 'undefined') {
|
|
255
|
+
setValue(self.value);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const setCursor = function(index) {
|
|
260
|
+
let item = self.rows[index];
|
|
261
|
+
if (typeof(item) !== 'undefined') {
|
|
262
|
+
// Set cursor number
|
|
263
|
+
cursor = index;
|
|
264
|
+
// Set visual indication
|
|
265
|
+
item.cursor = true;
|
|
266
|
+
// Go to the item on the scroll in case the item is not on the viewport
|
|
267
|
+
if (! item.el || ! item.el.parentNode) {
|
|
268
|
+
// Goto method
|
|
269
|
+
self.goto(item);
|
|
270
|
+
}
|
|
271
|
+
// Adjust cursor position
|
|
272
|
+
setTimeout(function() {
|
|
273
|
+
self.adjustPosition(item);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const removeCursor = function(reset) {
|
|
279
|
+
if (cursor !== null) {
|
|
280
|
+
if (typeof(self.rows[cursor]) !== 'undefined') {
|
|
281
|
+
self.rows[cursor].cursor = false;
|
|
282
|
+
}
|
|
283
|
+
if (reset) {
|
|
284
|
+
// Cursor is null
|
|
285
|
+
cursor = null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const moveCursor = function(direction, jump) {
|
|
291
|
+
// Remove cursor
|
|
292
|
+
removeCursor();
|
|
293
|
+
// Last item
|
|
294
|
+
let last = self.rows.length - 1;
|
|
295
|
+
if (jump) {
|
|
296
|
+
if (direction < 0) {
|
|
297
|
+
cursor = 0;
|
|
298
|
+
} else {
|
|
299
|
+
cursor = last;
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
// Position
|
|
303
|
+
if (cursor === null) {
|
|
304
|
+
cursor = 0;
|
|
305
|
+
} else {
|
|
306
|
+
// Move previous
|
|
307
|
+
cursor = cursor + direction;
|
|
308
|
+
}
|
|
309
|
+
// Reach the boundaries
|
|
310
|
+
if (direction < 0) {
|
|
311
|
+
// Back to the last one
|
|
312
|
+
if (cursor < 0) {
|
|
313
|
+
cursor = last;
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
// Back to the first one
|
|
317
|
+
if (cursor > last) {
|
|
318
|
+
cursor = 0;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Add cursor
|
|
323
|
+
setCursor(cursor);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const updateLabel = function() {
|
|
327
|
+
if (value && value.length) {
|
|
328
|
+
self.input.textContent = value.filter(v => v.selected).map(i => i.text).join('; ');
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const setValue = function(v) {
|
|
333
|
+
// Values
|
|
334
|
+
let newValue;
|
|
335
|
+
if (! Array.isArray(v)) {
|
|
336
|
+
if (typeof(v) === 'string') {
|
|
337
|
+
newValue = v.split(';');
|
|
338
|
+
} else {
|
|
339
|
+
newValue = [v];
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
newValue = v;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Width && values
|
|
346
|
+
value = [];
|
|
347
|
+
|
|
348
|
+
self.data.map(function(s) {
|
|
349
|
+
// Select values
|
|
350
|
+
if (newValue.indexOf(s.value) !== -1) {
|
|
351
|
+
s.selected = true;
|
|
352
|
+
value.push(s);
|
|
353
|
+
} else {
|
|
354
|
+
s.selected = false;
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Update label
|
|
359
|
+
updateLabel();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const getValue = function() {
|
|
363
|
+
if (value && value.length) {
|
|
364
|
+
return value.filter(v => v.selected).map(i => i.value);
|
|
365
|
+
}
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const onclose = function() {
|
|
370
|
+
// Cursor
|
|
371
|
+
removeCursor();
|
|
372
|
+
// Reset search
|
|
373
|
+
if (self.autocomplete && self.input.textContent) {
|
|
374
|
+
// Go to begin of the data
|
|
375
|
+
self.rows = self.data;
|
|
376
|
+
// Remove editable attribute
|
|
377
|
+
self.input.removeAttribute('contenteditable');
|
|
378
|
+
// Clear input
|
|
379
|
+
self.input.textContent = '';
|
|
380
|
+
}
|
|
381
|
+
// Update label
|
|
382
|
+
updateLabel();
|
|
383
|
+
// Update value
|
|
384
|
+
self.value = getValue();
|
|
385
|
+
// Identify the new state of the dropdown
|
|
386
|
+
self.state = false;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const onopen = function() {
|
|
390
|
+
self.state = true;
|
|
391
|
+
// Value
|
|
392
|
+
let v = value[value.length-1];
|
|
393
|
+
// Cursor
|
|
394
|
+
removeCursor();
|
|
395
|
+
// Move to the correct position
|
|
396
|
+
if (v) {
|
|
397
|
+
// Go to the last item in the array of values
|
|
398
|
+
self.goto(v);
|
|
399
|
+
// Mark the position of the cursor to the same element
|
|
400
|
+
setCursor(self.rows.indexOf(v));
|
|
401
|
+
} else {
|
|
402
|
+
// Go to begin of the data
|
|
403
|
+
self.rows = self.data;
|
|
404
|
+
}
|
|
405
|
+
// Prepare search field
|
|
406
|
+
if (self.autocomplete) {
|
|
407
|
+
// Clear input
|
|
408
|
+
self.input.textContent = '';
|
|
409
|
+
// Editable
|
|
410
|
+
self.input.setAttribute('contenteditable', true);
|
|
411
|
+
// Focus on the item
|
|
412
|
+
self.input.focus();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
self.search = function() {
|
|
417
|
+
if (self.state && self.autocomplete) {
|
|
418
|
+
// Filter options
|
|
419
|
+
let data;
|
|
420
|
+
if (! self.input.textContent) {
|
|
421
|
+
data = self.data;
|
|
422
|
+
} else {
|
|
423
|
+
data = self.data.filter(item => {
|
|
424
|
+
return item.selected === true ||
|
|
425
|
+
(item.text.toLowerCase().includes(self.input.textContent.toLowerCase())) ||
|
|
426
|
+
(item.group && item.group.toLowerCase().includes(self.input.textContent.toLowerCase()));
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
// Cursor
|
|
430
|
+
removeCursor(true);
|
|
431
|
+
// Update the data from the dropdown
|
|
432
|
+
self.rows = data;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
self.open = function () {
|
|
437
|
+
if (self.modal && self.modal.closed) {
|
|
438
|
+
self.modal.closed = false;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
self.close = function () {
|
|
443
|
+
// Close the modal
|
|
444
|
+
if (self.modal) {
|
|
445
|
+
self.modal.closed = true;
|
|
446
|
+
// Remove cursor
|
|
447
|
+
removeCursor(true);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
self.toggle = function() {
|
|
452
|
+
if (self.modal) {
|
|
453
|
+
if (self.modal.closed) {
|
|
454
|
+
self.open();
|
|
455
|
+
} else {
|
|
456
|
+
self.close();
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
self.select = function(e, s) {
|
|
462
|
+
if (s) {
|
|
463
|
+
if (self.multiple === true) {
|
|
464
|
+
let position = value.indexOf(s);
|
|
465
|
+
if (position === -1) {
|
|
466
|
+
value.push(s);
|
|
467
|
+
s.selected = true;
|
|
468
|
+
} else {
|
|
469
|
+
value.splice(position, 1);
|
|
470
|
+
s.selected = false;
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
if (value[0] === s) {
|
|
474
|
+
s.selected = !s.selected;
|
|
475
|
+
} else {
|
|
476
|
+
if (value[0]) {
|
|
477
|
+
value[0].selected = false;
|
|
478
|
+
}
|
|
479
|
+
s.selected = true;
|
|
480
|
+
}
|
|
481
|
+
if (s.selected) {
|
|
482
|
+
value = [s];
|
|
483
|
+
} else {
|
|
484
|
+
value = [];
|
|
485
|
+
}
|
|
486
|
+
// Close the modal
|
|
487
|
+
self.close();
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
self.getGroup = function() {
|
|
493
|
+
if (this.group && this.header) {
|
|
494
|
+
return this.group;
|
|
495
|
+
} else {
|
|
496
|
+
return '';
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
self.onload = function () {
|
|
501
|
+
if (self.type !== "inline") {
|
|
502
|
+
// Create modal instance
|
|
503
|
+
self.modal = {
|
|
504
|
+
closed: true,
|
|
505
|
+
focus: false,
|
|
506
|
+
width: self.width,
|
|
507
|
+
'auto-close': false,
|
|
508
|
+
onopen: onopen,
|
|
509
|
+
onclose: onclose,
|
|
510
|
+
};
|
|
511
|
+
// Generate modal
|
|
512
|
+
Modal(self.el.children[1], self.modal);
|
|
513
|
+
} else {
|
|
514
|
+
// For inline dropdown
|
|
515
|
+
self.el.setAttribute('tabindex', 0);
|
|
516
|
+
// Remove search
|
|
517
|
+
self.input.remove();
|
|
518
|
+
}
|
|
519
|
+
// Loading controls
|
|
520
|
+
lazyloading = lazyLoading(self);
|
|
521
|
+
// Process the data
|
|
522
|
+
setData();
|
|
523
|
+
// Focus out of the component
|
|
524
|
+
self.el.addEventListener('focusout', function(e) {
|
|
525
|
+
if (self.modal) {
|
|
526
|
+
if (! (e.relatedTarget && self.el.contains(e.relatedTarget)) && !self.el.contains(e.relatedTarget)) {
|
|
527
|
+
if (! self.modal.closed) {
|
|
528
|
+
self.close();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
})
|
|
533
|
+
// Key events
|
|
534
|
+
self.el.addEventListener('keydown', function(e) {
|
|
535
|
+
let prevent = false;
|
|
536
|
+
if (e.key === 'ArrowUp') {
|
|
537
|
+
moveCursor(-1);
|
|
538
|
+
prevent = true;
|
|
539
|
+
} else if (e.key === 'ArrowDown') {
|
|
540
|
+
moveCursor(1);
|
|
541
|
+
prevent = true;
|
|
542
|
+
} else if (e.key === 'Home') {
|
|
543
|
+
moveCursor(-1, true);
|
|
544
|
+
} else if (e.key === 'End') {
|
|
545
|
+
moveCursor(1, true);
|
|
546
|
+
} else if (e.key === 'Enter') {
|
|
547
|
+
self.select(e, self.rows[cursor]);
|
|
548
|
+
prevent = true;
|
|
549
|
+
} else {
|
|
550
|
+
if (e.keyCode === 32 && ! self.autocomplete) {
|
|
551
|
+
self.select(e, self.rows[cursor]);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if (prevent) {
|
|
556
|
+
e.preventDefault();
|
|
557
|
+
e.stopImmediatePropagation();
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
self.onchange = function(prop) {
|
|
563
|
+
if (prop === 'value') {
|
|
564
|
+
setValue(self.value);
|
|
565
|
+
} else if (prop === 'data') {
|
|
566
|
+
setData();
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
if (typeof(lazyloading) === 'function') {
|
|
570
|
+
lazyloading(prop);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return `<div class="lm-dropdown" data-type="{{self.type}}" data-state="{{self.state}}">
|
|
575
|
+
<div class="lm-dropdown-header">
|
|
576
|
+
<div class="lm-dropdown-input" oninput="self.search" onfocus="self.open" placeholder="{{self.placeholder}}" :ref="self.input" tabindex="0"></div>
|
|
577
|
+
<button onclick="self.close" class="lm-dropdown-done">Done</button>
|
|
578
|
+
</div>
|
|
579
|
+
<div class="lm-dropdown-content">
|
|
580
|
+
<div>
|
|
581
|
+
<div :loop="self.result" :ref="self.container" :rows="self.rows">
|
|
582
|
+
<div class="lm-dropdown-item" onclick="self.parent.select" data-cursor="{{self.cursor}}" data-selected="{{self.selected}}" data-group="{{self.parent.getGroup}}">
|
|
583
|
+
<div><img :src="self.image" /><span>{{self.text}}</span></div>
|
|
584
|
+
</div>
|
|
585
|
+
</div>
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
</div>`;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
lemonade.setComponents({ Dropdown: Dropdown });
|
|
592
|
+
|
|
593
|
+
return function (root, options) {
|
|
594
|
+
if (typeof (root) === 'object') {
|
|
595
|
+
lemonade.render(Dropdown, root, options)
|
|
596
|
+
return options;
|
|
597
|
+
} else {
|
|
598
|
+
return Dropdown.call(this, root)
|
|
599
|
+
}
|
|
600
|
+
}
|
|
333
601
|
})));
|