@lemonadejs/dropdown 3.1.2 → 3.1.5
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.js +191 -166
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,17 +20,22 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
20
20
|
// Default row height
|
|
21
21
|
let defaultRowHeight = 24;
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Compare two arrays to see if contains exact the same elements
|
|
25
|
+
* @param {number|number[]} a1
|
|
26
|
+
* @param {number|number[]} a2
|
|
27
|
+
*/
|
|
28
|
+
const compareValues = function (a1, a2) {
|
|
29
|
+
if (! a1 || ! a2) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (! Array.isArray(a1) || ! Array.isArray(a2)) {
|
|
33
|
+
if (a1 === a2) {
|
|
34
|
+
return true;
|
|
35
|
+
} else {
|
|
31
36
|
return false;
|
|
32
37
|
}
|
|
33
|
-
|
|
38
|
+
} else {
|
|
34
39
|
let i = a1.length;
|
|
35
40
|
if (i !== a2.length) {
|
|
36
41
|
return false;
|
|
@@ -40,9 +45,11 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
40
45
|
return false;
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
|
-
return true;
|
|
44
48
|
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
45
51
|
|
|
52
|
+
const lazyLoading = function(self) {
|
|
46
53
|
/**
|
|
47
54
|
* Get the position from top of a row by its index
|
|
48
55
|
* @param item
|
|
@@ -132,7 +139,7 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
// Update visible rows
|
|
135
|
-
if (reset || !
|
|
142
|
+
if (reset || ! compareValues(rows, self.result)) {
|
|
136
143
|
// Render the items
|
|
137
144
|
self.result = rows;
|
|
138
145
|
// Adjust scroll height
|
|
@@ -237,81 +244,33 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
237
244
|
|
|
238
245
|
const Dropdown = function () {
|
|
239
246
|
let self = this;
|
|
247
|
+
// Internal value controllers
|
|
240
248
|
let value = [];
|
|
249
|
+
// Cursor
|
|
241
250
|
let cursor = null;
|
|
242
|
-
|
|
251
|
+
// Control events
|
|
252
|
+
let ignoreEvents = false;
|
|
253
|
+
// Default widht
|
|
243
254
|
if (! self.width) {
|
|
244
255
|
self.width = 260;
|
|
245
256
|
}
|
|
246
|
-
|
|
247
257
|
// Lazy loading global instance
|
|
248
258
|
let lazyloading = null;
|
|
249
|
-
|
|
259
|
+
// Custom events defined by the user
|
|
250
260
|
let onload = self.load;
|
|
251
261
|
let onchange = self.onchange;
|
|
252
262
|
|
|
253
|
-
|
|
254
|
-
// Estimate width
|
|
255
|
-
let width = self.width;
|
|
256
|
-
// Re-order to make sure groups are in sequence
|
|
257
|
-
if (self.data && self.data.length) {
|
|
258
|
-
self.data.sort((a, b) => {
|
|
259
|
-
// Compare groups
|
|
260
|
-
if (a.group && b.group) {
|
|
261
|
-
return a.group.localeCompare(b.group);
|
|
262
|
-
}
|
|
263
|
-
return 0;
|
|
264
|
-
});
|
|
265
|
-
let group = '';
|
|
266
|
-
// Define group headers
|
|
267
|
-
self.data.map((v) => {
|
|
268
|
-
// Compare groups
|
|
269
|
-
if (v && v.group && v.group !== group) {
|
|
270
|
-
v.header = true;
|
|
271
|
-
group = v.group;
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
// Width && values
|
|
275
|
-
self.data.map(function (s) {
|
|
276
|
-
// Estimated width of the element
|
|
277
|
-
if (s.text) {
|
|
278
|
-
width = Math.max(width, s.text.length * 8);
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
// Adjust the width
|
|
283
|
-
let w = self.input.offsetWidth;
|
|
284
|
-
if (width < w) {
|
|
285
|
-
width = w;
|
|
286
|
-
}
|
|
287
|
-
// Estimated with based on the text
|
|
288
|
-
if (self.width < width) {
|
|
289
|
-
self.width = width;
|
|
290
|
-
}
|
|
291
|
-
self.el.style.width = self.width + 'px';
|
|
292
|
-
// Height
|
|
293
|
-
self.height = 400;
|
|
294
|
-
// Animation for mobile
|
|
295
|
-
if (document.documentElement.clientWidth < 800) {
|
|
296
|
-
self.animation = true;
|
|
297
|
-
}
|
|
298
|
-
// Data to be listed
|
|
299
|
-
self.rows = self.data;
|
|
300
|
-
// Set the initial value
|
|
301
|
-
if (typeof(self.value) !== 'undefined') {
|
|
302
|
-
setValue(self.value);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
263
|
+
// Cursor controllers
|
|
306
264
|
const setCursor = function(index) {
|
|
307
265
|
let item = self.rows[index];
|
|
266
|
+
|
|
308
267
|
if (typeof(item) !== 'undefined') {
|
|
309
268
|
// Set cursor number
|
|
310
269
|
cursor = index;
|
|
311
270
|
// Set visual indication
|
|
312
271
|
item.cursor = true;
|
|
313
272
|
// Go to the item on the scroll in case the item is not on the viewport
|
|
314
|
-
if (! item.el
|
|
273
|
+
if (! (item.el && item.el.parentNode)) {
|
|
315
274
|
// Goto method
|
|
316
275
|
self.goto(item);
|
|
317
276
|
}
|
|
@@ -370,6 +329,55 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
370
329
|
setCursor(cursor);
|
|
371
330
|
}
|
|
372
331
|
|
|
332
|
+
const setData = function() {
|
|
333
|
+
// Estimate width
|
|
334
|
+
let width = self.width;
|
|
335
|
+
// Re-order to make sure groups are in sequence
|
|
336
|
+
if (self.data && self.data.length) {
|
|
337
|
+
self.data.sort((a, b) => {
|
|
338
|
+
// Compare groups
|
|
339
|
+
if (a.group && b.group) {
|
|
340
|
+
return a.group.localeCompare(b.group);
|
|
341
|
+
}
|
|
342
|
+
return 0;
|
|
343
|
+
});
|
|
344
|
+
let group = '';
|
|
345
|
+
// Define group headers
|
|
346
|
+
self.data.map((v) => {
|
|
347
|
+
// Compare groups
|
|
348
|
+
if (v && v.group && v.group !== group) {
|
|
349
|
+
v.header = true;
|
|
350
|
+
group = v.group;
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
// Width && values
|
|
354
|
+
self.data.map(function (s) {
|
|
355
|
+
// Estimated width of the element
|
|
356
|
+
if (s.text) {
|
|
357
|
+
width = Math.max(width, s.text.length * 8);
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
// Adjust the width
|
|
362
|
+
let w = self.input.offsetWidth;
|
|
363
|
+
if (width < w) {
|
|
364
|
+
width = w;
|
|
365
|
+
}
|
|
366
|
+
// Estimated with based on the text
|
|
367
|
+
if (self.width < width) {
|
|
368
|
+
self.width = width;
|
|
369
|
+
}
|
|
370
|
+
self.el.style.width = self.width + 'px';
|
|
371
|
+
// Height
|
|
372
|
+
self.height = 400;
|
|
373
|
+
// Animation for mobile
|
|
374
|
+
if (document.documentElement.clientWidth < 800) {
|
|
375
|
+
self.animation = true;
|
|
376
|
+
}
|
|
377
|
+
// Data to be listed
|
|
378
|
+
self.rows = self.data;
|
|
379
|
+
}
|
|
380
|
+
|
|
373
381
|
const updateLabel = function() {
|
|
374
382
|
if (value && value.length) {
|
|
375
383
|
self.input.textContent = value.filter(v => v.selected).map(i => i.text).join('; ');
|
|
@@ -394,22 +402,24 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
394
402
|
// Width && values
|
|
395
403
|
value = [];
|
|
396
404
|
|
|
397
|
-
self.data
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
s.
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
405
|
+
if (Array.isArray(self.data)) {
|
|
406
|
+
self.data.map(function(s) {
|
|
407
|
+
// Select values
|
|
408
|
+
if (newValue.indexOf(s.value) !== -1) {
|
|
409
|
+
s.selected = true;
|
|
410
|
+
value.push(s);
|
|
411
|
+
} else {
|
|
412
|
+
s.selected = false;
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
}
|
|
406
416
|
|
|
407
417
|
// Update label
|
|
408
418
|
updateLabel();
|
|
409
419
|
|
|
410
420
|
// Component onchange
|
|
411
421
|
if (typeof(onchange) === 'function') {
|
|
412
|
-
onchange(self,
|
|
422
|
+
onchange(self, value);
|
|
413
423
|
}
|
|
414
424
|
}
|
|
415
425
|
|
|
@@ -440,10 +450,18 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
440
450
|
// Clear input
|
|
441
451
|
self.input.textContent = '';
|
|
442
452
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
453
|
+
|
|
454
|
+
// Current value
|
|
455
|
+
let newValue = getValue();
|
|
456
|
+
|
|
457
|
+
// If that is different from the component value
|
|
458
|
+
if (! compareValues(newValue, self.value)) {
|
|
459
|
+
self.value = newValue;
|
|
460
|
+
} else {
|
|
461
|
+
// Update label
|
|
462
|
+
updateLabel();
|
|
463
|
+
}
|
|
464
|
+
|
|
447
465
|
// Identify the new state of the dropdown
|
|
448
466
|
self.state = false;
|
|
449
467
|
|
|
@@ -456,15 +474,14 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
456
474
|
self.state = true;
|
|
457
475
|
// Value
|
|
458
476
|
let v = value[value.length-1];
|
|
477
|
+
// Make sure goes back to the top of the scroll
|
|
478
|
+
if (self.container.parentNode.scrollTop > 0) {
|
|
479
|
+
self.container.parentNode.scrollTop = 0;
|
|
480
|
+
}
|
|
459
481
|
// Move to the correct position
|
|
460
482
|
if (v) {
|
|
461
|
-
// Go to the last item in the array of values
|
|
462
|
-
self.goto(v);
|
|
463
483
|
// Mark the position of the cursor to the same element
|
|
464
484
|
setCursor(self.rows.indexOf(v));
|
|
465
|
-
} else {
|
|
466
|
-
// Go to begin of the data
|
|
467
|
-
self.rows = self.data;
|
|
468
485
|
}
|
|
469
486
|
// Prepare search field
|
|
470
487
|
if (self.autocomplete) {
|
|
@@ -481,6 +498,46 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
481
498
|
}
|
|
482
499
|
}
|
|
483
500
|
|
|
501
|
+
|
|
502
|
+
self.add = async function(e) {
|
|
503
|
+
if (! self.input.textContent) {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
e.preventDefault();
|
|
508
|
+
|
|
509
|
+
// New item
|
|
510
|
+
let s = {
|
|
511
|
+
text: self.input.textContent,
|
|
512
|
+
value: self.input.textContent,
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Event
|
|
516
|
+
if (typeof(self.onbeforeinsert) === 'function') {
|
|
517
|
+
let elClass = self.el.classList;
|
|
518
|
+
elClass.add('lm-dropdown-loading');
|
|
519
|
+
let ret = await self.onbeforeinsert(self, s);
|
|
520
|
+
elClass.remove('lm-dropdown-loading');
|
|
521
|
+
if (ret === false) {
|
|
522
|
+
return;
|
|
523
|
+
} else if (ret) {
|
|
524
|
+
s = ret;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Process the data
|
|
529
|
+
self.data.push(s);
|
|
530
|
+
// Select the new item
|
|
531
|
+
self.select(e, s);
|
|
532
|
+
// Close dropdown
|
|
533
|
+
self.close();
|
|
534
|
+
|
|
535
|
+
// Event
|
|
536
|
+
if (typeof(self.oninsert) === 'function') {
|
|
537
|
+
self.oninsert(self, s);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
484
541
|
self.search = function(e) {
|
|
485
542
|
if (self.state && self.autocomplete) {
|
|
486
543
|
// Filter options
|
|
@@ -501,14 +558,10 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
501
558
|
}
|
|
502
559
|
}
|
|
503
560
|
|
|
504
|
-
let timer = null;
|
|
505
|
-
|
|
506
561
|
self.open = function () {
|
|
507
562
|
if (self.modal && self.modal.closed) {
|
|
508
563
|
// Open the modal
|
|
509
564
|
self.modal.closed = false;
|
|
510
|
-
// Timer
|
|
511
|
-
timer = setTimeout(() => timer = null, 400);
|
|
512
565
|
}
|
|
513
566
|
}
|
|
514
567
|
|
|
@@ -519,11 +572,7 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
519
572
|
}
|
|
520
573
|
}
|
|
521
574
|
|
|
522
|
-
self.toggle = function(
|
|
523
|
-
if (timer) {
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
|
|
575
|
+
self.toggle = function() {
|
|
527
576
|
if (self.modal) {
|
|
528
577
|
if (self.modal.closed) {
|
|
529
578
|
self.open();
|
|
@@ -534,16 +583,20 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
534
583
|
}
|
|
535
584
|
|
|
536
585
|
self.click = function(e) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
586
|
+
if (self.autocomplete) {
|
|
587
|
+
let x;
|
|
588
|
+
if (e.changedTouches && e.changedTouches[0]) {
|
|
589
|
+
x = e.changedTouches[0].clientX;
|
|
590
|
+
} else {
|
|
591
|
+
x = e.clientX;
|
|
592
|
+
}
|
|
593
|
+
if (e.target.offsetWidth - (x - e.target.offsetLeft) < 20) {
|
|
594
|
+
self.toggle();
|
|
595
|
+
} else {
|
|
596
|
+
self.open();
|
|
597
|
+
}
|
|
540
598
|
} else {
|
|
541
|
-
x = e.clientX;
|
|
542
|
-
}
|
|
543
|
-
if (e.target.offsetWidth - (x - e.target.offsetLeft) < 20) {
|
|
544
599
|
self.toggle();
|
|
545
|
-
} else {
|
|
546
|
-
self.open();
|
|
547
600
|
}
|
|
548
601
|
}
|
|
549
602
|
|
|
@@ -611,6 +664,10 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
611
664
|
lazyloading = lazyLoading(self);
|
|
612
665
|
// Process the data
|
|
613
666
|
setData();
|
|
667
|
+
// Se value
|
|
668
|
+
if (self.value) {
|
|
669
|
+
setValue(self.value);
|
|
670
|
+
}
|
|
614
671
|
// Focus out of the component
|
|
615
672
|
self.el.addEventListener('focusout', function(e) {
|
|
616
673
|
if (self.modal) {
|
|
@@ -623,32 +680,38 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
623
680
|
})
|
|
624
681
|
// Key events
|
|
625
682
|
self.el.addEventListener('keydown', function(e) {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
prevent = true;
|
|
640
|
-
} else {
|
|
641
|
-
if (e.keyCode === 32 && ! self.autocomplete) {
|
|
683
|
+
if (! self.modal.closed) {
|
|
684
|
+
let prevent = false;
|
|
685
|
+
if (e.key === 'ArrowUp') {
|
|
686
|
+
moveCursor(-1);
|
|
687
|
+
prevent = true;
|
|
688
|
+
} else if (e.key === 'ArrowDown') {
|
|
689
|
+
moveCursor(1);
|
|
690
|
+
prevent = true;
|
|
691
|
+
} else if (e.key === 'Home') {
|
|
692
|
+
moveCursor(-1, true);
|
|
693
|
+
} else if (e.key === 'End') {
|
|
694
|
+
moveCursor(1, true);
|
|
695
|
+
} else if (e.key === 'Enter') {
|
|
642
696
|
self.select(e, self.rows[cursor]);
|
|
697
|
+
prevent = true;
|
|
698
|
+
} else {
|
|
699
|
+
if (e.keyCode === 32 && !self.autocomplete) {
|
|
700
|
+
self.select(e, self.rows[cursor]);
|
|
701
|
+
}
|
|
643
702
|
}
|
|
644
|
-
}
|
|
645
703
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
704
|
+
if (prevent) {
|
|
705
|
+
e.preventDefault();
|
|
706
|
+
e.stopImmediatePropagation();
|
|
707
|
+
}
|
|
708
|
+
} else {
|
|
709
|
+
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
710
|
+
self.modal.closed = false;
|
|
711
|
+
}
|
|
649
712
|
}
|
|
650
713
|
});
|
|
651
|
-
|
|
714
|
+
// Custom event by the developer
|
|
652
715
|
if (typeof(onload) === 'function') {
|
|
653
716
|
onload(self);
|
|
654
717
|
}
|
|
@@ -659,6 +722,7 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
659
722
|
setValue(self.value);
|
|
660
723
|
} else if (prop === 'data') {
|
|
661
724
|
setData();
|
|
725
|
+
self.value = null;
|
|
662
726
|
}
|
|
663
727
|
|
|
664
728
|
if (typeof(lazyloading) === 'function') {
|
|
@@ -682,48 +746,9 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
682
746
|
e.preventDefault();
|
|
683
747
|
}
|
|
684
748
|
|
|
685
|
-
self.
|
|
686
|
-
if (! self.input.textContent) {
|
|
687
|
-
return false;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
e.preventDefault();
|
|
691
|
-
|
|
692
|
-
// New item
|
|
693
|
-
let s = {
|
|
694
|
-
text: self.input.textContent,
|
|
695
|
-
value: self.input.textContent,
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
// Event
|
|
699
|
-
if (typeof(self.onbeforeinsert) === 'function') {
|
|
700
|
-
let elClass = self.el.classList;
|
|
701
|
-
elClass.add('lm-dropdown-loading');
|
|
702
|
-
let ret = await self.onbeforeinsert(self, s);
|
|
703
|
-
elClass.remove('lm-dropdown-loading');
|
|
704
|
-
if (ret === false) {
|
|
705
|
-
return;
|
|
706
|
-
} else if (ret) {
|
|
707
|
-
s = ret;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// Process the data
|
|
712
|
-
self.data.push(s);
|
|
713
|
-
// Select the new item
|
|
714
|
-
self.select(e, s);
|
|
715
|
-
// Close dropdown
|
|
716
|
-
self.close();
|
|
717
|
-
|
|
718
|
-
// Event
|
|
719
|
-
if (typeof(self.oninsert) === 'function') {
|
|
720
|
-
self.oninsert(self, s);
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
return `<div class="lm-dropdown" data-insert="{{self.insert}}" data-type="{{self.type}}" data-state="{{self.state}}" :value="self.value">
|
|
749
|
+
return `<div class="lm-dropdown" data-insert="{{self.insert}}" data-type="{{self.type}}" data-state="{{self.state}}" :value="self.value" :data="self.data">
|
|
725
750
|
<div class="lm-dropdown-header">
|
|
726
|
-
<div class="lm-dropdown-input" onpaste="self.onpaste" oninput="self.search" onfocus="self.open"
|
|
751
|
+
<div class="lm-dropdown-input" onpaste="self.onpaste" oninput="self.search" onfocus="self.open" onmousedown="self.click" placeholder="{{self.placeholder}}" :ref="self.input" tabindex="0"></div>
|
|
727
752
|
<div class="lm-dropdown-add" onmousedown="self.add"></div>
|
|
728
753
|
<button onclick="self.close" class="lm-dropdown-done">Done</button>
|
|
729
754
|
</div>
|
package/dist/style.css
CHANGED
package/package.json
CHANGED