-
-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Release v2.2.1 #563
Release v2.2.1 #563
Changes from 1 commit
8a53446
f6375da
dcffec3
bf40157
29e92a7
add76d6
5f93e5d
4dd3913
838a9bd
56752e9
ea59cdc
7f72601
82a9d7c
759ea60
3a89be1
5f8a1ac
28123ec
5240b2f
6b782a8
ef35166
3472297
d0e84e0
eb347bb
e023654
0b7c8c5
c0522b7
d4d05f6
24daf93
4afb62e
34593d0
562a542
800255c
182a808
c887f6d
65ddf18
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import { Utils } from "./utils"; | ||
import { Dropdown, DropdownOptions } from "./dropdown"; | ||
import { Component, BaseOptions, InitElements, MElement } from "./component"; | ||
import { Utils } from './utils'; | ||
import { Dropdown, DropdownOptions } from './dropdown'; | ||
import { Component, BaseOptions, InitElements, MElement } from './component'; | ||
|
||
export interface AutocompleteData { | ||
/** | ||
|
@@ -82,9 +82,10 @@ const _defaults: AutocompleteOptions = { | |
onSearch: (text: string, autocomplete: Autocomplete) => { | ||
const normSearch = text.toLocaleLowerCase(); | ||
autocomplete.setMenuItems( | ||
autocomplete.options.data.filter((option) => | ||
option.id.toString().toLocaleLowerCase().includes(normSearch) | ||
|| option.text?.toLocaleLowerCase().includes(normSearch) | ||
autocomplete.options.data.filter( | ||
(option) => | ||
option.id.toString().toLocaleLowerCase().includes(normSearch) || | ||
option.text?.toLocaleLowerCase().includes(normSearch) | ||
) | ||
); | ||
}, | ||
|
@@ -101,7 +102,7 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
/** Index of the current selected option. */ | ||
activeIndex: number; | ||
private oldVal: string; | ||
private $active: HTMLElement|null; | ||
private $active: HTMLElement | null; | ||
private _mousedown: boolean; | ||
container: HTMLElement; | ||
/** Instance of the dropdown plugin for this autocomplete. */ | ||
|
@@ -112,7 +113,7 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
|
||
constructor(el: HTMLInputElement, options: Partial<AutocompleteOptions>) { | ||
super(el, options, Autocomplete); | ||
(this.el as any).M_Autocomplete = this; | ||
this.el['M_Autocomplete'] = this; | ||
|
||
this.options = { | ||
...Autocomplete.defaults, | ||
|
@@ -122,7 +123,7 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
this.isOpen = false; | ||
this.count = 0; | ||
this.activeIndex = -1; | ||
this.oldVal = ""; | ||
this.oldVal = ''; | ||
this.selectedValues = []; | ||
this.menuItems = this.options.data || []; | ||
this.$active = null; | ||
|
@@ -146,24 +147,30 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
* @param els HTML elements. | ||
* @param options Component options. | ||
*/ | ||
static init(els: InitElements<HTMLInputElement | MElement>, options?: Partial<AutocompleteOptions>): Autocomplete[]; | ||
static init( | ||
els: InitElements<HTMLInputElement | MElement>, | ||
options?: Partial<AutocompleteOptions> | ||
): Autocomplete[]; | ||
/** | ||
* Initializes instances of Autocomplete. | ||
* @param els HTML elements. | ||
* @param options Component options. | ||
*/ | ||
static init(els: HTMLInputElement | InitElements<HTMLInputElement | MElement>, options: Partial<AutocompleteOptions> = {}): Autocomplete | Autocomplete[] { | ||
static init( | ||
els: HTMLInputElement | InitElements<HTMLInputElement | MElement>, | ||
options: Partial<AutocompleteOptions> = {} | ||
): Autocomplete | Autocomplete[] { | ||
return super.init(els, options, Autocomplete); | ||
} | ||
|
||
static getInstance(el: HTMLElement): Autocomplete { | ||
return (el as any).M_Autocomplete; | ||
return el['M_Autocomplete']; | ||
Comment on lines
-160
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we might need to revert this, since it introduces backwards compatibility issues with applications using the previous object orientated approach, propose to just set it to warnings until we can declare the correct type definition |
||
} | ||
|
||
destroy() { | ||
this._removeEventHandlers(); | ||
this._removeDropdown(); | ||
(this.el as any).M_Autocomplete = undefined; | ||
this.el['M_Autocomplete'] = undefined; | ||
Comment on lines
-166
to
+173
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we might need to revert this, since it introduces backwards compatibility issues with applications using the previous object orientated approach, propose to just set it to warnings until we can declare the correct type definition |
||
} | ||
|
||
_setupEventHandlers() { | ||
|
@@ -172,16 +179,10 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
this.el.addEventListener('focus', this._handleInputFocus); | ||
this.el.addEventListener('keydown', this._handleInputKeydown); | ||
this.el.addEventListener('click', this._handleInputClick); | ||
this.container.addEventListener( | ||
'mousedown', | ||
this._handleContainerMousedownAndTouchstart | ||
); | ||
this.container.addEventListener('mousedown', this._handleContainerMousedownAndTouchstart); | ||
this.container.addEventListener('mouseup', this._handleContainerMouseupAndTouchend); | ||
if (typeof window.ontouchstart !== 'undefined') { | ||
this.container.addEventListener( | ||
'touchstart', | ||
this._handleContainerMousedownAndTouchstart | ||
); | ||
this.container.addEventListener('touchstart', this._handleContainerMousedownAndTouchstart); | ||
this.container.addEventListener('touchend', this._handleContainerMouseupAndTouchend); | ||
} | ||
} | ||
|
@@ -192,21 +193,12 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
this.el.removeEventListener('focus', this._handleInputFocus); | ||
this.el.removeEventListener('keydown', this._handleInputKeydown); | ||
this.el.removeEventListener('click', this._handleInputClick); | ||
this.container.removeEventListener( | ||
'mousedown', | ||
this._handleContainerMousedownAndTouchstart | ||
); | ||
this.container.removeEventListener('mousedown', this._handleContainerMousedownAndTouchstart); | ||
this.container.removeEventListener('mouseup', this._handleContainerMouseupAndTouchend); | ||
|
||
if (typeof window.ontouchstart !== 'undefined') { | ||
this.container.removeEventListener( | ||
'touchstart', | ||
this._handleContainerMousedownAndTouchstart | ||
); | ||
this.container.removeEventListener( | ||
'touchend', | ||
this._handleContainerMouseupAndTouchend | ||
); | ||
this.container.removeEventListener('touchstart', this._handleContainerMousedownAndTouchstart); | ||
this.container.removeEventListener('touchend', this._handleContainerMouseupAndTouchend); | ||
} | ||
} | ||
|
||
|
@@ -217,7 +209,7 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
this.container.classList.add('autocomplete-content', 'dropdown-content'); | ||
this.el.setAttribute('data-target', this.container.id); | ||
|
||
this.menuItems.forEach(menuItem => { | ||
this.menuItems.forEach((menuItem) => { | ||
const itemElement = this._createDropdownItem(menuItem); | ||
this.container.append(itemElement); | ||
}); | ||
|
@@ -269,17 +261,22 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
this.close(); | ||
this._resetAutocomplete(); | ||
} | ||
} | ||
}; | ||
|
||
_handleInputKeyup = (e: KeyboardEvent) => { | ||
if (e.type === 'keyup') Autocomplete._keydown = false; | ||
this.count = 0; | ||
const actualValue = this.el.value.toLocaleLowerCase(); | ||
// Don't capture enter or arrow key usage. | ||
if (Utils.keys.ENTER.includes(e.key) || Utils.keys.ARROW_UP.includes(e.key) || Utils.keys.ARROW_DOWN.includes(e.key)) return; | ||
if ( | ||
Utils.keys.ENTER.includes(e.key) || | ||
Utils.keys.ARROW_UP.includes(e.key) || | ||
Utils.keys.ARROW_DOWN.includes(e.key) | ||
) | ||
return; | ||
// Check if the input isn't empty | ||
// Check if focus triggered by tab | ||
if (this.oldVal !== actualValue && (Utils.tabPressed)) { | ||
if (this.oldVal !== actualValue && Utils.tabPressed) { | ||
this.open(); | ||
} | ||
this._inputChangeDetection(actualValue); | ||
|
@@ -289,7 +286,7 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
this.count = 0; | ||
const actualValue = this.el.value.toLocaleLowerCase(); | ||
this._inputChangeDetection(actualValue); | ||
} | ||
}; | ||
|
||
_inputChangeDetection = (value: string) => { | ||
// Value has changed! | ||
|
@@ -322,7 +319,8 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
if (Utils.keys.ARROW_UP.includes(e.key) || Utils.keys.ARROW_DOWN.includes(e.key)) { | ||
e.preventDefault(); | ||
if (Utils.keys.ARROW_UP.includes(e.key) && this.activeIndex > 0) this.activeIndex--; | ||
if (Utils.keys.ARROW_DOWN.includes(e.key) && this.activeIndex < numItems - 1) this.activeIndex++; | ||
if (Utils.keys.ARROW_DOWN.includes(e.key) && this.activeIndex < numItems - 1) | ||
this.activeIndex++; | ||
this.$active?.classList.remove('active'); | ||
if (this.activeIndex >= 0) { | ||
this.$active = this.container.querySelectorAll('li')[this.activeIndex]; | ||
|
@@ -335,19 +333,19 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
}); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
_handleInputClick = () => { | ||
this.open(); | ||
} | ||
}; | ||
|
||
_handleContainerMousedownAndTouchstart = () => { | ||
this._mousedown = true; | ||
} | ||
}; | ||
|
||
_handleContainerMouseupAndTouchend = () => { | ||
this._mousedown = false; | ||
} | ||
}; | ||
|
||
_resetCurrentElementPosition() { | ||
this.activeIndex = -1; | ||
|
@@ -420,7 +418,10 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
item.appendChild(itemText); | ||
item.querySelector('.item-text').appendChild(div); | ||
// Description | ||
if (typeof entry.description === 'string' || (typeof entry.description === 'number' && !isNaN(entry.description))) { | ||
if ( | ||
typeof entry.description === 'string' || | ||
(typeof entry.description === 'number' && !isNaN(entry.description)) | ||
) { | ||
const description = document.createElement('small'); | ||
description.setAttribute( | ||
'style', | ||
|
@@ -455,9 +456,8 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
} | ||
|
||
_setStatusLoading() { | ||
this.el.parentElement.querySelector( | ||
'.status-info' | ||
).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"> | ||
this.el.parentElement.querySelector('.status-info').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"> | ||
<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> | ||
<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> | ||
<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> | ||
|
@@ -467,7 +467,8 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
_updateSelectedInfo() { | ||
const statusElement = this.el.parentElement.querySelector('.status-info'); | ||
if (statusElement) { | ||
if (this.options.isMultiSelect) statusElement.innerHTML = this.selectedValues.length.toString(); | ||
if (this.options.isMultiSelect) | ||
statusElement.innerHTML = this.selectedValues.length.toString(); | ||
else statusElement.innerHTML = ''; | ||
} | ||
} | ||
|
@@ -501,16 +502,15 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
setTimeout(() => { | ||
this.dropdown.open(); | ||
}, 0); // TODO: why? | ||
} | ||
else this.dropdown.recalculateDimensions(); // Recalculate dropdown when its already open | ||
} | ||
} else this.dropdown.recalculateDimensions(); // Recalculate dropdown when its already open | ||
}; | ||
|
||
/** | ||
* Hide autocomplete. | ||
*/ | ||
close = () => { | ||
this.dropdown.close(); | ||
} | ||
}; | ||
|
||
/** | ||
* Updates the visible or selectable items shown in the menu. | ||
|
@@ -543,10 +543,10 @@ export class Autocomplete extends Component<AutocompleteOptions> { | |
const entry = this.menuItems.find((item) => item.id == id); | ||
if (!entry) return; | ||
// Toggle Checkbox | ||
const li = this.container.querySelector('li[data-id="'+id+'"]'); | ||
const li = this.container.querySelector('li[data-id="' + id + '"]'); | ||
if (!li) return; | ||
if (this.options.isMultiSelect) { | ||
const checkbox = <HTMLInputElement|null>li.querySelector('input[type="checkbox"]'); | ||
const checkbox = <HTMLInputElement | null>li.querySelector('input[type="checkbox"]'); | ||
checkbox.checked = !checkbox.checked; | ||
if (checkbox.checked) this.selectedValues.push(entry); | ||
else | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we might need to revert this, since it introduces backwards compatibility issues with applications using the previous object orientated approach, propose to just set it to warnings until we can declare the correct type definition