1
- import { Component } from "./component" ;
2
1
import { M } from "./global" ;
3
- import { Dropdown } from "./dropdown" ;
2
+ import { Dropdown , DropdownOptions } from "./dropdown" ;
3
+ import { Component , BaseOptions , InitElements } from "./component" ;
4
+
5
+ export interface AutocompleteData {
6
+ /**
7
+ * A primitive value that can be converted to string.
8
+ * If "text" is not provided, it will also be used as "option text" as well
9
+ */
10
+ id : string | number ;
11
+ /**
12
+ * This optional attribute is used as "display value" for the current entry.
13
+ * When provided, it will also be taken into consideration by the standard search function.
14
+ */
15
+ text ?: string ;
16
+ /**
17
+ * This optional attribute is used to provide a valid image URL to the current option.
18
+ */
19
+ image ?: string ;
20
+ /**
21
+ * Optional attributes which describes the option.
22
+ */
23
+ description ?: string ;
24
+ }
25
+
26
+ export interface AutocompleteOptions extends BaseOptions {
27
+ /**
28
+ * Data object defining autocomplete options with
29
+ * optional icon strings.
30
+ */
31
+ data : AutocompleteData [ ] ;
32
+ /**
33
+ * Flag which can be set if multiple values can be selected. The Result will be an Array.
34
+ * @default false
35
+ */
36
+ isMultiSelect : boolean ;
37
+ /**
38
+ * Callback for when autocompleted.
39
+ */
40
+ onAutocomplete : ( entries : AutocompleteData [ ] ) => void ;
41
+ /**
42
+ * Minimum number of characters before autocomplete starts.
43
+ * @default 1
44
+ */
45
+ minLength : number ;
46
+ /**
47
+ * The height of the Menu which can be set via css-property.
48
+ * @default '300px'
49
+ */
50
+ maxDropDownHeight : string ;
51
+ /**
52
+ * Function is called when the input text is altered and data can also be loaded asynchronously.
53
+ * If the results are collected the items in the list can be updated via the function setMenuItems(collectedItems).
54
+ * @param text Searched text.
55
+ * @param autocomplete Current autocomplete instance.
56
+ */
57
+ onSearch : ( text : string , autocomplete : Autocomplete ) => void ;
58
+ /**
59
+ * If true will render the key from each item directly as HTML.
60
+ * User input MUST be properly sanitized first.
61
+ * @default false
62
+ */
63
+ allowUnsafeHTML : boolean ;
64
+ /**
65
+ * Pass options object to select dropdown initialization.
66
+ * @default {}
67
+ */
68
+ dropdownOptions : Partial < DropdownOptions > ;
69
+ } ;
4
70
5
- let _defaults = {
71
+ let _defaults : AutocompleteOptions = {
6
72
data : [ ] , // Autocomplete data set
7
73
onAutocomplete : null , // Callback for when autocompleted
8
74
dropdownOptions : {
@@ -26,45 +92,73 @@ let _defaults = {
26
92
} ;
27
93
28
94
29
- export class Autocomplete extends Component {
30
- el : HTMLInputElement ;
95
+ export class Autocomplete extends Component < AutocompleteOptions > {
96
+ declare el : HTMLInputElement ;
97
+ /** If the autocomplete is open. */
31
98
isOpen : boolean ;
99
+ /** Number of matching autocomplete options. */
32
100
count : number ;
101
+ /** Index of the current selected option. */
33
102
activeIndex : number ;
34
- private oldVal : any ;
103
+ private oldVal : string ;
35
104
private $active : HTMLElement | null ;
36
105
private _mousedown : boolean ;
37
106
container : HTMLElement ;
107
+ /** Instance of the dropdown plugin for this autocomplete. */
38
108
dropdown : Dropdown ;
39
109
static _keydown : boolean ;
40
- selectedValues : any [ ] ;
41
- menuItems : any [ ] ;
110
+ selectedValues : AutocompleteData [ ] ;
111
+ menuItems : AutocompleteData [ ] ;
42
112
43
113
44
- constructor ( el , options ) {
45
- super ( Autocomplete , el , options ) ;
114
+ constructor ( el : HTMLElement , options : Partial < AutocompleteOptions > ) {
115
+ super ( el , options , Autocomplete ) ;
46
116
( this . el as any ) . M_Autocomplete = this ;
47
- this . options = { ...Autocomplete . defaults , ...options } ;
117
+
118
+ this . options = {
119
+ ...Autocomplete . defaults ,
120
+ ...options
121
+ } ;
122
+
48
123
this . isOpen = false ;
49
124
this . count = 0 ;
50
125
this . activeIndex = - 1 ;
51
- this . oldVal ;
126
+ this . oldVal = "" ;
52
127
this . selectedValues = [ ] ;
53
128
this . menuItems = [ ] ;
54
129
this . $active = null ;
55
130
this . _mousedown = false ;
56
131
this . _setupDropdown ( ) ;
57
132
this . _setupEventHandlers ( ) ;
58
133
}
59
- static get defaults ( ) {
134
+
135
+ static get defaults ( ) : AutocompleteOptions {
60
136
return _defaults ;
61
137
}
62
- static init ( els , options ) {
63
- return super . init ( this , els , options ) ;
138
+
139
+ /**
140
+ * Initializes instance of Autocomplete.
141
+ * @param el HTML element.
142
+ * @param options Component options.
143
+ */
144
+ static init ( el : HTMLElement , options : Partial < AutocompleteOptions > ) : Autocomplete ;
145
+ /**
146
+ * Initializes instances of Autocomplete.
147
+ * @param els HTML elements.
148
+ * @param options Component options.
149
+ */
150
+ static init ( els : InitElements < HTMLElement > , options : Partial < AutocompleteOptions > ) : Autocomplete [ ] ;
151
+ /**
152
+ * Initializes instances of Autocomplete.
153
+ * @param els HTML elements.
154
+ * @param options Component options.
155
+ */
156
+ static init ( els : HTMLElement | InitElements < HTMLElement > , options : Partial < AutocompleteOptions > ) : Autocomplete | Autocomplete [ ] {
157
+ return super . init ( els , options , Autocomplete ) ;
64
158
}
65
- static getInstance ( el ) {
66
- let domElem = el . jquery ? el [ 0 ] : el ;
67
- return domElem . M_Autocomplete ;
159
+
160
+ static getInstance ( el : HTMLElement ) : Autocomplete {
161
+ return ( el as any ) . M_Autocomplete ;
68
162
}
69
163
70
164
destroy ( ) {
@@ -253,7 +347,7 @@ export class Autocomplete extends Component {
253
347
this . _mousedown = false ;
254
348
}
255
349
256
- _highlightPartialText ( input , label ) {
350
+ _highlightPartialText ( input : string , label : string ) {
257
351
const start = label . toLowerCase ( ) . indexOf ( '' + input . toLowerCase ( ) + '' ) ;
258
352
const end = start + input . length - 1 ;
259
353
//custom filters may return results where the string does not match any part
@@ -263,9 +357,9 @@ export class Autocomplete extends Component {
263
357
return [ label . slice ( 0 , start ) , label . slice ( start , end + 1 ) , label . slice ( end + 1 ) ] ;
264
358
}
265
359
266
- _createDropdownItem ( entry ) {
360
+ _createDropdownItem ( entry : AutocompleteData ) {
267
361
const item = document . createElement ( 'li' ) ;
268
- item . setAttribute ( 'data-id' , entry . id ) ;
362
+ item . setAttribute ( 'data-id' , < string > entry . id ) ;
269
363
item . setAttribute (
270
364
'style' ,
271
365
'display:grid; grid-auto-flow: column; user-select: none; align-items: center;'
@@ -366,7 +460,7 @@ export class Autocomplete extends Component {
366
460
_refreshInputText ( ) {
367
461
if ( this . selectedValues . length === 1 ) {
368
462
const entry = this . selectedValues [ 0 ] ;
369
- this . el . value = entry . text || entry . id ; // Write Text to Input
463
+ this . el . value = entry . text || < string > entry . id ; // Write Text to Input
370
464
}
371
465
}
372
466
@@ -377,7 +471,10 @@ export class Autocomplete extends Component {
377
471
this . options . onAutocomplete . call ( this , this . selectedValues ) ;
378
472
}
379
473
380
- open ( ) {
474
+ /**
475
+ * Show autocomplete.
476
+ */
477
+ open = ( ) => {
381
478
const inputText = this . el . value . toLowerCase ( ) ;
382
479
this . _resetAutocomplete ( ) ;
383
480
if ( inputText . length >= this . options . minLength ) {
@@ -393,17 +490,28 @@ export class Autocomplete extends Component {
393
490
else this . dropdown . recalculateDimensions ( ) ; // Recalculate dropdown when its already open
394
491
}
395
492
396
- close ( ) {
493
+ /**
494
+ * Hide autocomplete.
495
+ */
496
+ close = ( ) => {
397
497
this . dropdown . close ( ) ;
398
498
}
399
499
400
- setMenuItems ( menuItems ) {
500
+ /**
501
+ * Updates the visible or selectable items shown in the menu.
502
+ * @param menuItems Items to be available.
503
+ */
504
+ setMenuItems ( menuItems : AutocompleteData [ ] ) {
401
505
this . menuItems = menuItems ;
402
506
this . open ( ) ;
403
507
this . _updateSelectedInfo ( ) ;
404
508
}
405
509
406
- setValues ( entries ) {
510
+ /**
511
+ * Sets selected values.
512
+ * @param entries
513
+ */
514
+ setValues ( entries : AutocompleteData [ ] ) {
407
515
this . selectedValues = entries ;
408
516
this . _updateSelectedInfo ( ) ;
409
517
if ( ! this . options . isMultiSelect ) {
@@ -412,7 +520,11 @@ export class Autocomplete extends Component {
412
520
this . _triggerChanged ( ) ;
413
521
}
414
522
415
- selectOption ( id ) {
523
+ /**
524
+ * Select a specific autocomplete option via id-property.
525
+ * @param id The id of a data-entry.
526
+ */
527
+ selectOption ( id : number | string ) {
416
528
const entry = this . menuItems . find ( ( item ) => item . id == id ) ;
417
529
if ( ! entry ) return ;
418
530
// Toggle Checkbox
0 commit comments