mirror of
https://github.com/Choices-js/Choices.git
synced 2024-06-18 05:35:57 +02:00
Minor refactoring
This commit is contained in:
parent
9e3d1cd519
commit
f6f63bc994
|
@ -228,6 +228,7 @@ exports.TEXT_TYPE = 'text';
|
|||
exports.SELECT_ONE_TYPE = 'select-one';
|
||||
exports.SELECT_MULTIPLE_TYPE = 'select-multiple';
|
||||
exports.SCROLLING_SPEED = 4;
|
||||
exports.DEFAULT_ID = -1;
|
||||
|
||||
/***/ }),
|
||||
/* 1 */
|
||||
|
@ -1412,8 +1413,8 @@ function () {
|
|||
}
|
||||
|
||||
if (userConfig.addItemFilter && typeof userConfig.addItemFilter !== 'function') {
|
||||
var re = userConfig.addItemFilter instanceof RegExp ? userConfig.addItemFilter : new RegExp(userConfig.addItemFilter);
|
||||
this.config.addItemFilter = re.test.bind(re);
|
||||
var exp = userConfig.addItemFilter instanceof RegExp ? userConfig.addItemFilter : new RegExp(userConfig.addItemFilter);
|
||||
this.config.addItemFilter = exp.test.bind(exp);
|
||||
}
|
||||
|
||||
if (this._isTextElement) {
|
||||
|
@ -1434,9 +1435,11 @@ function () {
|
|||
|
||||
this.initialised = false;
|
||||
this._store = new store_1.default();
|
||||
this._initialState = reducers_1.defaultState;
|
||||
this._currentState = reducers_1.defaultState;
|
||||
this._prevState = reducers_1.defaultState;
|
||||
this._state = {
|
||||
initial: reducers_1.defaultState,
|
||||
current: reducers_1.defaultState,
|
||||
previous: reducers_1.defaultState
|
||||
};
|
||||
this._currentValue = '';
|
||||
this._canSearch = !!this.config.searchEnabled;
|
||||
this._isScrollingOnIe = false;
|
||||
|
@ -1444,6 +1447,9 @@ function () {
|
|||
this._wasTap = true;
|
||||
this._placeholderValue = this._generatePlaceholderValue();
|
||||
this._baseId = utils_1.generateId(this.passedElement.element, 'choices-');
|
||||
this._idNames = {
|
||||
itemChoice: 'item-choice'
|
||||
};
|
||||
/**
|
||||
* setting direction in cases where it's explicitly set on passedElement
|
||||
* or when calculated direction is different from the document
|
||||
|
@ -1460,31 +1466,23 @@ function () {
|
|||
}
|
||||
}
|
||||
|
||||
this._idNames = {
|
||||
itemChoice: 'item-choice'
|
||||
};
|
||||
|
||||
if (this._isSelectElement) {
|
||||
// Assign preset groups from passed element
|
||||
this._presetGroups = this.passedElement.optionGroups; // Assign preset options from passed element
|
||||
|
||||
this._presetOptions = this.passedElement.options;
|
||||
} // Assign preset choices from passed object
|
||||
|
||||
|
||||
this._presetChoices = this.config.choices; // Assign preset items from passed object first
|
||||
|
||||
this._presetItems = this.config.items; // Add any values passed from attribute
|
||||
this._presetData = {
|
||||
choices: this.config.choices,
|
||||
items: this.config.items,
|
||||
// Assign preset option groups/options from passed element
|
||||
groups: this._isSelectElement ? this.passedElement.optionGroups : [],
|
||||
options: this._isSelectElement ? this.passedElement.options : []
|
||||
}; // Add any values passed from attribute
|
||||
|
||||
if (this.passedElement.value && this._isTextElement) {
|
||||
var splitValues = this.passedElement.value.split(this.config.delimiter);
|
||||
this._presetItems = this._presetItems.concat(splitValues);
|
||||
this._presetData.items = this._presetData.items.concat(splitValues);
|
||||
} // Create array of choices from option elements
|
||||
|
||||
|
||||
if (this.passedElement.options) {
|
||||
this.passedElement.options.forEach(function (option) {
|
||||
_this._presetChoices.push({
|
||||
_this._presetData.choices.push({
|
||||
value: option.value,
|
||||
label: option.innerHTML,
|
||||
selected: !!option.selected,
|
||||
|
@ -1543,6 +1541,7 @@ function () {
|
|||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
;
|
||||
|
||||
Choices.prototype.init = function () {
|
||||
if (this.initialised) {
|
||||
|
@ -1587,7 +1586,7 @@ function () {
|
|||
this.clearStore();
|
||||
|
||||
if (this._isSelectElement) {
|
||||
this.passedElement.options = this._presetOptions;
|
||||
this.passedElement.options = this._presetData.options;
|
||||
}
|
||||
|
||||
this._templates = templates_1.default;
|
||||
|
@ -1635,7 +1634,7 @@ function () {
|
|||
|
||||
var id = item.id,
|
||||
_a = item.groupId,
|
||||
groupId = _a === void 0 ? -1 : _a,
|
||||
groupId = _a === void 0 ? constants_1.DEFAULT_ID : _a,
|
||||
_b = item.value,
|
||||
value = _b === void 0 ? '' : _b,
|
||||
_c = item.label,
|
||||
|
@ -1663,7 +1662,7 @@ function () {
|
|||
|
||||
var id = item.id,
|
||||
_a = item.groupId,
|
||||
groupId = _a === void 0 ? -1 : _a,
|
||||
groupId = _a === void 0 ? constants_1.DEFAULT_ID : _a,
|
||||
_b = item.value,
|
||||
value = _b === void 0 ? '' : _b,
|
||||
_c = item.label,
|
||||
|
@ -2034,10 +2033,10 @@ function () {
|
|||
return;
|
||||
}
|
||||
|
||||
this._currentState = this._store.state;
|
||||
var stateChanged = this._currentState.choices !== this._prevState.choices || this._currentState.groups !== this._prevState.groups || this._currentState.items !== this._prevState.items;
|
||||
this._state.current = this._store.state;
|
||||
var stateChanged = this._state.current.choices !== this._state.previous.choices || this._state.current.groups !== this._state.previous.groups || this._state.current.items !== this._state.previous.items;
|
||||
var shouldRenderChoices = this._isSelectElement;
|
||||
var shouldRenderItems = this._currentState.items !== this._prevState.items;
|
||||
var shouldRenderItems = this._state.current.items !== this._state.previous.items;
|
||||
|
||||
if (!stateChanged) {
|
||||
return;
|
||||
|
@ -2051,7 +2050,7 @@ function () {
|
|||
this._renderItems();
|
||||
}
|
||||
|
||||
this._prevState = this._currentState;
|
||||
this._state.previous = this._state.current;
|
||||
};
|
||||
|
||||
Choices.prototype._renderChoices = function () {
|
||||
|
@ -2073,7 +2072,7 @@ function () {
|
|||
if (activeGroups.length >= 1 && !this._isSearching) {
|
||||
// If we have a placeholder choice along with groups
|
||||
var activePlaceholders = activeChoices.filter(function (activeChoice) {
|
||||
return activeChoice.placeholder === true && activeChoice.groupId === -1;
|
||||
return activeChoice.placeholder === true && activeChoice.groupId === constants_1.DEFAULT_ID;
|
||||
});
|
||||
|
||||
if (activePlaceholders.length >= 1) {
|
||||
|
@ -2784,7 +2783,6 @@ function () {
|
|||
var highlightedChoice = this.dropdown.getChild("." + this.config.classNames.highlightedState);
|
||||
|
||||
if (highlightedChoice) {
|
||||
// add enter keyCode value
|
||||
if (activeItems[0]) {
|
||||
activeItems[0].keyCode = enterKey; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
@ -3060,7 +3058,7 @@ function () {
|
|||
};
|
||||
|
||||
Choices.prototype._onFormReset = function () {
|
||||
this._store.dispatch(misc_1.resetTo(this._initialState));
|
||||
this._store.dispatch(misc_1.resetTo(this._state.initial));
|
||||
};
|
||||
|
||||
Choices.prototype._highlightChoice = function (el) {
|
||||
|
@ -3120,9 +3118,9 @@ function () {
|
|||
_b = _a.label,
|
||||
label = _b === void 0 ? null : _b,
|
||||
_c = _a.choiceId,
|
||||
choiceId = _c === void 0 ? -1 : _c,
|
||||
choiceId = _c === void 0 ? constants_1.DEFAULT_ID : _c,
|
||||
_d = _a.groupId,
|
||||
groupId = _d === void 0 ? -1 : _d,
|
||||
groupId = _d === void 0 ? constants_1.DEFAULT_ID : _d,
|
||||
_e = _a.customProperties,
|
||||
customProperties = _e === void 0 ? {} : _e,
|
||||
_f = _a.placeholder,
|
||||
|
@ -3132,7 +3130,6 @@ function () {
|
|||
var passedValue = typeof value === 'string' ? value.trim() : value;
|
||||
var items = this._store.items;
|
||||
var passedLabel = label || passedValue;
|
||||
var passedOptionId = choiceId || -1;
|
||||
var group = groupId >= 0 ? this._store.getGroupById(groupId) : null;
|
||||
var id = items ? items.length + 1 : 1; // If a prepended value has been passed, prepend it
|
||||
|
||||
|
@ -3149,7 +3146,7 @@ function () {
|
|||
value: passedValue,
|
||||
label: passedLabel,
|
||||
id: id,
|
||||
choiceId: passedOptionId,
|
||||
choiceId: choiceId,
|
||||
groupId: groupId,
|
||||
customProperties: customProperties,
|
||||
placeholder: placeholder,
|
||||
|
@ -3204,7 +3201,7 @@ function () {
|
|||
_d = _a.isDisabled,
|
||||
isDisabled = _d === void 0 ? false : _d,
|
||||
_e = _a.groupId,
|
||||
groupId = _e === void 0 ? -1 : _e,
|
||||
groupId = _e === void 0 ? constants_1.DEFAULT_ID : _e,
|
||||
_f = _a.customProperties,
|
||||
customProperties = _f === void 0 ? {} : _f,
|
||||
_g = _a.placeholder,
|
||||
|
@ -3214,8 +3211,7 @@ function () {
|
|||
|
||||
if (typeof value === 'undefined' || value === null) {
|
||||
return;
|
||||
} // Generate unique id
|
||||
|
||||
}
|
||||
|
||||
var choices = this._store.choices;
|
||||
var choiceLabel = label || value;
|
||||
|
@ -3259,37 +3255,37 @@ function () {
|
|||
var groupId = id || Math.floor(new Date().valueOf() * Math.random());
|
||||
var isDisabled = group.disabled ? group.disabled : false;
|
||||
|
||||
if (groupChoices) {
|
||||
this._store.dispatch(groups_1.addGroup({
|
||||
value: group.label,
|
||||
id: groupId,
|
||||
active: true,
|
||||
disabled: isDisabled
|
||||
}));
|
||||
|
||||
var addGroupChoices = function addGroupChoices(choice) {
|
||||
var isOptDisabled = choice.disabled || choice.parentNode && choice.parentNode.disabled;
|
||||
|
||||
_this._addChoice({
|
||||
value: choice[valueKey],
|
||||
label: utils_1.isType('Object', choice) ? choice[labelKey] : choice.innerHTML,
|
||||
isSelected: choice.selected,
|
||||
isDisabled: isOptDisabled,
|
||||
groupId: groupId,
|
||||
customProperties: choice.customProperties,
|
||||
placeholder: choice.placeholder
|
||||
});
|
||||
};
|
||||
|
||||
groupChoices.forEach(addGroupChoices);
|
||||
} else {
|
||||
this._store.dispatch(groups_1.addGroup({
|
||||
if (!groupChoices) {
|
||||
return this._store.dispatch(groups_1.addGroup({
|
||||
value: group.label,
|
||||
id: group.id,
|
||||
active: false,
|
||||
disabled: group.disabled
|
||||
}));
|
||||
}
|
||||
|
||||
this._store.dispatch(groups_1.addGroup({
|
||||
value: group.label,
|
||||
id: groupId,
|
||||
active: true,
|
||||
disabled: isDisabled
|
||||
}));
|
||||
|
||||
var addGroupChoices = function addGroupChoices(choice) {
|
||||
var isOptDisabled = choice.disabled || choice.parentNode && choice.parentNode.disabled;
|
||||
|
||||
_this._addChoice({
|
||||
value: choice[valueKey],
|
||||
label: utils_1.isType('Object', choice) ? choice[labelKey] : choice.innerHTML,
|
||||
isSelected: choice.selected,
|
||||
isDisabled: isOptDisabled,
|
||||
groupId: groupId,
|
||||
customProperties: choice.customProperties,
|
||||
placeholder: choice.placeholder
|
||||
});
|
||||
};
|
||||
|
||||
groupChoices.forEach(addGroupChoices);
|
||||
};
|
||||
|
||||
Choices.prototype._getTemplate = function (template) {
|
||||
|
@ -3383,17 +3379,17 @@ function () {
|
|||
|
||||
this._startLoading();
|
||||
|
||||
if (this._presetGroups.length) {
|
||||
this._addPredefinedGroups(this._presetGroups);
|
||||
if (this._presetData.groups.length) {
|
||||
this._addPredefinedGroups(this._presetData.groups);
|
||||
} else {
|
||||
this._addPredefinedChoices(this._presetChoices);
|
||||
this._addPredefinedChoices(this._presetData.choices);
|
||||
}
|
||||
|
||||
this._stopLoading();
|
||||
}
|
||||
|
||||
if (this._isTextElement) {
|
||||
this._addPredefinedItems(this._presetItems);
|
||||
this._addPredefinedItems(this._presetData.items);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3442,36 +3438,8 @@ function () {
|
|||
customProperties = choice.customProperties,
|
||||
placeholder = choice.placeholder;
|
||||
|
||||
if (_this._isSelectElement) {
|
||||
// If the choice is actually a group
|
||||
if (choice.choices) {
|
||||
_this._addGroup({
|
||||
group: choice,
|
||||
id: choice.id || null
|
||||
});
|
||||
} else {
|
||||
/**
|
||||
* If there is a selected choice already or the choice is not the first in
|
||||
* the array, add each choice normally.
|
||||
*
|
||||
* Otherwise we pre-select the first enabled choice in the array ("select-one" only)
|
||||
*/
|
||||
var shouldPreselect = _this._isSelectOneElement && !hasSelectedChoice && index === firstEnabledChoiceIndex;
|
||||
var isSelected = shouldPreselect ? true : choice.selected;
|
||||
var isDisabled = choice.disabled;
|
||||
console.log(isDisabled, choice);
|
||||
|
||||
_this._addChoice({
|
||||
value: value,
|
||||
label: label,
|
||||
isSelected: !!isSelected,
|
||||
isDisabled: !!isDisabled,
|
||||
placeholder: !!placeholder,
|
||||
customProperties: customProperties
|
||||
});
|
||||
}
|
||||
} else {
|
||||
_this._addChoice({
|
||||
if (!_this._isSelectElement) {
|
||||
return _this._addChoice({
|
||||
value: value,
|
||||
label: label,
|
||||
isSelected: !!choice.selected,
|
||||
|
@ -3479,7 +3447,35 @@ function () {
|
|||
placeholder: !!choice.placeholder,
|
||||
customProperties: customProperties
|
||||
});
|
||||
} // If the choice is actually a group
|
||||
|
||||
|
||||
if (choice.choices) {
|
||||
return _this._addGroup({
|
||||
group: choice,
|
||||
id: choice.id || null
|
||||
});
|
||||
}
|
||||
/**
|
||||
* If there is a selected choice already or the choice is not the first in
|
||||
* the array, add each choice normally.
|
||||
*
|
||||
* Otherwise we pre-select the first enabled choice in the array ("select-one" only)
|
||||
*/
|
||||
|
||||
|
||||
var shouldPreselect = _this._isSelectOneElement && !hasSelectedChoice && index === firstEnabledChoiceIndex;
|
||||
var isSelected = shouldPreselect ? true : choice.selected;
|
||||
var isDisabled = choice.disabled;
|
||||
|
||||
_this._addChoice({
|
||||
value: value,
|
||||
label: label,
|
||||
isSelected: !!isSelected,
|
||||
isDisabled: !!isDisabled,
|
||||
placeholder: !!placeholder,
|
||||
customProperties: customProperties
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -3518,7 +3514,7 @@ function () {
|
|||
|
||||
|
||||
if (!_this._isTextElement) {
|
||||
_this._addChoice({
|
||||
return _this._addChoice({
|
||||
value: item.value,
|
||||
label: item.label,
|
||||
isSelected: true,
|
||||
|
@ -3526,29 +3522,29 @@ function () {
|
|||
customProperties: item.customProperties,
|
||||
placeholder: item.placeholder
|
||||
});
|
||||
} else {
|
||||
_this._addItem({
|
||||
value: item.value,
|
||||
label: item.label,
|
||||
choiceId: item.id,
|
||||
customProperties: item.customProperties,
|
||||
placeholder: item.placeholder
|
||||
});
|
||||
}
|
||||
|
||||
_this._addItem({
|
||||
value: item.value,
|
||||
label: item.label,
|
||||
choiceId: item.id,
|
||||
customProperties: item.customProperties,
|
||||
placeholder: item.placeholder
|
||||
});
|
||||
},
|
||||
string: function string() {
|
||||
if (!_this._isTextElement) {
|
||||
_this._addChoice({
|
||||
return _this._addChoice({
|
||||
value: item,
|
||||
label: item,
|
||||
isSelected: true,
|
||||
isDisabled: false
|
||||
});
|
||||
} else {
|
||||
_this._addItem({
|
||||
value: item
|
||||
});
|
||||
}
|
||||
|
||||
_this._addItem({
|
||||
value: item
|
||||
});
|
||||
}
|
||||
};
|
||||
handleType[itemType]();
|
||||
|
@ -3577,7 +3573,7 @@ function () {
|
|||
};
|
||||
|
||||
Choices.prototype._generatePlaceholderValue = function () {
|
||||
if (this._isSelectElement) {
|
||||
if (this._isSelectElement && this.passedElement.placeholderOption) {
|
||||
var placeholderOption = this.passedElement.placeholderOption;
|
||||
return placeholderOption ? placeholderOption.text : null;
|
||||
}
|
||||
|
|
4
public/assets/scripts/choices.min.js
vendored
4
public/assets/scripts/choices.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -2085,15 +2085,15 @@ describe('choices', () => {
|
|||
hasFocussedInput = instance.input.isFocussed;
|
||||
});
|
||||
|
||||
describe('direction key', () => {
|
||||
const keyCodes = [
|
||||
KEY_CODES.UP_KEY,
|
||||
KEY_CODES.DOWN_KEY,
|
||||
KEY_CODES.PAGE_UP_KEY,
|
||||
KEY_CODES.PAGE_DOWN_KEY,
|
||||
describe('direction keys', () => {
|
||||
const directionKeyCodes = [
|
||||
KEY_CODES.upKey,
|
||||
KEY_CODES.downKey,
|
||||
KEY_CODES.pageUpKey,
|
||||
KEY_CODES.pageDownKey,
|
||||
];
|
||||
|
||||
keyCodes.forEach(keyCode => {
|
||||
directionKeyCodes.forEach(keyCode => {
|
||||
it(`calls _onDirectionKey with the expected arguments`, () => {
|
||||
const event = {
|
||||
keyCode,
|
||||
|
@ -2112,7 +2112,7 @@ describe('choices', () => {
|
|||
describe('select key', () => {
|
||||
it(`calls _onSelectKey with the expected arguments`, () => {
|
||||
const event = {
|
||||
keyCode: KEY_CODES.A_KEY,
|
||||
keyCode: KEY_CODES.aKey,
|
||||
};
|
||||
|
||||
instance._onKeyDown(event);
|
||||
|
@ -2127,7 +2127,7 @@ describe('choices', () => {
|
|||
describe('enter key', () => {
|
||||
it(`calls _onEnterKey with the expected arguments`, () => {
|
||||
const event = {
|
||||
keyCode: KEY_CODES.ENTER_KEY,
|
||||
keyCode: KEY_CODES.enterKey,
|
||||
};
|
||||
|
||||
instance._onKeyDown(event);
|
||||
|
@ -2141,9 +2141,9 @@ describe('choices', () => {
|
|||
});
|
||||
|
||||
describe('delete key', () => {
|
||||
const keyCodes = [KEY_CODES.DELETE_KEY, KEY_CODES.BACK_KEY];
|
||||
const deleteKeyCodes = [KEY_CODES.deleteKey, KEY_CODES.backKey];
|
||||
|
||||
keyCodes.forEach(keyCode => {
|
||||
deleteKeyCodes.forEach(keyCode => {
|
||||
it(`calls _onDeleteKey with the expected arguments`, () => {
|
||||
const event = {
|
||||
keyCode,
|
||||
|
|
|
@ -94,9 +94,12 @@ class Choices {
|
|||
_isSelectMultipleElement: boolean;
|
||||
_isSelectElement: boolean;
|
||||
_store: Store;
|
||||
_state: {
|
||||
initial: State;
|
||||
previous: State;
|
||||
current: State;
|
||||
};
|
||||
_templates: typeof templates;
|
||||
_initialState: State;
|
||||
_currentState: State;
|
||||
_prevState: State;
|
||||
_currentValue: string;
|
||||
_canSearch: boolean;
|
||||
|
@ -110,10 +113,12 @@ class Choices {
|
|||
_idNames: {
|
||||
itemChoice: string;
|
||||
};
|
||||
_presetGroups: Group[] | HTMLOptGroupElement[] | Element[];
|
||||
_presetOptions: Item[] | HTMLOptionElement[];
|
||||
_presetChoices: Partial<Choice>[];
|
||||
_presetItems: Item[] | string[];
|
||||
_presetData: {
|
||||
groups: Group[] | HTMLOptGroupElement[] | Element[];
|
||||
options: Item[] | HTMLOptionElement[];
|
||||
choices: Partial<Choice>[];
|
||||
items: Item[] | string[];
|
||||
};
|
||||
|
||||
constructor(
|
||||
element:
|
||||
|
@ -195,9 +200,11 @@ class Choices {
|
|||
this.initialised = false;
|
||||
|
||||
this._store = new Store();
|
||||
this._initialState = defaultState;
|
||||
this._currentState = defaultState;
|
||||
this._prevState = defaultState;
|
||||
this._state = {
|
||||
initial: defaultState,
|
||||
current: defaultState,
|
||||
previous: defaultState,
|
||||
};
|
||||
this._currentValue = '';
|
||||
this._canSearch = !!this.config.searchEnabled;
|
||||
this._isScrollingOnIe = false;
|
||||
|
@ -226,28 +233,30 @@ class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
if (this._isSelectElement) {
|
||||
// Assign preset groups from passed element
|
||||
this._presetGroups = (this.passedElement as WrappedSelect).optionGroups;
|
||||
// Assign preset options from passed element
|
||||
this._presetOptions = (this.passedElement as WrappedSelect).options;
|
||||
}
|
||||
|
||||
// Assign preset choices from passed object
|
||||
this._presetChoices = this.config.choices;
|
||||
// Assign preset items from passed object first
|
||||
this._presetItems = this.config.items;
|
||||
this._presetData = {
|
||||
choices: this.config.choices,
|
||||
items: this.config.items,
|
||||
// Assign preset option groups/options from passed element
|
||||
groups: this._isSelectElement
|
||||
? (this.passedElement as WrappedSelect).optionGroups
|
||||
: [],
|
||||
options: this._isSelectElement
|
||||
? (this.passedElement as WrappedSelect).options
|
||||
: [],
|
||||
};
|
||||
// Add any values passed from attribute
|
||||
if (this.passedElement.value && this._isTextElement) {
|
||||
const splitValues: string[] = this.passedElement.value.split(
|
||||
this.config.delimiter,
|
||||
);
|
||||
this._presetItems = (this._presetItems as string[]).concat(splitValues);
|
||||
this._presetData.items = (this._presetData.items as string[]).concat(
|
||||
splitValues,
|
||||
);
|
||||
}
|
||||
// Create array of choices from option elements
|
||||
if ((this.passedElement as WrappedSelect).options) {
|
||||
(this.passedElement as WrappedSelect).options.forEach(option => {
|
||||
this._presetChoices.push({
|
||||
this._presetData.choices.push({
|
||||
value: option.value,
|
||||
label: option.innerHTML,
|
||||
selected: !!option.selected,
|
||||
|
@ -337,7 +346,7 @@ class Choices {
|
|||
this.clearStore();
|
||||
|
||||
if (this._isSelectElement) {
|
||||
(this.passedElement as WrappedSelect).options = this._presetOptions;
|
||||
(this.passedElement as WrappedSelect).options = this._presetData.options;
|
||||
}
|
||||
|
||||
this._templates = templates;
|
||||
|
@ -628,8 +637,6 @@ class Choices {
|
|||
const fetcher = choicesArrayOrFetcher(this);
|
||||
|
||||
if (typeof Promise === 'function' && fetcher instanceof Promise) {
|
||||
// that's a promise
|
||||
// eslint-disable-next-line compat/compat
|
||||
return new Promise(resolve => requestAnimationFrame(resolve)) // eslint-disable-line compat/compat
|
||||
.then(() => this._handleLoadingState(true))
|
||||
.then(() => fetcher)
|
||||
|
@ -658,7 +665,7 @@ class Choices {
|
|||
|
||||
if (!Array.isArray(choicesArrayOrFetcher)) {
|
||||
throw new TypeError(
|
||||
`.setChoices must be called either with array of choices with a function resulting into Promise of array of choices`,
|
||||
`setChoices must be called either with array of choices with a function resulting into Promise of array of choices`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -726,15 +733,15 @@ class Choices {
|
|||
return;
|
||||
}
|
||||
|
||||
this._currentState = this._store.state;
|
||||
this._state.current = this._store.state;
|
||||
|
||||
const stateChanged =
|
||||
this._currentState.choices !== this._prevState.choices ||
|
||||
this._currentState.groups !== this._prevState.groups ||
|
||||
this._currentState.items !== this._prevState.items;
|
||||
this._state.current.choices !== this._state.previous.choices ||
|
||||
this._state.current.groups !== this._state.previous.groups ||
|
||||
this._state.current.items !== this._state.previous.items;
|
||||
const shouldRenderChoices = this._isSelectElement;
|
||||
const shouldRenderItems =
|
||||
this._currentState.items !== this._prevState.items;
|
||||
this._state.current.items !== this._state.previous.items;
|
||||
|
||||
if (!stateChanged) {
|
||||
return;
|
||||
|
@ -748,12 +755,11 @@ class Choices {
|
|||
this._renderItems();
|
||||
}
|
||||
|
||||
this._prevState = this._currentState;
|
||||
this._state.previous = this._state.current;
|
||||
}
|
||||
|
||||
_renderChoices(): void {
|
||||
const { activeGroups, activeChoices } = this._store;
|
||||
let choiceListFragment = document.createDocumentFragment();
|
||||
|
||||
this.choiceList.clear();
|
||||
|
||||
|
@ -761,31 +767,10 @@ class Choices {
|
|||
requestAnimationFrame(() => this.choiceList.scrollToTop());
|
||||
}
|
||||
|
||||
// If we have grouped options
|
||||
if (activeGroups.length >= 1 && !this._isSearching) {
|
||||
// If we have a placeholder choice along with groups
|
||||
const activePlaceholders = activeChoices.filter(
|
||||
activeChoice =>
|
||||
activeChoice.placeholder === true &&
|
||||
activeChoice.groupId === DEFAULT_ID,
|
||||
);
|
||||
if (activePlaceholders.length >= 1) {
|
||||
choiceListFragment = this._createChoicesFragment(
|
||||
activePlaceholders,
|
||||
choiceListFragment,
|
||||
);
|
||||
}
|
||||
choiceListFragment = this._createGroupsFragment(
|
||||
activeGroups,
|
||||
activeChoices,
|
||||
choiceListFragment,
|
||||
);
|
||||
} else if (activeChoices.length >= 1) {
|
||||
choiceListFragment = this._createChoicesFragment(
|
||||
activeChoices,
|
||||
choiceListFragment,
|
||||
);
|
||||
}
|
||||
const choiceListFragment = this._createChoiceListFragment(
|
||||
activeGroups,
|
||||
activeChoices,
|
||||
);
|
||||
|
||||
// If we have choices to show
|
||||
if (
|
||||
|
@ -805,30 +790,32 @@ class Choices {
|
|||
this.choiceList.append(notice);
|
||||
}
|
||||
} else {
|
||||
// Otherwise show a notice
|
||||
let dropdownItem;
|
||||
let notice;
|
||||
|
||||
if (this._isSearching) {
|
||||
notice =
|
||||
typeof this.config.noResultsText === 'function'
|
||||
? this.config.noResultsText()
|
||||
: this.config.noResultsText;
|
||||
|
||||
dropdownItem = this._getTemplate('notice', notice, 'no-results');
|
||||
} else {
|
||||
notice =
|
||||
typeof this.config.noChoicesText === 'function'
|
||||
? this.config.noChoicesText()
|
||||
: this.config.noChoicesText;
|
||||
|
||||
dropdownItem = this._getTemplate('notice', notice, 'no-choices');
|
||||
}
|
||||
|
||||
this.choiceList.append(dropdownItem);
|
||||
this.choiceList.append(
|
||||
this._isSearching
|
||||
? this._getNoResultsTemplate()
|
||||
: this._getNoChoicesTemplate(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_getNoChoicesTemplate(): HTMLElement {
|
||||
const textToDisplay =
|
||||
typeof this.config.noChoicesText === 'function'
|
||||
? this.config.noChoicesText()
|
||||
: this.config.noChoicesText;
|
||||
|
||||
return this._getTemplate('notice', textToDisplay, 'no-choices');
|
||||
}
|
||||
|
||||
_getNoResultsTemplate(): HTMLElement {
|
||||
const textToDisplay =
|
||||
typeof this.config.noResultsText === 'function'
|
||||
? this.config.noResultsText()
|
||||
: this.config.noResultsText;
|
||||
|
||||
return this._getTemplate('notice', textToDisplay, 'no-results');
|
||||
}
|
||||
|
||||
_renderItems(): void {
|
||||
const activeItems = this._store.activeItems || [];
|
||||
this.itemList.clear();
|
||||
|
@ -992,6 +979,40 @@ class Choices {
|
|||
return fragment;
|
||||
}
|
||||
|
||||
_createChoiceListFragment(
|
||||
groups: Group[],
|
||||
choices: Choice[],
|
||||
): DocumentFragment {
|
||||
let choiceListFragment = document.createDocumentFragment();
|
||||
// If we have grouped options
|
||||
if (groups.length >= 1 && !this._isSearching) {
|
||||
// If we have a placeholder choice along with groups
|
||||
const activePlaceholders = choices.filter(
|
||||
activeChoice =>
|
||||
activeChoice.placeholder === true &&
|
||||
activeChoice.groupId === DEFAULT_ID,
|
||||
);
|
||||
if (activePlaceholders.length >= 1) {
|
||||
choiceListFragment = this._createChoicesFragment(
|
||||
activePlaceholders,
|
||||
choiceListFragment,
|
||||
);
|
||||
}
|
||||
choiceListFragment = this._createGroupsFragment(
|
||||
groups,
|
||||
choices,
|
||||
choiceListFragment,
|
||||
);
|
||||
} else if (choices.length >= 1) {
|
||||
choiceListFragment = this._createChoicesFragment(
|
||||
choices,
|
||||
choiceListFragment,
|
||||
);
|
||||
}
|
||||
|
||||
return choiceListFragment;
|
||||
}
|
||||
|
||||
_triggerChange(value): void {
|
||||
if (value === undefined || value === null) {
|
||||
return;
|
||||
|
@ -1043,16 +1064,11 @@ class Choices {
|
|||
}
|
||||
|
||||
_handleItemAction(
|
||||
activeItems?: Item[],
|
||||
element?: HTMLElement,
|
||||
activeItems: Item[],
|
||||
element: HTMLElement,
|
||||
hasShiftKey = false,
|
||||
): void {
|
||||
if (
|
||||
!activeItems ||
|
||||
!element ||
|
||||
!this.config.removeItems ||
|
||||
this._isSelectOneElement
|
||||
) {
|
||||
if (!this.config.removeItems || this._isSelectOneElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1074,14 +1090,11 @@ class Choices {
|
|||
this.input.focus();
|
||||
}
|
||||
|
||||
_handleChoiceAction(activeItems?: Item[], element?: HTMLElement): void {
|
||||
if (!activeItems || !element) {
|
||||
return;
|
||||
}
|
||||
|
||||
_handleChoiceAction(activeItems: Item[], element: HTMLElement): void {
|
||||
// If we are clicking on an option
|
||||
const { id } = element.dataset;
|
||||
const choice = id && this._store.getChoiceById(id);
|
||||
|
||||
if (!choice) {
|
||||
return;
|
||||
}
|
||||
|
@ -1126,8 +1139,8 @@ class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
_handleBackspace(activeItems?: Item[]): void {
|
||||
if (!this.config.removeItems || !activeItems) {
|
||||
_handleBackspace(activeItems: Item[]): void {
|
||||
if (!this.config.removeItems) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1146,6 +1159,8 @@ class Choices {
|
|||
// Highlight last item if none already highlighted
|
||||
this.highlightItem(lastItem, false);
|
||||
}
|
||||
|
||||
// then remove all highlighted items
|
||||
this.removeHighlightedItems(true);
|
||||
}
|
||||
}
|
||||
|
@ -1158,12 +1173,12 @@ class Choices {
|
|||
this._store.dispatch(setIsLoading(false));
|
||||
}
|
||||
|
||||
_handleLoadingState(setLoading = true): void {
|
||||
_handleLoadingState(isLoading = true): void {
|
||||
let placeholderItem = this.itemList.getChild(
|
||||
`.${this.config.classNames.placeholder}`,
|
||||
);
|
||||
|
||||
if (setLoading) {
|
||||
if (isLoading) {
|
||||
this.disable();
|
||||
this.containerOuter.addLoadingState();
|
||||
|
||||
|
@ -1406,15 +1421,15 @@ class Choices {
|
|||
const wasAlphaNumericChar = /[a-zA-Z0-9-_ ]/.test(keyString);
|
||||
|
||||
const {
|
||||
BACK_KEY,
|
||||
DELETE_KEY,
|
||||
ENTER_KEY,
|
||||
A_KEY,
|
||||
ESC_KEY,
|
||||
UP_KEY,
|
||||
DOWN_KEY,
|
||||
PAGE_UP_KEY,
|
||||
PAGE_DOWN_KEY,
|
||||
backKey,
|
||||
deleteKey,
|
||||
enterKey,
|
||||
aKey,
|
||||
escKey,
|
||||
upKey,
|
||||
downKey,
|
||||
pageUpKey,
|
||||
pageDownKey,
|
||||
} = KEY_CODES;
|
||||
|
||||
if (!this._isTextElement && !hasActiveDropdown && wasAlphaNumericChar) {
|
||||
|
@ -1431,19 +1446,19 @@ class Choices {
|
|||
}
|
||||
|
||||
switch (keyCode) {
|
||||
case A_KEY:
|
||||
case aKey:
|
||||
return this._onSelectKey(event, hasItems);
|
||||
case ENTER_KEY:
|
||||
case enterKey:
|
||||
return this._onEnterKey(event, activeItems, hasActiveDropdown);
|
||||
case ESC_KEY:
|
||||
case escKey:
|
||||
return this._onEscapeKey(hasActiveDropdown);
|
||||
case UP_KEY:
|
||||
case PAGE_UP_KEY:
|
||||
case DOWN_KEY:
|
||||
case PAGE_DOWN_KEY:
|
||||
case upKey:
|
||||
case pageUpKey:
|
||||
case downKey:
|
||||
case pageDownKey:
|
||||
return this._onDirectionKey(event, hasActiveDropdown);
|
||||
case DELETE_KEY:
|
||||
case BACK_KEY:
|
||||
case deleteKey:
|
||||
case backKey:
|
||||
return this._onDeleteKey(event, activeItems, hasFocusedInput);
|
||||
default:
|
||||
}
|
||||
|
@ -1456,7 +1471,7 @@ class Choices {
|
|||
const { value } = this.input;
|
||||
const { activeItems } = this._store;
|
||||
const canAddItem = this._canAddItem(activeItems, value);
|
||||
const { BACK_KEY: backKey, DELETE_KEY: deleteKey } = KEY_CODES;
|
||||
const { backKey, deleteKey } = KEY_CODES;
|
||||
|
||||
// We are typing into a text input and have a value, we want to show a dropdown
|
||||
// notice. Otherwise hide the dropdown
|
||||
|
@ -1513,7 +1528,7 @@ class Choices {
|
|||
hasActiveDropdown: boolean,
|
||||
): void {
|
||||
const { target } = event;
|
||||
const { ENTER_KEY: enterKey } = KEY_CODES;
|
||||
const { enterKey: enterKey } = KEY_CODES;
|
||||
const targetWasButton =
|
||||
target && (target as HTMLElement).hasAttribute('data-button');
|
||||
|
||||
|
@ -1563,9 +1578,9 @@ class Choices {
|
|||
_onDirectionKey(event: KeyboardEvent, hasActiveDropdown: boolean): void {
|
||||
const { keyCode, metaKey } = event;
|
||||
const {
|
||||
DOWN_KEY: downKey,
|
||||
PAGE_UP_KEY: pageUpKey,
|
||||
PAGE_DOWN_KEY: pageDownKey,
|
||||
downKey: downKey,
|
||||
pageUpKey: pageUpKey,
|
||||
pageDownKey: pageDownKey,
|
||||
} = KEY_CODES;
|
||||
|
||||
// If up or down key is pressed, traverse through options
|
||||
|
@ -1841,7 +1856,7 @@ class Choices {
|
|||
}
|
||||
|
||||
_onFormReset(): void {
|
||||
this._store.dispatch(resetTo(this._initialState));
|
||||
this._store.dispatch(resetTo(this._state.initial));
|
||||
}
|
||||
|
||||
_highlightChoice(el: HTMLElement | null = null): void {
|
||||
|
@ -2176,17 +2191,17 @@ class Choices {
|
|||
this._isSearching = false;
|
||||
this._startLoading();
|
||||
|
||||
if (this._presetGroups.length) {
|
||||
this._addPredefinedGroups(this._presetGroups);
|
||||
if (this._presetData.groups.length) {
|
||||
this._addPredefinedGroups(this._presetData.groups);
|
||||
} else {
|
||||
this._addPredefinedChoices(this._presetChoices);
|
||||
this._addPredefinedChoices(this._presetData.choices);
|
||||
}
|
||||
|
||||
this._stopLoading();
|
||||
}
|
||||
|
||||
if (this._isTextElement) {
|
||||
this._addPredefinedItems(this._presetItems);
|
||||
this._addPredefinedItems(this._presetData.items);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,15 +132,15 @@ describe('constants', () => {
|
|||
it('exports as an object with expected keys', () => {
|
||||
expect(KEY_CODES).to.be.an('object');
|
||||
expect(Object.keys(KEY_CODES)).to.eql([
|
||||
'BACK_KEY',
|
||||
'DELETE_KEY',
|
||||
'ENTER_KEY',
|
||||
'A_KEY',
|
||||
'ESC_KEY',
|
||||
'UP_KEY',
|
||||
'DOWN_KEY',
|
||||
'PAGE_UP_KEY',
|
||||
'PAGE_DOWN_KEY',
|
||||
'backKey',
|
||||
'deleteKey',
|
||||
'enterKey',
|
||||
'aKey',
|
||||
'escKey',
|
||||
'upKey',
|
||||
'downKey',
|
||||
'pageUpKey',
|
||||
'pageDownKey',
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -111,15 +111,15 @@ export const ACTION_TYPES: Record<ActionType, ActionType> = {
|
|||
};
|
||||
|
||||
export const KEY_CODES: KeyCodeMap = {
|
||||
BACK_KEY: 46,
|
||||
DELETE_KEY: 8,
|
||||
ENTER_KEY: 13,
|
||||
A_KEY: 65,
|
||||
ESC_KEY: 27,
|
||||
UP_KEY: 38,
|
||||
DOWN_KEY: 40,
|
||||
PAGE_UP_KEY: 33,
|
||||
PAGE_DOWN_KEY: 34,
|
||||
backKey: 46,
|
||||
deleteKey: 8,
|
||||
enterKey: 13,
|
||||
aKey: 65,
|
||||
escKey: 27,
|
||||
upKey: 38,
|
||||
downKey: 40,
|
||||
pageUpKey: 33,
|
||||
pageDownKey: 34,
|
||||
};
|
||||
|
||||
export const TEXT_TYPE: HTMLInputElement['type'] = 'text';
|
||||
|
|
|
@ -159,15 +159,15 @@ export interface EventMap {
|
|||
}
|
||||
|
||||
export interface KeyCodeMap {
|
||||
BACK_KEY: 46;
|
||||
DELETE_KEY: 8;
|
||||
ENTER_KEY: 13;
|
||||
A_KEY: 65;
|
||||
ESC_KEY: 27;
|
||||
UP_KEY: 38;
|
||||
DOWN_KEY: 40;
|
||||
PAGE_UP_KEY: 33;
|
||||
PAGE_DOWN_KEY: 34;
|
||||
backKey: 46;
|
||||
deleteKey: 8;
|
||||
enterKey: 13;
|
||||
aKey: 65;
|
||||
escKey: 27;
|
||||
upKey: 38;
|
||||
downKey: 40;
|
||||
pageUpKey: 33;
|
||||
pageDownKey: 34;
|
||||
}
|
||||
|
||||
export type ActionType =
|
||||
|
|
Loading…
Reference in a new issue