mirror of
https://github.com/Choices-js/Choices.git
synced 2024-06-15 20:25:18 +02:00
And more...
This commit is contained in:
parent
585ee6457f
commit
3f850f61d6
|
@ -1503,7 +1503,8 @@ class Choices {
|
||||||
}: Pick<KeyDownAction, 'event' | 'activeItems' | 'hasActiveDropdown'>): void {
|
}: Pick<KeyDownAction, 'event' | 'activeItems' | 'hasActiveDropdown'>): void {
|
||||||
const { target } = event;
|
const { target } = event;
|
||||||
const { ENTER_KEY: enterKey } = KEY_CODES;
|
const { ENTER_KEY: enterKey } = KEY_CODES;
|
||||||
const targetWasButton = target && target.hasAttribute('data-button');
|
const targetWasButton =
|
||||||
|
target && (target as HTMLElement).hasAttribute('data-button');
|
||||||
|
|
||||||
if (this._isTextElement && target && target.value) {
|
if (this._isTextElement && target && target.value) {
|
||||||
const { value } = this.input;
|
const { value } = this.input;
|
||||||
|
@ -1518,7 +1519,7 @@ class Choices {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetWasButton) {
|
if (targetWasButton) {
|
||||||
this._handleButtonAction(activeItems, target);
|
this._handleButtonAction(activeItems, target as HTMLElement);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1618,6 +1619,10 @@ class Choices {
|
||||||
hasFocusedInput,
|
hasFocusedInput,
|
||||||
activeItems,
|
activeItems,
|
||||||
}: Partial<KeyDownAction>): void {
|
}: Partial<KeyDownAction>): void {
|
||||||
|
if (!event || event.type !== 'KeyboardEvent' || !event.target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { target } = event;
|
const { target } = event;
|
||||||
// If backspace or delete key is pressed and the input has no value
|
// If backspace or delete key is pressed and the input has no value
|
||||||
if (hasFocusedInput && !target.value && !this._isSelectOneElement) {
|
if (hasFocusedInput && !target.value && !this._isSelectOneElement) {
|
||||||
|
@ -1635,7 +1640,7 @@ class Choices {
|
||||||
_onTouchEnd(event: TouchEvent): void {
|
_onTouchEnd(event: TouchEvent): void {
|
||||||
const { target } = event || event.touches[0];
|
const { target } = event || event.touches[0];
|
||||||
const touchWasWithinContainer =
|
const touchWasWithinContainer =
|
||||||
this._wasTap && this.containerOuter.element.contains(target);
|
this._wasTap && this.containerOuter.element.contains(target as Node);
|
||||||
|
|
||||||
if (touchWasWithinContainer) {
|
if (touchWasWithinContainer) {
|
||||||
const containerWasExactTarget =
|
const containerWasExactTarget =
|
||||||
|
@ -1829,7 +1834,7 @@ class Choices {
|
||||||
}
|
}
|
||||||
|
|
||||||
_highlightChoice(el: HTMLElement | null = null): void {
|
_highlightChoice(el: HTMLElement | null = null): void {
|
||||||
const choices = Array.from(
|
const choices: HTMLElement[] = Array.from(
|
||||||
this.dropdown.element.querySelectorAll('[data-choice-selectable]'),
|
this.dropdown.element.querySelectorAll('[data-choice-selectable]'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2059,7 +2064,10 @@ class Choices {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getTemplate<K extends keyof Templates>(template: K, ...args): Templates[K] {
|
_getTemplate<K extends keyof Templates>(
|
||||||
|
template: K,
|
||||||
|
...args: any
|
||||||
|
): HTMLElement | HTMLOptionElement {
|
||||||
const { classNames } = this.config;
|
const { classNames } = this.config;
|
||||||
|
|
||||||
return this._templates[template].call(this, classNames, ...args);
|
return this._templates[template].call(this, classNames, ...args);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { ClassNames, Item, Choice } from '../interfaces';
|
||||||
export default class WrappedSelect extends WrappedElement {
|
export default class WrappedSelect extends WrappedElement {
|
||||||
element: HTMLSelectElement;
|
element: HTMLSelectElement;
|
||||||
classNames: ClassNames;
|
classNames: ClassNames;
|
||||||
template: () => HTMLElement;
|
template: (data: object) => HTMLOptionElement;
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
element,
|
element,
|
||||||
|
@ -13,7 +13,7 @@ export default class WrappedSelect extends WrappedElement {
|
||||||
}: {
|
}: {
|
||||||
element: HTMLSelectElement;
|
element: HTMLSelectElement;
|
||||||
classNames: ClassNames;
|
classNames: ClassNames;
|
||||||
template: () => HTMLElement;
|
template: (data: object) => HTMLOptionElement;
|
||||||
}) {
|
}) {
|
||||||
super({ element, classNames });
|
super({ element, classNames });
|
||||||
this.template = template;
|
this.template = template;
|
||||||
|
@ -37,7 +37,7 @@ export default class WrappedSelect extends WrappedElement {
|
||||||
|
|
||||||
set options(options: Item[] | Choice[]): void {
|
set options(options: Item[] | Choice[]): void {
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
const addOptionToFragment = data => {
|
const addOptionToFragment = (data): void => {
|
||||||
// Create a standard select option
|
// Create a standard select option
|
||||||
const option = this.template(data);
|
const option = this.template(data);
|
||||||
// Append it to fragment
|
// Append it to fragment
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import Choices from './choices';
|
import Choices from './choices';
|
||||||
|
|
||||||
export namespace Types {
|
export namespace Types {
|
||||||
|
|
|
@ -1,24 +1,17 @@
|
||||||
/**
|
import { EventMap } from '../interfaces';
|
||||||
* @param {number} min
|
|
||||||
* @param {number} max
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
* @returns {number}
|
|
||||||
*/
|
export const getRandomNumber = (min: number, max: number): number =>
|
||||||
export const getRandomNumber = (min, max) =>
|
|
||||||
Math.floor(Math.random() * (max - min) + min);
|
Math.floor(Math.random() * (max - min) + min);
|
||||||
|
|
||||||
/**
|
export const generateChars = (length: number): string =>
|
||||||
* @param {number} length
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export const generateChars = length =>
|
|
||||||
Array.from({ length }, () => getRandomNumber(0, 36).toString(36)).join('');
|
Array.from({ length }, () => getRandomNumber(0, 36).toString(36)).join('');
|
||||||
|
|
||||||
/**
|
export const generateId = (
|
||||||
* @param {HTMLInputElement | HTMLSelectElement} element
|
element: HTMLInputElement | HTMLSelectElement,
|
||||||
* @param {string} prefix
|
prefix: string,
|
||||||
* @returns {string}
|
): string => {
|
||||||
*/
|
|
||||||
export const generateId = (element, prefix) => {
|
|
||||||
let id =
|
let id =
|
||||||
element.id ||
|
element.id ||
|
||||||
(element.name && `${element.name}-${generateChars(2)}`) ||
|
(element.name && `${element.name}-${generateChars(2)}`) ||
|
||||||
|
@ -29,46 +22,31 @@ export const generateId = (element, prefix) => {
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const getType = (obj: any): string =>
|
||||||
* @param {any} obj
|
Object.prototype.toString.call(obj).slice(8, -1);
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export const getType = obj => Object.prototype.toString.call(obj).slice(8, -1);
|
|
||||||
|
|
||||||
/**
|
export const isType = (type: string, obj: any): boolean =>
|
||||||
* @param {string} type
|
|
||||||
* @param {any} obj
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export const isType = (type, obj) =>
|
|
||||||
obj !== undefined && obj !== null && getType(obj) === type;
|
obj !== undefined && obj !== null && getType(obj) === type;
|
||||||
|
|
||||||
/**
|
export const wrap = (
|
||||||
* @param {HTMLElement} element
|
element: HTMLElement,
|
||||||
* @param {HTMLElement} [wrapper={HTMLDivElement}]
|
wrapper: HTMLElement = document.createElement('div'),
|
||||||
* @returns {HTMLElement}
|
): HTMLElement => {
|
||||||
*/
|
|
||||||
export const wrap = (element, wrapper = document.createElement('div')) => {
|
|
||||||
if (element.nextSibling) {
|
if (element.nextSibling) {
|
||||||
element.parentNode.insertBefore(wrapper, element.nextSibling);
|
element.parentNode &&
|
||||||
|
element.parentNode.insertBefore(wrapper, element.nextSibling);
|
||||||
} else {
|
} else {
|
||||||
element.parentNode.appendChild(wrapper);
|
element.parentNode && element.parentNode.appendChild(wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper.appendChild(element);
|
return wrapper.appendChild(element);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const getAdjacentEl = (
|
||||||
* @param {Element} startEl
|
startEl: Element,
|
||||||
* @param {string} selector
|
selector: string,
|
||||||
* @param {1 | -1} direction
|
direction = 1,
|
||||||
* @returns {Element | undefined}
|
): Element => {
|
||||||
*/
|
|
||||||
export const getAdjacentEl = (startEl, selector, direction = 1) => {
|
|
||||||
if (!(startEl instanceof Element) || typeof selector !== 'string') {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const prop = `${direction > 0 ? 'next' : 'previous'}ElementSibling`;
|
const prop = `${direction > 0 ? 'next' : 'previous'}ElementSibling`;
|
||||||
|
|
||||||
let sibling = startEl[prop];
|
let sibling = startEl[prop];
|
||||||
|
@ -82,13 +60,11 @@ export const getAdjacentEl = (startEl, selector, direction = 1) => {
|
||||||
return sibling;
|
return sibling;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const isScrolledIntoView = (
|
||||||
* @param {Element} element
|
element: HTMLElement,
|
||||||
* @param {Element} parent
|
parent: HTMLElement,
|
||||||
* @param {-1 | 1} direction
|
direction = 1,
|
||||||
* @returns {boolean}
|
): boolean => {
|
||||||
*/
|
|
||||||
export const isScrolledIntoView = (element, parent, direction = 1) => {
|
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -108,11 +84,7 @@ export const isScrolledIntoView = (element, parent, direction = 1) => {
|
||||||
return isVisible;
|
return isVisible;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const sanitise = <T>(value: T | string): T | string => {
|
||||||
* @param {any} value
|
|
||||||
* @returns {any}
|
|
||||||
*/
|
|
||||||
export const sanitise = value => {
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -124,13 +96,10 @@ export const sanitise = value => {
|
||||||
.replace(/"/g, '"');
|
.replace(/"/g, '"');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const strToEl = ((): ((str: string) => Element) => {
|
||||||
* @returns {() => (str: string) => Element}
|
|
||||||
*/
|
|
||||||
export const strToEl = (() => {
|
|
||||||
const tmpEl = document.createElement('div');
|
const tmpEl = document.createElement('div');
|
||||||
|
|
||||||
return str => {
|
return (str): Element => {
|
||||||
const cleanedInput = str.trim();
|
const cleanedInput = str.trim();
|
||||||
tmpEl.innerHTML = cleanedInput;
|
tmpEl.innerHTML = cleanedInput;
|
||||||
const firldChild = tmpEl.children[0];
|
const firldChild = tmpEl.children[0];
|
||||||
|
@ -143,33 +112,31 @@ export const strToEl = (() => {
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/**
|
interface RecordToCompare {
|
||||||
* @param {{ label?: string, value: string }} a
|
value: string;
|
||||||
* @param {{ label?: string, value: string }} b
|
label?: string;
|
||||||
* @returns {number}
|
}
|
||||||
*/
|
|
||||||
export const sortByAlpha = (
|
export const sortByAlpha = (
|
||||||
{ value, label = value },
|
{ value, label = value }: RecordToCompare,
|
||||||
{ value: value2, label: label2 = value2 },
|
{ value: value2, label: label2 = value2 }: RecordToCompare,
|
||||||
) =>
|
): number =>
|
||||||
label.localeCompare(label2, [], {
|
label.localeCompare(label2, [], {
|
||||||
sensitivity: 'base',
|
sensitivity: 'base',
|
||||||
ignorePunctuation: true,
|
ignorePunctuation: true,
|
||||||
numeric: true,
|
numeric: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
interface RecordToSort {
|
||||||
* @param {{ score: number }} a
|
score: number;
|
||||||
* @param {{ score: number }} b
|
}
|
||||||
*/
|
export const sortByScore = (a: RecordToSort, b: RecordToSort): number =>
|
||||||
export const sortByScore = (a, b) => a.score - b.score;
|
a.score - b.score;
|
||||||
|
|
||||||
/**
|
export const dispatchEvent = (
|
||||||
* @param {HTMLElement} element
|
element: HTMLElement,
|
||||||
* @param {string} type
|
type: keyof EventMap,
|
||||||
* @param {object} customArgs
|
customArgs: object | null = null,
|
||||||
*/
|
): boolean => {
|
||||||
export const dispatchEvent = (element, type, customArgs = null) => {
|
|
||||||
const event = new CustomEvent(type, {
|
const event = new CustomEvent(type, {
|
||||||
detail: customArgs,
|
detail: customArgs,
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
@ -179,13 +146,11 @@ export const dispatchEvent = (element, type, customArgs = null) => {
|
||||||
return element.dispatchEvent(event);
|
return element.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const existsInArray = (
|
||||||
* @param {array} array
|
array: any[],
|
||||||
* @param {any} value
|
value: string,
|
||||||
* @param {string} [key="value"]
|
key = 'value',
|
||||||
* @returns {boolean}
|
): boolean =>
|
||||||
*/
|
|
||||||
export const existsInArray = (array, value, key = 'value') =>
|
|
||||||
array.some(item => {
|
array.some(item => {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
return item[key] === value.trim();
|
return item[key] === value.trim();
|
||||||
|
@ -194,19 +159,16 @@ export const existsInArray = (array, value, key = 'value') =>
|
||||||
return item[key] === value;
|
return item[key] === value;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
export const cloneObject = (obj: object): object =>
|
||||||
* @param {any} obj
|
JSON.parse(JSON.stringify(obj));
|
||||||
* @returns {any}
|
|
||||||
*/
|
|
||||||
export const cloneObject = obj => JSON.parse(JSON.stringify(obj));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of keys present on the first but missing on the second object
|
* Returns an array of keys present on the first but missing on the second object
|
||||||
* @param {object} a
|
|
||||||
* @param {object} b
|
|
||||||
* @returns {string[]}
|
|
||||||
*/
|
*/
|
||||||
export const diff = (a, b) => {
|
export const diff = (
|
||||||
|
a: Record<string, any>,
|
||||||
|
b: Record<string, any>,
|
||||||
|
): string[] => {
|
||||||
const aKeys = Object.keys(a).sort();
|
const aKeys = Object.keys(a).sort();
|
||||||
const bKeys = Object.keys(b).sort();
|
const bKeys = Object.keys(b).sort();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue