@materializecss/materialize 1.2.2 → 2.0.0-alpha
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/Gruntfile.js +68 -313
- package/README.md +2 -2
- package/dist/css/materialize.css +1009 -1822
- package/dist/css/materialize.min.css +2 -8
- package/dist/js/materialize.js +8402 -12300
- package/dist/js/materialize.min.js +3 -2
- package/dist/js/materialize.min.js.map +1 -0
- package/package.json +13 -9
- package/sass/components/_badges.scss +12 -2
- package/sass/components/_buttons.scss +16 -11
- package/sass/components/_cards.scss +14 -9
- package/sass/components/_carousel.scss +5 -2
- package/sass/components/_chips.scss +3 -3
- package/sass/components/_collapsible.scss +22 -8
- package/sass/components/_collection.scss +14 -6
- package/sass/components/_datepicker.scss +30 -11
- package/sass/components/_dropdown.scss +6 -4
- package/sass/components/_global.scss +132 -111
- package/sass/components/_grid.scss +119 -98
- package/sass/components/_modal.scss +3 -3
- package/sass/components/_navbar.scss +31 -17
- package/sass/components/_normalize.scss +26 -124
- package/sass/components/_sidenav.scss +21 -20
- package/sass/components/_slider.scss +27 -7
- package/sass/components/_table_of_contents.scss +12 -12
- package/sass/components/_tabs.scss +47 -16
- package/sass/components/_tapTarget.scss +6 -6
- package/sass/components/_timepicker.scss +54 -46
- package/sass/components/_toast.scss +3 -3
- package/sass/components/_tooltip.scss +4 -5
- package/sass/components/_typography.scss +1 -1
- package/sass/components/_variables.scss +185 -120
- package/sass/components/forms/_checkboxes.scss +9 -9
- package/sass/components/forms/_file-input.scss +9 -7
- package/sass/components/forms/_input-fields.scss +173 -234
- package/sass/components/forms/_radio-buttons.scss +1 -1
- package/sass/components/forms/_range.scss +11 -11
- package/sass/components/forms/_select.scss +29 -19
- package/sass/components/forms/_switches.scss +22 -18
- package/sass/materialize.scss +1 -1
- package/src/autocomplete.ts +459 -0
- package/src/bounding.ts +6 -0
- package/{js/buttons.js → src/buttons.ts} +103 -162
- package/src/cards.ts +54 -0
- package/{js/carousel.js → src/carousel.ts} +137 -262
- package/src/characterCounter.ts +88 -0
- package/src/chips.ts +350 -0
- package/src/collapsible.ts +184 -0
- package/{js/component.js → src/component.ts} +6 -19
- package/{js/datepicker.js → src/datepicker.ts} +213 -299
- package/{js/dropdown.js → src/dropdown.ts} +140 -254
- package/src/edges.ts +6 -0
- package/src/forms.ts +120 -0
- package/src/global.ts +385 -0
- package/src/materialbox.ts +348 -0
- package/src/modal.ts +256 -0
- package/{js/parallax.js → src/parallax.ts} +47 -60
- package/{js/pushpin.js → src/pushpin.ts} +19 -47
- package/{js/range.js → src/range.ts} +58 -139
- package/{js/scrollspy.js → src/scrollspy.ts} +81 -153
- package/src/select.ts +448 -0
- package/{js/sidenav.js → src/sidenav.ts} +96 -202
- package/src/slider.ts +415 -0
- package/src/tabs.ts +290 -0
- package/src/tapTarget.ts +240 -0
- package/{js/timepicker.js → src/timepicker.ts} +268 -272
- package/{js/toasts.js → src/toasts.ts} +75 -134
- package/{js/tooltip.js → src/tooltip.ts} +59 -96
- package/src/waves.ts +70 -0
- package/extras/noUiSlider/nouislider.css +0 -404
- package/extras/noUiSlider/nouislider.js +0 -2147
- package/extras/noUiSlider/nouislider.min.js +0 -1
- package/js/anime.min.js +0 -34
- package/js/autocomplete.js +0 -479
- package/js/cards.js +0 -40
- package/js/cash.js +0 -960
- package/js/characterCounter.js +0 -136
- package/js/chips.js +0 -486
- package/js/collapsible.js +0 -275
- package/js/forms.js +0 -285
- package/js/global.js +0 -428
- package/js/materialbox.js +0 -453
- package/js/modal.js +0 -382
- package/js/select.js +0 -391
- package/js/slider.js +0 -497
- package/js/tabs.js +0 -402
- package/js/tapTarget.js +0 -315
- package/js/waves.js +0 -615
- package/sass/components/_waves.scss +0 -187
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/* Select Field
|
|
2
2
|
========================================================================== */
|
|
3
3
|
|
|
4
|
-
select.browser-default {
|
|
4
|
+
select.browser-default {
|
|
5
|
+
opacity: 1;
|
|
6
|
+
color: $select-input-color;
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
select {
|
|
6
10
|
opacity: 0;
|
|
7
11
|
background-color: $select-background;
|
|
@@ -12,11 +16,13 @@ select {
|
|
|
12
16
|
height: $input-height;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
.select-label {
|
|
16
|
-
|
|
17
|
-
}
|
|
19
|
+
// .select-label {
|
|
20
|
+
// position: absolute;
|
|
21
|
+
// }
|
|
22
|
+
|
|
18
23
|
|
|
19
24
|
.select-wrapper {
|
|
25
|
+
/*
|
|
20
26
|
&.valid .helper-text[data-success],
|
|
21
27
|
&.invalid ~ .helper-text[data-error] {
|
|
22
28
|
@extend %hidden-text;
|
|
@@ -26,9 +32,8 @@ select {
|
|
|
26
32
|
& > input.select-dropdown {
|
|
27
33
|
@extend %valid-input-style;
|
|
28
34
|
}
|
|
29
|
-
|
|
30
35
|
& ~ .helper-text:after {
|
|
31
|
-
|
|
36
|
+
//@extend %custom-success-message;
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
|
|
@@ -37,9 +42,8 @@ select {
|
|
|
37
42
|
& > input.select-dropdown:focus {
|
|
38
43
|
@extend %invalid-input-style;
|
|
39
44
|
}
|
|
40
|
-
|
|
41
45
|
& ~ .helper-text:after {
|
|
42
|
-
|
|
46
|
+
//@extend %custom-error-message;
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
@@ -48,14 +52,17 @@ select {
|
|
|
48
52
|
width: 100%;
|
|
49
53
|
pointer-events: none;
|
|
50
54
|
}
|
|
51
|
-
|
|
52
55
|
& + label:after {
|
|
53
|
-
|
|
56
|
+
//@extend %input-after-style;
|
|
54
57
|
}
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
|
|
55
61
|
|
|
56
62
|
position: relative;
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
/*
|
|
65
|
+
input.select-dropdown {
|
|
59
66
|
&:focus {
|
|
60
67
|
border-bottom: 1px solid $input-focus-color;
|
|
61
68
|
}
|
|
@@ -74,7 +81,9 @@ select {
|
|
|
74
81
|
display: block;
|
|
75
82
|
user-select:none;
|
|
76
83
|
z-index: 1;
|
|
84
|
+
color: $select-input-color;
|
|
77
85
|
}
|
|
86
|
+
*/
|
|
78
87
|
|
|
79
88
|
.caret {
|
|
80
89
|
position: absolute;
|
|
@@ -83,14 +92,16 @@ select {
|
|
|
83
92
|
bottom: 0;
|
|
84
93
|
margin: auto 0;
|
|
85
94
|
z-index: 0;
|
|
86
|
-
fill:
|
|
95
|
+
fill: $select-input-color;
|
|
87
96
|
}
|
|
88
97
|
|
|
98
|
+
/*
|
|
89
99
|
& + label {
|
|
90
100
|
position: absolute;
|
|
91
101
|
top: -26px;
|
|
92
102
|
font-size: $label-font-size;
|
|
93
103
|
}
|
|
104
|
+
*/
|
|
94
105
|
|
|
95
106
|
// Hide select with overflow hidden instead of using display none
|
|
96
107
|
// (this prevents form validation errors with hidden form elements)
|
|
@@ -143,33 +154,32 @@ body.keyboard-focused {
|
|
|
143
154
|
|
|
144
155
|
.select-dropdown.dropdown-content {
|
|
145
156
|
li {
|
|
146
|
-
&:hover {
|
|
157
|
+
&:hover:not(.disabled) {
|
|
147
158
|
background-color: $select-option-hover;
|
|
148
159
|
}
|
|
149
160
|
|
|
150
|
-
&.selected {
|
|
161
|
+
&.selected:not(.disabled) {
|
|
151
162
|
background-color: $select-option-selected;
|
|
152
163
|
}
|
|
153
164
|
}
|
|
154
165
|
}
|
|
155
166
|
|
|
167
|
+
/*
|
|
156
168
|
// Prefix Icons
|
|
157
169
|
.prefix ~ .select-wrapper {
|
|
158
170
|
margin-left: 3rem;
|
|
159
171
|
width: 92%;
|
|
160
172
|
width: calc(100% - 3rem);
|
|
161
173
|
}
|
|
162
|
-
|
|
163
174
|
.prefix ~ label { margin-left: 3rem; }
|
|
164
|
-
|
|
165
175
|
// Suffix Icons
|
|
166
176
|
.suffix ~ .select-wrapper {
|
|
167
177
|
margin-right: 3rem;
|
|
168
178
|
width: 92%;
|
|
169
179
|
width: calc(100% - 3rem);
|
|
170
180
|
}
|
|
171
|
-
|
|
172
181
|
.suffix ~ label { margin-right: 3rem; }
|
|
182
|
+
*/
|
|
173
183
|
|
|
174
184
|
// Icons
|
|
175
185
|
.select-dropdown li {
|
|
@@ -186,11 +196,11 @@ body.keyboard-focused {
|
|
|
186
196
|
border-top: 1px solid $dropdown-hover-bg-color;
|
|
187
197
|
|
|
188
198
|
&.selected > span {
|
|
189
|
-
color:
|
|
199
|
+
color: $font-color-main;
|
|
190
200
|
}
|
|
191
201
|
|
|
192
202
|
& > span {
|
|
193
|
-
color:
|
|
203
|
+
color: $font-color-medium;
|
|
194
204
|
}
|
|
195
205
|
|
|
196
206
|
& ~ li.optgroup-option {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
width: 0;
|
|
17
17
|
height: 0;
|
|
18
18
|
|
|
19
|
-
&:checked
|
|
20
|
-
background-color: $switch-checked-
|
|
19
|
+
&:checked + .lever{
|
|
20
|
+
background-color: $switch-track-checked-bg;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
&:checked + .lever {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
&:after {
|
|
29
|
-
background-color: $switch-
|
|
29
|
+
background-color: $switch-thumb-checked-color;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
position: relative;
|
|
38
38
|
width: 36px;
|
|
39
39
|
height: 14px;
|
|
40
|
-
background-color: $switch-unchecked-
|
|
40
|
+
background-color: $switch-track-unchecked-bg;
|
|
41
41
|
border-radius: $switch-radius;
|
|
42
42
|
margin-right: 10px;
|
|
43
43
|
transition: background 0.3s ease;
|
|
@@ -56,36 +56,40 @@
|
|
|
56
56
|
transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
&:before {
|
|
60
|
-
background-color: transparentize($switch-bg-color, .85);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
59
|
&:after {
|
|
64
|
-
background-color: $switch-unchecked-
|
|
60
|
+
background-color: $switch-thumb-unchecked-color;
|
|
65
61
|
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
|
|
66
62
|
}
|
|
67
63
|
}
|
|
68
64
|
|
|
65
|
+
input[type=checkbox]:not(:disabled) ~ .lever:active:before,
|
|
66
|
+
input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before,
|
|
67
|
+
input[type=checkbox]:not(:disabled) ~ .lever:hover::before {
|
|
68
|
+
transform: scale(2.4);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
input[type=checkbox]:checked:not(:disabled) ~ .lever:hover::before {
|
|
72
|
+
background-color: $switch-reaction-checked-hover-color;
|
|
73
|
+
}
|
|
74
|
+
|
|
69
75
|
// Switch active style
|
|
70
76
|
input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before,
|
|
71
77
|
input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::before {
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
background-color: $switch-reaction-checked-focus-color;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
input[type=checkbox]:not(:disabled) ~ .lever:hover::before {
|
|
82
|
+
background-color: $switch-reaction-unchecked-hover-color;
|
|
74
83
|
}
|
|
75
84
|
|
|
76
85
|
input[type=checkbox]:not(:disabled) ~ .lever:active:before,
|
|
77
86
|
input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before {
|
|
78
|
-
|
|
79
|
-
background-color: rgba(0,0,0,.08);
|
|
87
|
+
background-color: $switch-reaction-unchecked-focus-color;
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
// Disabled Styles
|
|
83
91
|
.switch input[type=checkbox][disabled] + .lever {
|
|
84
92
|
cursor: default;
|
|
85
|
-
|
|
93
|
+
opacity: 0.5;
|
|
86
94
|
}
|
|
87
95
|
|
|
88
|
-
.switch label input[type=checkbox][disabled] + .lever:after,
|
|
89
|
-
.switch label input[type=checkbox][disabled]:checked + .lever:after {
|
|
90
|
-
background-color: $input-disabled-solid-color;
|
|
91
|
-
}
|
package/sass/materialize.scss
CHANGED
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
@import "components/tooltip";
|
|
26
26
|
@import "components/buttons";
|
|
27
27
|
@import "components/dropdown";
|
|
28
|
-
@import "components/waves";
|
|
29
28
|
@import "components/modal";
|
|
30
29
|
@import "components/collapsible";
|
|
31
30
|
@import "components/chips";
|
|
@@ -40,3 +39,4 @@
|
|
|
40
39
|
@import "components/pulse";
|
|
41
40
|
@import "components/datepicker";
|
|
42
41
|
@import "components/timepicker";
|
|
42
|
+
@import "components/_theme_variables";
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import { Component } from "./component";
|
|
2
|
+
import { M } from "./global";
|
|
3
|
+
import { Dropdown } from "./dropdown";
|
|
4
|
+
|
|
5
|
+
let _defaults = {
|
|
6
|
+
data: [], // Autocomplete data set
|
|
7
|
+
onAutocomplete: null, // Callback for when autocompleted
|
|
8
|
+
dropdownOptions: {
|
|
9
|
+
// Default dropdown options
|
|
10
|
+
autoFocus: false,
|
|
11
|
+
closeOnClick: false,
|
|
12
|
+
coverTrigger: false
|
|
13
|
+
},
|
|
14
|
+
minLength: 1, // Min characters before autocomplete starts
|
|
15
|
+
isMultiSelect: false,
|
|
16
|
+
onSearch: function(text, autocomplete) {
|
|
17
|
+
const filteredData = autocomplete.options.data.filter(item => {
|
|
18
|
+
return Object.keys(item)
|
|
19
|
+
.map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
|
|
20
|
+
.some(isMatch => isMatch);
|
|
21
|
+
});
|
|
22
|
+
autocomplete.setMenuItems(filteredData);
|
|
23
|
+
},
|
|
24
|
+
maxDropDownHeight: '300px',
|
|
25
|
+
allowUnsafeHTML: false
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export class Autocomplete extends Component {
|
|
30
|
+
el: HTMLInputElement;
|
|
31
|
+
isOpen: boolean;
|
|
32
|
+
count: number;
|
|
33
|
+
activeIndex: number;
|
|
34
|
+
private oldVal: any;
|
|
35
|
+
private $inputField: any;
|
|
36
|
+
private $active: HTMLElement|null;
|
|
37
|
+
private _mousedown: boolean;
|
|
38
|
+
private _handleInputBlurBound: any;
|
|
39
|
+
private _handleInputKeyupAndFocusBound: any;
|
|
40
|
+
private _handleInputKeydownBound: any;
|
|
41
|
+
private _handleInputClickBound: any;
|
|
42
|
+
private _handleContainerMousedownAndTouchstartBound: any;
|
|
43
|
+
private _handleContainerMouseupAndTouchendBound: any;
|
|
44
|
+
container: HTMLElement;
|
|
45
|
+
dropdown: Dropdown;
|
|
46
|
+
static _keydown: boolean;
|
|
47
|
+
selectedValues: any[];
|
|
48
|
+
menuItems: any[];
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
constructor(el, options) {
|
|
52
|
+
super(Autocomplete, el, options);
|
|
53
|
+
(this.el as any).M_Autocomplete = this;
|
|
54
|
+
this.options = {...Autocomplete.defaults, ...options};
|
|
55
|
+
this.isOpen = false;
|
|
56
|
+
this.count = 0;
|
|
57
|
+
this.activeIndex = -1;
|
|
58
|
+
this.oldVal;
|
|
59
|
+
this.selectedValues = [];
|
|
60
|
+
this.menuItems = [];
|
|
61
|
+
this.$active = null;
|
|
62
|
+
this._mousedown = false;
|
|
63
|
+
this._setupDropdown();
|
|
64
|
+
this._setupEventHandlers();
|
|
65
|
+
}
|
|
66
|
+
static get defaults() {
|
|
67
|
+
return _defaults;
|
|
68
|
+
}
|
|
69
|
+
static init(els, options) {
|
|
70
|
+
return super.init(this, els, options);
|
|
71
|
+
}
|
|
72
|
+
static getInstance(el) {
|
|
73
|
+
let domElem = el.jquery ? el[0] : el;
|
|
74
|
+
return domElem.M_Autocomplete;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
destroy() {
|
|
78
|
+
this._removeEventHandlers();
|
|
79
|
+
this._removeDropdown();
|
|
80
|
+
(this.el as any).M_Autocomplete = undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_setupEventHandlers() {
|
|
84
|
+
this._handleInputBlurBound = this._handleInputBlur.bind(this);
|
|
85
|
+
this._handleInputKeyupAndFocusBound = this._handleInputKeyupAndFocus.bind(this);
|
|
86
|
+
this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
|
|
87
|
+
this._handleInputClickBound = this._handleInputClick.bind(this);
|
|
88
|
+
this._handleContainerMousedownAndTouchstartBound = this._handleContainerMousedownAndTouchstart.bind(
|
|
89
|
+
this
|
|
90
|
+
);
|
|
91
|
+
this._handleContainerMouseupAndTouchendBound = this._handleContainerMouseupAndTouchend.bind(
|
|
92
|
+
this
|
|
93
|
+
);
|
|
94
|
+
this.el.addEventListener('blur', this._handleInputBlurBound);
|
|
95
|
+
this.el.addEventListener('keyup', this._handleInputKeyupAndFocusBound);
|
|
96
|
+
this.el.addEventListener('focus', this._handleInputKeyupAndFocusBound);
|
|
97
|
+
this.el.addEventListener('keydown', this._handleInputKeydownBound);
|
|
98
|
+
this.el.addEventListener('click', this._handleInputClickBound);
|
|
99
|
+
this.container.addEventListener(
|
|
100
|
+
'mousedown',
|
|
101
|
+
this._handleContainerMousedownAndTouchstartBound
|
|
102
|
+
);
|
|
103
|
+
this.container.addEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
|
|
104
|
+
if (typeof window.ontouchstart !== 'undefined') {
|
|
105
|
+
this.container.addEventListener(
|
|
106
|
+
'touchstart',
|
|
107
|
+
this._handleContainerMousedownAndTouchstartBound
|
|
108
|
+
);
|
|
109
|
+
this.container.addEventListener('touchend', this._handleContainerMouseupAndTouchendBound);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_removeEventHandlers() {
|
|
114
|
+
this.el.removeEventListener('blur', this._handleInputBlurBound);
|
|
115
|
+
this.el.removeEventListener('keyup', this._handleInputKeyupAndFocusBound);
|
|
116
|
+
this.el.removeEventListener('focus', this._handleInputKeyupAndFocusBound);
|
|
117
|
+
this.el.removeEventListener('keydown', this._handleInputKeydownBound);
|
|
118
|
+
this.el.removeEventListener('click', this._handleInputClickBound);
|
|
119
|
+
this.container.removeEventListener(
|
|
120
|
+
'mousedown',
|
|
121
|
+
this._handleContainerMousedownAndTouchstartBound
|
|
122
|
+
);
|
|
123
|
+
this.container.removeEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
|
|
124
|
+
|
|
125
|
+
if (typeof window.ontouchstart !== 'undefined') {
|
|
126
|
+
this.container.removeEventListener(
|
|
127
|
+
'touchstart',
|
|
128
|
+
this._handleContainerMousedownAndTouchstartBound
|
|
129
|
+
);
|
|
130
|
+
this.container.removeEventListener(
|
|
131
|
+
'touchend',
|
|
132
|
+
this._handleContainerMouseupAndTouchendBound
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
_setupDropdown() {
|
|
138
|
+
this.container = document.createElement('ul');
|
|
139
|
+
this.container.style.maxHeight = this.options.maxDropDownHeight;
|
|
140
|
+
this.container.id = `autocomplete-options-${M.guid()}`;
|
|
141
|
+
this.container.classList.add('autocomplete-content', 'dropdown-content');
|
|
142
|
+
this.el.setAttribute('data-target', this.container.id);
|
|
143
|
+
|
|
144
|
+
// ! Issue in Component Dropdown: _placeDropdown moves dom-position
|
|
145
|
+
this.el.parentElement.appendChild(this.container);
|
|
146
|
+
|
|
147
|
+
// Initialize dropdown
|
|
148
|
+
let dropdownOptions = {
|
|
149
|
+
...Autocomplete.defaults.dropdownOptions,
|
|
150
|
+
...this.options.dropdownOptions
|
|
151
|
+
};
|
|
152
|
+
let userOnItemClick = dropdownOptions.onItemClick;
|
|
153
|
+
// Ensuring the select Option call when user passes custom onItemClick function to dropdown
|
|
154
|
+
dropdownOptions.onItemClick = (li) => {
|
|
155
|
+
if (!li) return;
|
|
156
|
+
const entryID = li.getAttribute('data-id');
|
|
157
|
+
this.selectOption(entryID);
|
|
158
|
+
// Handle user declared onItemClick if needed
|
|
159
|
+
if (userOnItemClick && typeof userOnItemClick === 'function')
|
|
160
|
+
userOnItemClick.call(this.dropdown, this.el);
|
|
161
|
+
};
|
|
162
|
+
this.dropdown = M.Dropdown.init(this.el, dropdownOptions);
|
|
163
|
+
|
|
164
|
+
// ! Workaround for Label: move label up again
|
|
165
|
+
// TODO: Just use PopperJS in future!
|
|
166
|
+
const label = this.el.parentElement.querySelector('label');
|
|
167
|
+
if (label) this.el.after(label);
|
|
168
|
+
|
|
169
|
+
// Sketchy removal of dropdown click handler
|
|
170
|
+
this.el.removeEventListener('click', this.dropdown._handleClickBound);
|
|
171
|
+
// Set Value if already set in HTML
|
|
172
|
+
if (this.el.value) this.selectOption(this.el.value);
|
|
173
|
+
// Add StatusInfo
|
|
174
|
+
const div = document.createElement('div');
|
|
175
|
+
div.classList.add('status-info');
|
|
176
|
+
div.setAttribute('style', 'position: absolute;right:0;top:0;');
|
|
177
|
+
this.el.parentElement.appendChild(div);
|
|
178
|
+
this._updateSelectedInfo();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
_removeDropdown() {
|
|
182
|
+
this.container.parentNode.removeChild(this.container);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
_handleInputBlur() {
|
|
186
|
+
if (!this._mousedown) {
|
|
187
|
+
this.close();
|
|
188
|
+
this._resetAutocomplete();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
_handleInputKeyupAndFocus(e) {
|
|
193
|
+
if (e.type === 'keyup') Autocomplete._keydown = false;
|
|
194
|
+
this.count = 0;
|
|
195
|
+
const actualValue = this.el.value.toLowerCase();
|
|
196
|
+
// Don't capture enter or arrow key usage.
|
|
197
|
+
if (e.keyCode === 13 || e.keyCode === 38 || e.keyCode === 40) return;
|
|
198
|
+
// Check if the input isn't empty
|
|
199
|
+
// Check if focus triggered by tab
|
|
200
|
+
if (this.oldVal !== actualValue && (M.tabPressed || e.type !== 'focus')) {
|
|
201
|
+
this.open();
|
|
202
|
+
}
|
|
203
|
+
// Value has changed!
|
|
204
|
+
if (this.oldVal !== actualValue) {
|
|
205
|
+
this._setStatusLoading();
|
|
206
|
+
this.options.onSearch(this.el.value, this);
|
|
207
|
+
}
|
|
208
|
+
// Reset Single-Select when Input cleared
|
|
209
|
+
if (!this.options.isMultiSelect && this.el.value.length === 0) {
|
|
210
|
+
this.selectedValues = [];
|
|
211
|
+
this._triggerChanged();
|
|
212
|
+
}
|
|
213
|
+
this.oldVal = actualValue;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
_handleInputKeydown(e) {
|
|
217
|
+
Autocomplete._keydown = true;
|
|
218
|
+
// Arrow keys and enter key usage
|
|
219
|
+
const keyCode = e.keyCode;
|
|
220
|
+
const numItems = this.container.querySelectorAll('li').length;
|
|
221
|
+
// select element on Enter
|
|
222
|
+
if (keyCode === M.keys.ENTER && this.activeIndex >= 0) {
|
|
223
|
+
const liElement = this.container.querySelectorAll('li')[this.activeIndex];
|
|
224
|
+
if (liElement) {
|
|
225
|
+
this.selectOption(liElement.getAttribute('data-id'));
|
|
226
|
+
e.preventDefault();
|
|
227
|
+
}
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Capture up and down key
|
|
231
|
+
if (keyCode === M.keys.ARROW_UP || keyCode === M.keys.ARROW_DOWN) {
|
|
232
|
+
e.preventDefault();
|
|
233
|
+
if (keyCode === M.keys.ARROW_UP && this.activeIndex > 0) this.activeIndex--;
|
|
234
|
+
if (keyCode === M.keys.ARROW_DOWN && this.activeIndex < numItems - 1) this.activeIndex++;
|
|
235
|
+
this.$active?.classList.remove('active');
|
|
236
|
+
if (this.activeIndex >= 0) {
|
|
237
|
+
this.$active = this.container.querySelectorAll('li')[this.activeIndex];
|
|
238
|
+
this.$active?.classList.add('active');
|
|
239
|
+
// Focus selected
|
|
240
|
+
this.container.children[this.activeIndex].scrollIntoView({
|
|
241
|
+
behavior: 'smooth',
|
|
242
|
+
block: 'nearest',
|
|
243
|
+
inline: 'nearest'
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
_handleInputClick(e) {
|
|
250
|
+
this.open();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
_handleContainerMousedownAndTouchstart(e) {
|
|
254
|
+
this._mousedown = true;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
_handleContainerMouseupAndTouchend(e) {
|
|
258
|
+
this._mousedown = false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
_resetCurrentElementPosition() {
|
|
262
|
+
this.activeIndex = -1;
|
|
263
|
+
this.$active?.classList.remove('active');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
_resetAutocomplete() {
|
|
267
|
+
this.container.replaceChildren();
|
|
268
|
+
this._resetCurrentElementPosition();
|
|
269
|
+
this.oldVal = null;
|
|
270
|
+
this.isOpen = false;
|
|
271
|
+
this._mousedown = false;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
_highlightPartialText(input, label) {
|
|
275
|
+
const start = label.toLowerCase().indexOf('' + input.toLowerCase() + '');
|
|
276
|
+
const end = start + input.length - 1;
|
|
277
|
+
//custom filters may return results where the string does not match any part
|
|
278
|
+
if (start == -1 || end == -1) {
|
|
279
|
+
return [label, '', ''];
|
|
280
|
+
}
|
|
281
|
+
return [label.slice(0, start), label.slice(start, end + 1), label.slice(end + 1)];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
_createDropdownItem(entry) {
|
|
285
|
+
const item = document.createElement('li');
|
|
286
|
+
item.setAttribute('data-id', entry.id);
|
|
287
|
+
item.setAttribute(
|
|
288
|
+
'style',
|
|
289
|
+
'display:grid; grid-auto-flow: column; user-select: none; align-items: center;'
|
|
290
|
+
);
|
|
291
|
+
// Checkbox
|
|
292
|
+
if (this.options.isMultiSelect) {
|
|
293
|
+
item.innerHTML = `
|
|
294
|
+
<div class="item-selection" style="text-align:center;">
|
|
295
|
+
<input type="checkbox"${
|
|
296
|
+
this.selectedValues.some((sel) => sel.id === entry.id) ? ' checked="checked"' : ''
|
|
297
|
+
}><span style="padding-left:21px;"></span>
|
|
298
|
+
</div>`;
|
|
299
|
+
}
|
|
300
|
+
// Image
|
|
301
|
+
if (entry.image) {
|
|
302
|
+
const img = document.createElement('img');
|
|
303
|
+
img.classList.add('circle');
|
|
304
|
+
img.src = entry.image;
|
|
305
|
+
item.appendChild(img);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Text
|
|
309
|
+
const inputText = this.el.value.toLowerCase();
|
|
310
|
+
const parts = this._highlightPartialText(inputText, (entry.text || entry.id).toString());
|
|
311
|
+
const div = document.createElement('div');
|
|
312
|
+
div.setAttribute('style', 'line-height:1.2;font-weight:500;');
|
|
313
|
+
if (this.options.allowUnsafeHTML) {
|
|
314
|
+
div.innerHTML = parts[0] + '<span class="highlight">' + parts[1] + '</span>' + parts[2];
|
|
315
|
+
} else {
|
|
316
|
+
div.appendChild(document.createTextNode(parts[0]));
|
|
317
|
+
if (parts[1]) {
|
|
318
|
+
const highlight = document.createElement('span');
|
|
319
|
+
highlight.textContent = parts[1];
|
|
320
|
+
highlight.classList.add('highlight');
|
|
321
|
+
div.appendChild(highlight);
|
|
322
|
+
div.appendChild(document.createTextNode(parts[2]));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const itemText = document.createElement('div');
|
|
327
|
+
itemText.classList.add('item-text');
|
|
328
|
+
itemText.setAttribute('style', 'padding:5px;overflow:hidden;');
|
|
329
|
+
item.appendChild(itemText);
|
|
330
|
+
item.querySelector('.item-text').appendChild(div);
|
|
331
|
+
// Description
|
|
332
|
+
if (typeof entry.description === 'string' || (typeof entry.description === 'number' && !isNaN(entry.description))) {
|
|
333
|
+
const description = document.createElement('small');
|
|
334
|
+
description.setAttribute(
|
|
335
|
+
'style',
|
|
336
|
+
'line-height:1.3;color:grey;white-space:nowrap;text-overflow:ellipsis;display:block;width:90%;overflow:hidden;'
|
|
337
|
+
);
|
|
338
|
+
description.innerText = entry.description;
|
|
339
|
+
item.querySelector('.item-text').appendChild(description);
|
|
340
|
+
}
|
|
341
|
+
// Set Grid
|
|
342
|
+
const getGridConfig = () => {
|
|
343
|
+
if (this.options.isMultiSelect) {
|
|
344
|
+
if (entry.image) return '40px min-content auto'; // cb-img-txt
|
|
345
|
+
return '40px auto'; // cb-txt
|
|
346
|
+
}
|
|
347
|
+
if (entry.image) return 'min-content auto'; // img-txt
|
|
348
|
+
return 'auto'; // txt
|
|
349
|
+
};
|
|
350
|
+
item.style.gridTemplateColumns = getGridConfig();
|
|
351
|
+
return item;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
_renderDropdown() {
|
|
355
|
+
this._resetAutocomplete();
|
|
356
|
+
// Check if Data is empty
|
|
357
|
+
if (this.menuItems.length === 0) {
|
|
358
|
+
this.menuItems = this.selectedValues; // Show selected Items
|
|
359
|
+
}
|
|
360
|
+
for (let i = 0; i < this.menuItems.length; i++) {
|
|
361
|
+
const item = this._createDropdownItem(this.menuItems[i]);
|
|
362
|
+
this.container.append(item);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
_setStatusLoading() {
|
|
367
|
+
this.el.parentElement.querySelector(
|
|
368
|
+
'.status-info'
|
|
369
|
+
).innerHTML = `<div style="height:100%;width:50px;"><svg version="1.1" id="L4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
|
|
370
|
+
<circle fill="#888c" stroke="none" cx="6" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.1"/></circle>
|
|
371
|
+
<circle fill="#888c" stroke="none" cx="26" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.2"/></circle>
|
|
372
|
+
<circle fill="#888c" stroke="none" cx="46" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.3"/></circle>
|
|
373
|
+
</svg></div>`;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
_updateSelectedInfo() {
|
|
377
|
+
const statusElement = this.el.parentElement.querySelector('.status-info');
|
|
378
|
+
if (statusElement) {
|
|
379
|
+
if (this.options.isMultiSelect) statusElement.innerHTML = this.selectedValues.length.toString();
|
|
380
|
+
else statusElement.innerHTML = '';
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
_refreshInputText() {
|
|
385
|
+
if (this.selectedValues.length === 1) {
|
|
386
|
+
const entry = this.selectedValues[0];
|
|
387
|
+
this.el.value = entry.text || entry.id; // Write Text to Input
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
_triggerChanged() {
|
|
392
|
+
this.el.dispatchEvent(new Event('change'));
|
|
393
|
+
// Trigger Autocomplete Event
|
|
394
|
+
if (typeof this.options.onAutocomplete === 'function')
|
|
395
|
+
this.options.onAutocomplete.call(this, this.selectedValues);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
open() {
|
|
399
|
+
const inputText = this.el.value.toLowerCase();
|
|
400
|
+
this._resetAutocomplete();
|
|
401
|
+
if (inputText.length >= this.options.minLength) {
|
|
402
|
+
this.isOpen = true;
|
|
403
|
+
this._renderDropdown();
|
|
404
|
+
}
|
|
405
|
+
// Open dropdown
|
|
406
|
+
if (!this.dropdown.isOpen) {
|
|
407
|
+
setTimeout(() => {
|
|
408
|
+
this.dropdown.open();
|
|
409
|
+
}, 100);
|
|
410
|
+
}
|
|
411
|
+
else this.dropdown.recalculateDimensions(); // Recalculate dropdown when its already open
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
close() {
|
|
415
|
+
this.dropdown.close();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
setMenuItems(menuItems) {
|
|
419
|
+
this.menuItems = menuItems;
|
|
420
|
+
this.open();
|
|
421
|
+
this._updateSelectedInfo();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
setValues(entries) {
|
|
425
|
+
this.selectedValues = entries;
|
|
426
|
+
this._updateSelectedInfo();
|
|
427
|
+
if (!this.options.isMultiSelect) {
|
|
428
|
+
this._refreshInputText();
|
|
429
|
+
}
|
|
430
|
+
this._triggerChanged();
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
selectOption(id) {
|
|
434
|
+
const entry = this.menuItems.find((item) => item.id == id);
|
|
435
|
+
if (!entry) return;
|
|
436
|
+
// Toggle Checkbox
|
|
437
|
+
const li = this.container.querySelector('li[data-id="'+id+'"]');
|
|
438
|
+
if (!li) return;
|
|
439
|
+
if (this.options.isMultiSelect) {
|
|
440
|
+
const checkbox = <HTMLInputElement|null>li.querySelector('input[type="checkbox"]');
|
|
441
|
+
checkbox.checked = !checkbox.checked;
|
|
442
|
+
if (checkbox.checked) this.selectedValues.push(entry);
|
|
443
|
+
else
|
|
444
|
+
this.selectedValues = this.selectedValues.filter(
|
|
445
|
+
(selectedEntry) => selectedEntry.id !== entry.id
|
|
446
|
+
);
|
|
447
|
+
this.el.focus();
|
|
448
|
+
} else {
|
|
449
|
+
// Single-Select
|
|
450
|
+
this.selectedValues = [entry];
|
|
451
|
+
this._refreshInputText();
|
|
452
|
+
this._resetAutocomplete();
|
|
453
|
+
this.close();
|
|
454
|
+
}
|
|
455
|
+
this._updateSelectedInfo();
|
|
456
|
+
this._triggerChanged();
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|