mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-21 15:06:45 +02:00
15d54c7d34
* enable restricted syntax in tests * add Options to global * crearte native elements * remove unused helper * fix/improve typings * add JSDoc typings * remove if/else
195 lines
5.6 KiB
JavaScript
195 lines
5.6 KiB
JavaScript
/**
|
|
* Helpers to create HTML elements used by Choices
|
|
* Can be overridden by providing `callbackOnCreateTemplates` option
|
|
* @typedef {import('../../types/index').Choices.Templates} Templates
|
|
*/
|
|
|
|
export const TEMPLATES = /** @type {Templates} */ ({
|
|
containerOuter(
|
|
{ containerOuter },
|
|
dir,
|
|
isSelectElement,
|
|
isSelectOneElement,
|
|
searchEnabled,
|
|
passedElementType,
|
|
) {
|
|
const div = Object.assign(document.createElement('div'), {
|
|
className: containerOuter,
|
|
dir,
|
|
});
|
|
div.dataset.type = passedElementType;
|
|
if (isSelectOneElement) div.tabIndex = 0;
|
|
if (isSelectElement) {
|
|
div.setAttribute('role', searchEnabled ? 'combobox' : 'listbox');
|
|
if (searchEnabled) div.setAttribute('aria-autocomplete', 'list');
|
|
}
|
|
div.setAttribute('aria-haspopup', 'true');
|
|
div.setAttribute('aria-expanded', 'false');
|
|
|
|
return div;
|
|
},
|
|
containerInner({ containerInner }) {
|
|
return Object.assign(document.createElement('div'), {
|
|
className: containerInner,
|
|
});
|
|
},
|
|
itemList({ list, listSingle, listItems }, isSelectOneElement) {
|
|
return Object.assign(document.createElement('div'), {
|
|
className: `${list} ${isSelectOneElement ? listSingle : listItems}`,
|
|
});
|
|
},
|
|
placeholder({ placeholder }, value) {
|
|
return Object.assign(document.createElement('div'), {
|
|
className: placeholder,
|
|
innerHTML: value,
|
|
});
|
|
},
|
|
|
|
item(
|
|
{ item, button, highlightedState, itemSelectable, placeholder },
|
|
{
|
|
id,
|
|
value,
|
|
label,
|
|
customProperties,
|
|
active,
|
|
disabled,
|
|
highlighted,
|
|
placeholder: isPlaceholder,
|
|
},
|
|
removeItemButton,
|
|
) {
|
|
const div = Object.assign(document.createElement('div'), {
|
|
className: item,
|
|
innerHTML: label,
|
|
});
|
|
Object.assign(div.dataset, {
|
|
item: '',
|
|
id,
|
|
value,
|
|
customProperties,
|
|
});
|
|
if (active) div.setAttribute('aria-selected', 'true');
|
|
if (disabled) div.setAttribute('aria-disabled', 'true');
|
|
|
|
if (isPlaceholder) div.classList.add(placeholder);
|
|
div.classList.add(highlighted ? highlightedState : itemSelectable);
|
|
|
|
if (removeItemButton) {
|
|
if (disabled) div.classList.remove(itemSelectable);
|
|
div.dataset.deletable = '';
|
|
/** @todo This MUST be localizable, not hardcoded! */
|
|
const REMOVE_ITEM_TEXT = 'Remove item';
|
|
const removeButton = Object.assign(document.createElement('button'), {
|
|
type: 'button',
|
|
className: button,
|
|
innerHTML: REMOVE_ITEM_TEXT,
|
|
});
|
|
removeButton.setAttribute(
|
|
'aria-label',
|
|
`${REMOVE_ITEM_TEXT}: '${value}'`,
|
|
);
|
|
removeButton.dataset.button = '';
|
|
div.appendChild(removeButton);
|
|
}
|
|
|
|
return div;
|
|
},
|
|
choiceList({ list }, isSelectOneElement) {
|
|
const div = Object.assign(document.createElement('div'), {
|
|
className: list,
|
|
dir: 'ltr',
|
|
});
|
|
if (!isSelectOneElement) div.setAttribute('aria-multiselectable', 'true');
|
|
div.setAttribute('role', 'listbox');
|
|
return div;
|
|
},
|
|
|
|
choiceGroup({ group, groupHeading, itemDisabled }, { id, value, disabled }) {
|
|
const div = Object.assign(document.createElement('div'), {
|
|
className: `${group} ${disabled ? itemDisabled : ''}`,
|
|
});
|
|
div.setAttribute('role', 'group');
|
|
Object.assign(div.dataset, { group: '', id, value });
|
|
if (disabled) div.setAttribute('aria-disabled', 'true');
|
|
div.appendChild(
|
|
Object.assign(document.createElement('div'), {
|
|
className: groupHeading,
|
|
innerHTML: value,
|
|
}),
|
|
);
|
|
return div;
|
|
},
|
|
|
|
choice(
|
|
{ item, itemChoice, itemSelectable, itemDisabled, placeholder },
|
|
{
|
|
id,
|
|
value,
|
|
label,
|
|
groupId,
|
|
elementId,
|
|
disabled,
|
|
placeholder: isPlaceholder,
|
|
},
|
|
selectText,
|
|
) {
|
|
const div = Object.assign(document.createElement('div'), {
|
|
id: elementId,
|
|
innerHTML: label,
|
|
className: `${item} ${itemChoice} ${
|
|
disabled ? itemDisabled : itemSelectable
|
|
} ${isPlaceholder ? placeholder : ''}`,
|
|
});
|
|
div.setAttribute('role', groupId > 0 ? 'treeitem' : 'option');
|
|
Object.assign(div.dataset, {
|
|
choice: '',
|
|
id,
|
|
value,
|
|
selectText,
|
|
});
|
|
if (disabled) {
|
|
div.dataset.choiceDisabled = '';
|
|
div.setAttribute('aria-disabled', 'true');
|
|
} else div.dataset.choiceSelectable = '';
|
|
|
|
return div;
|
|
},
|
|
input({ input, inputCloned }, placeholderValue) {
|
|
const inp = Object.assign(document.createElement('input'), {
|
|
type: 'text',
|
|
className: `${input} ${inputCloned}`,
|
|
autocomplete: 'off',
|
|
autocapitalize: 'off',
|
|
spellcheck: false,
|
|
});
|
|
inp.setAttribute('role', 'textbox');
|
|
inp.setAttribute('aria-autocomplete', 'list');
|
|
inp.setAttribute('aria-label', placeholderValue);
|
|
return inp;
|
|
},
|
|
dropdown({ list, listDropdown }) {
|
|
const div = document.createElement('div');
|
|
div.classList.add(list, listDropdown);
|
|
div.setAttribute('aria-expanded', 'false');
|
|
return div;
|
|
},
|
|
notice({ item, itemChoice, noResults, noChoices }, innerHTML, type = '') {
|
|
const classes = [item, itemChoice];
|
|
if (type === 'no-choices') classes.push(noChoices);
|
|
else if (type === 'no-results') classes.push(noResults);
|
|
return Object.assign(document.createElement('div'), {
|
|
innerHTML,
|
|
className: classes.join(' '),
|
|
});
|
|
},
|
|
option({ label, value, customProperties, active, disabled }) {
|
|
const opt = new Option(label, value, false, active);
|
|
if (customProperties) opt.dataset.customProperties = customProperties;
|
|
opt.disabled = disabled;
|
|
return opt;
|
|
},
|
|
});
|
|
|
|
export default TEMPLATES;
|