mirror of
https://github.com/Choices-js/Choices.git
synced 2024-04-30 04:52:51 +02:00
Sort choices by label
This commit is contained in:
parent
a862e4a00a
commit
b45715c5be
4
assets/scripts/dist/choices.min.js
vendored
4
assets/scripts/dist/choices.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -44,7 +44,7 @@ export const filterChoices = (results) => {
|
|||
|
||||
export const activateChoices = (active = true) => {
|
||||
return {
|
||||
type: 'ACTIVATE_OPTIONS',
|
||||
type: 'ACTIVATE_CHOICES',
|
||||
active,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ import Store from './store/index.js';
|
|||
* - Single select box search in dropdown
|
||||
*/
|
||||
export class Choices {
|
||||
constructor(element = '[data-choice]', userOptions = {}) {
|
||||
constructor(element = '[data-option]', userConfig = {}) {
|
||||
|
||||
// If there are multiple elements, create a new instance
|
||||
// for each element besides the first one (as that already has an instance)
|
||||
|
@ -22,12 +22,12 @@ export class Choices {
|
|||
if(elements.length > 1) {
|
||||
for (let i = 1; i < elements.length; i++) {
|
||||
const el = elements[i];
|
||||
new Choices(el, userOptions);
|
||||
new Choices(el, userConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const defaultOptions = {
|
||||
const defaultConfig = {
|
||||
items: [],
|
||||
maxItemCount: -1,
|
||||
addItems: true,
|
||||
|
@ -76,7 +76,7 @@ export class Choices {
|
|||
};
|
||||
|
||||
// Merge options with user options
|
||||
this.options = extend(defaultOptions, userOptions);
|
||||
this.config = extend(defaultConfig, userConfig);
|
||||
|
||||
// Create data store
|
||||
this.store = new Store(this.render);
|
||||
|
@ -87,17 +87,17 @@ export class Choices {
|
|||
this.prevState = {};
|
||||
this.currentValue = '';
|
||||
|
||||
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
|
||||
// Retrieve triggering element (i.e. element with 'data-option' trigger)
|
||||
this.passedElement = isType('String', element) ? document.querySelector(element) : element;
|
||||
|
||||
this.highlightPosition = 0;
|
||||
this.canSearch = this.options.searchOptions;
|
||||
this.canSearch = this.config.searchOptions;
|
||||
|
||||
// Assign preset items from passed object first
|
||||
this.presetItems = this.options.items;
|
||||
this.presetItems = this.config.items;
|
||||
// Then add any values passed from attribute
|
||||
if(this.passedElement.value !== '') {
|
||||
this.presetItems = this.presetItems.concat(this.passedElement.value.split(this.options.delimiter));
|
||||
if(this.passedElement.value) {
|
||||
this.presetItems = this.presetItems.concat(this.passedElement.value.split(this.config.delimiter));
|
||||
}
|
||||
|
||||
// Bind methods
|
||||
|
@ -124,10 +124,13 @@ export class Choices {
|
|||
const canInit = this.passedElement && ['select-one', 'select-multiple', 'text'].includes(this.passedElement.type);
|
||||
|
||||
if(canInit) {
|
||||
// Let's have it large
|
||||
this.init();
|
||||
// If element has already been initalised with Choices
|
||||
if(this.passedElement.hasAttribute('data-choice')) return
|
||||
|
||||
// Let's go
|
||||
this.init();
|
||||
} else {
|
||||
console.error('Choices: Incompatible input passed');
|
||||
console.error('Incompatible input passed');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +159,7 @@ export class Choices {
|
|||
this._addEventListeners();
|
||||
|
||||
// Run callback if it is a function
|
||||
if(callback = this.options.callbackOnInit){
|
||||
if(callback = this.config.callbackOnInit){
|
||||
if(isType('Function', callback)) {
|
||||
callback();
|
||||
} else {
|
||||
|
@ -172,7 +175,7 @@ export class Choices {
|
|||
* @public
|
||||
*/
|
||||
destroy() {
|
||||
this.passedElement.classList.remove(this.options.classNames.input, this.options.classNames.hiddenState);
|
||||
this.passedElement.classList.remove(this.config.classNames.input, this.config.classNames.hiddenState);
|
||||
this.passedElement.tabIndex = '';
|
||||
this.passedElement.removeAttribute('style', 'display:none;');
|
||||
this.passedElement.removeAttribute('aria-hidden');
|
||||
|
@ -180,8 +183,8 @@ export class Choices {
|
|||
this.containerOuter.outerHTML = this.passedElement.outerHTML;
|
||||
|
||||
this.passedElement = null;
|
||||
this.userOptions = null;
|
||||
this.options = null;
|
||||
this.userConfig = null;
|
||||
this.config = null;
|
||||
this.store = null;
|
||||
|
||||
this._removeEventListeners();
|
||||
|
@ -306,17 +309,17 @@ export class Choices {
|
|||
* @public
|
||||
*/
|
||||
showDropdown() {
|
||||
this.containerOuter.classList.add(this.options.classNames.openState);
|
||||
this.dropdown.classList.add(this.options.classNames.activeState);
|
||||
this.containerOuter.classList.add(this.config.classNames.openState);
|
||||
this.dropdown.classList.add(this.config.classNames.activeState);
|
||||
|
||||
const dimensions = this.dropdown.getBoundingClientRect();
|
||||
const shouldFlip = dimensions.top + dimensions.height >= document.body.offsetHeight;
|
||||
|
||||
// Whether or not the dropdown should appear above or below input
|
||||
if(shouldFlip) {
|
||||
this.containerOuter.classList.add(this.options.classNames.flippedState);
|
||||
this.containerOuter.classList.add(this.config.classNames.flippedState);
|
||||
} else {
|
||||
this.containerOuter.classList.remove(this.options.classNames.flippedState);
|
||||
this.containerOuter.classList.remove(this.config.classNames.flippedState);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -329,13 +332,13 @@ export class Choices {
|
|||
*/
|
||||
hideDropdown() {
|
||||
// A dropdown flips if it does not have space below the input
|
||||
const isFlipped = this.containerOuter.classList.contains(this.options.classNames.flippedState);
|
||||
const isFlipped = this.containerOuter.classList.contains(this.config.classNames.flippedState);
|
||||
|
||||
this.containerOuter.classList.remove(this.options.classNames.openState);
|
||||
this.dropdown.classList.remove(this.options.classNames.activeState);
|
||||
this.containerOuter.classList.remove(this.config.classNames.openState);
|
||||
this.dropdown.classList.remove(this.config.classNames.activeState);
|
||||
|
||||
if(isFlipped) {
|
||||
this.containerOuter.classList.remove(this.options.classNames.flippedState);
|
||||
this.containerOuter.classList.remove(this.config.classNames.flippedState);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -347,9 +350,11 @@ export class Choices {
|
|||
* @public
|
||||
*/
|
||||
toggleDropdown() {
|
||||
const isActive = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
|
||||
isActive ? this.hideDropdown() : this.showDropdown();
|
||||
if(this.dropdown.classList.contains(this.config.classNames.activeState)) {
|
||||
this.hideDropdown()
|
||||
} else {
|
||||
this.showDropdown();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -405,7 +410,7 @@ export class Choices {
|
|||
this.passedElement.disabled = true;
|
||||
if(this.initialised) {
|
||||
this.input.disabled = true;
|
||||
this.containerOuter.classList.add(this.options.classNames.disabledState);
|
||||
this.containerOuter.classList.add(this.config.classNames.disabledState);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -417,29 +422,33 @@ export class Choices {
|
|||
* @public
|
||||
*/
|
||||
ajax(fn) {
|
||||
if(this.passedElement.type === 'select-one' || this.passedElement.type === 'select-multiple') {
|
||||
this.containerOuter.classList.add('is-loading');
|
||||
// this.input.placeholder = this.options.loadingText;
|
||||
if(this.initialised === true) {
|
||||
if(this.passedElement.type === 'select-one' || this.passedElement.type === 'select-multiple') {
|
||||
this.containerOuter.classList.add('is-loading');
|
||||
// this.input.placeholder = this.config.loadingText;
|
||||
|
||||
const placeholderItem = this._getTemplate('item', { id: -1, value: 'Loading', label: this.options.loadingText, active: true});
|
||||
this.itemList.appendChild(placeholderItem);
|
||||
const placeholderItem = this._getTemplate('item', { id: -1, value: 'Loading', label: this.config.loadingText, active: true});
|
||||
this.itemList.appendChild(placeholderItem);
|
||||
|
||||
const callback = (results, value, label) => {
|
||||
if(results && results.length) {
|
||||
this.containerOuter.classList.remove('is-loading');
|
||||
this.input.placeholder = "";
|
||||
results.forEach((result, index) => {
|
||||
// Select first choice in list if single select input
|
||||
if(index === 0 && this.passedElement.type === 'select-one') {
|
||||
this._addChoice(true, false, result[value], result[label]);
|
||||
} else {
|
||||
this._addChoice(false, false, result[value], result[label]);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
const callback = (results, value, label) => {
|
||||
if(!isType('Array', results) || !value) return;
|
||||
|
||||
fn(callback);
|
||||
if(results && results.length) {
|
||||
this.containerOuter.classList.remove('is-loading');
|
||||
this.input.placeholder = "";
|
||||
results.forEach((result, index) => {
|
||||
// Select first choice in list if single select input
|
||||
if(index === 0 && this.passedElement.type === 'select-one') {
|
||||
this._addChoice(true, false, result[value], result[label]);
|
||||
} else {
|
||||
this._addChoice(false, false, result[value], result[label]);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
fn(callback);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -468,12 +477,12 @@ export class Choices {
|
|||
_handleEnter(activeItems, value) {
|
||||
let canUpdate = true;
|
||||
|
||||
if(this.options.addItems) {
|
||||
if (this.options.maxItemCount && this.options.maxItemCount > 0 && this.options.maxItemCount <= this.itemList.children.length) {
|
||||
if(this.config.addItems) {
|
||||
if (this.config.maxItemCount && this.config.maxItemCount > 0 && this.config.maxItemCount <= this.itemList.children.length) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
canUpdate = false;
|
||||
} else if(this.options.duplicateItems === false && this.passedElement.value) {
|
||||
} else if(this.config.duplicateItems === false && this.passedElement.value) {
|
||||
// If no duplicates are allowed, and the value already exists
|
||||
// in the array, don't update
|
||||
canUpdate = !activeItems.some((item) => item.value === value );
|
||||
|
@ -486,7 +495,7 @@ export class Choices {
|
|||
let canAddItem = true;
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if(this.options.regexFilter) {
|
||||
if(this.config.regexFilter) {
|
||||
// Determine whether we can update based on whether
|
||||
// our regular expression passes
|
||||
canAddItem = this._regexFilter(value);
|
||||
|
@ -508,13 +517,13 @@ export class Choices {
|
|||
* @private
|
||||
*/
|
||||
_handleBackspace(activeItems) {
|
||||
if(this.options.removeItems && activeItems) {
|
||||
if(this.config.removeItems && activeItems) {
|
||||
const lastItem = activeItems[activeItems.length - 1];
|
||||
const hasSelectedItems = activeItems.some((item) => item.selected === true);
|
||||
|
||||
// If editing the last item is allowed and there are not other selected items,
|
||||
// we can edit the item value. Otherwise if we can remove items, remove all selected items
|
||||
if(this.options.editItems && !hasSelectedItems && lastItem) {
|
||||
if(this.config.editItems && !hasSelectedItems && lastItem) {
|
||||
this.input.value = lastItem.value;
|
||||
this._removeItem(lastItem);
|
||||
} else {
|
||||
|
@ -545,7 +554,7 @@ export class Choices {
|
|||
const activeChoices = this.store.getChoicesFilteredByActive();
|
||||
|
||||
const hasFocusedInput = this.input === document.activeElement;
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
const hasItems = this.itemList && this.itemList.children;
|
||||
const keyString = String.fromCharCode(event.keyCode);
|
||||
|
||||
|
@ -554,14 +563,14 @@ export class Choices {
|
|||
this.showDropdown();
|
||||
}
|
||||
|
||||
this.canSearch = this.options.searchOptions;
|
||||
this.canSearch = this.config.searchOptions;
|
||||
|
||||
switch (e.keyCode) {
|
||||
case aKey:
|
||||
// If CTRL + A or CMD + A have been pressed and there are items to select
|
||||
if(ctrlDownKey && hasItems) {
|
||||
this.canSearch = false;
|
||||
if(this.options.removeItems && !this.input.value && this.input === document.activeElement) {
|
||||
if(this.config.removeItems && !this.input.value && this.input === document.activeElement) {
|
||||
// Highlight items
|
||||
this.highlightAll(this.itemList.children);
|
||||
}
|
||||
|
@ -576,7 +585,7 @@ export class Choices {
|
|||
}
|
||||
|
||||
if(hasActiveDropdown) {
|
||||
const highlighted = this.dropdown.querySelector(`.${this.options.classNames.highlightedState}`);
|
||||
const highlighted = this.dropdown.querySelector(`.${this.config.classNames.highlightedState}`);
|
||||
|
||||
if(highlighted) {
|
||||
const value = highlighted.getAttribute('data-value');
|
||||
|
@ -595,16 +604,14 @@ export class Choices {
|
|||
break;
|
||||
|
||||
case escapeKey:
|
||||
if(hasActiveDropdown) {
|
||||
this.toggleDropdown();
|
||||
}
|
||||
if(hasActiveDropdown) this.toggleDropdown();
|
||||
break;
|
||||
|
||||
case downKey:
|
||||
case upKey:
|
||||
// If up or down key is pressed, traverse through options
|
||||
if(hasActiveDropdown) {
|
||||
const currentEl = this.dropdown.querySelector(`.${this.options.classNames.highlightedState}`);
|
||||
const currentEl = this.dropdown.querySelector(`.${this.config.classNames.highlightedState}`);
|
||||
const directionInt = e.keyCode === downKey ? 1 : -1;
|
||||
let nextEl;
|
||||
|
||||
|
@ -658,29 +665,31 @@ export class Choices {
|
|||
// We are typing into a text input and have a value, we want to show a dropdown
|
||||
// notice. Otherwise hide the dropdown
|
||||
if(this.passedElement.type === 'text') {
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
let dropdownItem;
|
||||
if(this.input.value) {
|
||||
const activeItems = this.store.getItemsFilteredByActive();
|
||||
const isUnique = !activeItems.some((item) => item.value === this.input.value);
|
||||
|
||||
if (this.options.maxItemCount && this.options.maxItemCount > 0 && this.options.maxItemCount <= this.itemList.children.length) {
|
||||
dropdownItem = this._getTemplate('notice', `Only ${ this.options.maxItemCount } options can be added.`);
|
||||
} else if(!this.options.duplicateItems && !isUnique) {
|
||||
if (this.config.maxItemCount && this.config.maxItemCount > 0 && this.config.maxItemCount <= this.itemList.children.length) {
|
||||
dropdownItem = this._getTemplate('notice', `Only ${ this.config.maxItemCount } options can be added.`);
|
||||
} else if(!this.config.duplicateItems && !isUnique) {
|
||||
dropdownItem = this._getTemplate('notice', `Only unique values can be added.`);
|
||||
} else {
|
||||
dropdownItem = this._getTemplate('notice', `Add "${ this.input.value }"`);
|
||||
}
|
||||
|
||||
if((this.options.regexFilter && this._regexFilter(this.input.value)) || !this.options.regexFilter) {
|
||||
if((this.config.regexFilter && this._regexFilter(this.input.value)) || !this.config.regexFilter) {
|
||||
this.dropdown.innerHTML = dropdownItem.outerHTML;
|
||||
if(!this.dropdown.classList.contains(this.options.classNames.activeState)) {
|
||||
if(!this.dropdown.classList.contains(this.config.classNames.activeState)) {
|
||||
this.showDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if(hasActiveDropdown) this.hideDropdown();
|
||||
if(hasActiveDropdown) {
|
||||
this.hideDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -717,7 +726,7 @@ export class Choices {
|
|||
} else if(hasUnactiveChoices) {
|
||||
// Otherwise reset options to active
|
||||
this.isSearching = false;
|
||||
this.store.dispatch(activateChoices());
|
||||
this.store.dispatch(activateChoices(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -731,7 +740,7 @@ export class Choices {
|
|||
*/
|
||||
_onInput(e) {
|
||||
if(this.passedElement.type !== 'select-one') {
|
||||
this.input.style.width = getWidthOfInput(this.input);
|
||||
this.input.style.width = getWidthOfInput(this.input);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,7 +764,7 @@ export class Choices {
|
|||
|
||||
const hasShiftKey = e.shiftKey ? true : false;
|
||||
|
||||
if(this.passedElement.type !== 'text' && !this.dropdown.classList.contains(this.options.classNames.activeState)) {
|
||||
if(this.passedElement.type !== 'text' && !this.dropdown.classList.contains(this.config.classNames.activeState)) {
|
||||
// For select inputs we always want to show the dropdown if it isn't already showing
|
||||
this.showDropdown();
|
||||
}
|
||||
|
@ -766,14 +775,14 @@ export class Choices {
|
|||
}
|
||||
|
||||
if(e.target.hasAttribute('data-button')) {
|
||||
if(this.options.removeItems && this.options.removeItemButton) {
|
||||
if(this.config.removeItems && this.config.removeItemButton) {
|
||||
const itemId = e.target.parentNode.getAttribute('data-id');
|
||||
const itemToRemove = activeItems.find((item) => item.id === parseInt(itemId));
|
||||
this._removeItem(itemToRemove);
|
||||
}
|
||||
} else if(e.target.hasAttribute('data-item')) {
|
||||
// If we are clicking on an item
|
||||
if(this.options.removeItems) {
|
||||
if(this.config.removeItems) {
|
||||
const passedId = e.target.getAttribute('data-id');
|
||||
|
||||
// We only want to select one item with a click
|
||||
|
@ -806,17 +815,21 @@ export class Choices {
|
|||
|
||||
} else {
|
||||
// Click is outside of our element so close dropdown and de-select items
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
const hasSelectedItems = activeItems.some((item) => item.selected === true);
|
||||
|
||||
// De-select any highlighted items
|
||||
if(hasSelectedItems) this.unhighlightAll();
|
||||
if(hasSelectedItems) {
|
||||
this.unhighlightAll();
|
||||
}
|
||||
|
||||
// Remove focus state
|
||||
this.containerOuter.classList.remove(this.options.classNames.focusState);
|
||||
this.containerOuter.classList.remove(this.config.classNames.focusState);
|
||||
|
||||
// Close all other dropdowns
|
||||
if(hasActiveDropdown) this.toggleDropdown();
|
||||
if(hasActiveDropdown) {
|
||||
this.toggleDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -829,10 +842,8 @@ export class Choices {
|
|||
*/
|
||||
_onMouseOver(e) {
|
||||
// If the dropdown is either the target or one of its children is the target
|
||||
if((e.target === this.dropdown || findAncestor(e.target, this.options.classNames.listDropdown))) {
|
||||
if(e.target.hasAttribute('data-option')) {
|
||||
this._highlightChoice(e.target);
|
||||
}
|
||||
if((e.target === this.dropdown || findAncestor(e.target, this.config.classNames.listDropdown))) {
|
||||
if(e.target.hasAttribute('data-option')) this._highlightChoice(e.target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -845,8 +856,8 @@ export class Choices {
|
|||
_onPaste(e) {
|
||||
if(e.target !== this.input) return;
|
||||
// Disable pasting into the input if option has been set
|
||||
if(!this.options.paste) {
|
||||
e.preventDefault();
|
||||
if(!this.config.paste) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,9 +869,9 @@ export class Choices {
|
|||
* @private
|
||||
*/
|
||||
_onFocus(e) {
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
if(e.target === this.input && !hasActiveDropdown) {
|
||||
this.containerOuter.classList.add(this.options.classNames.focusState);
|
||||
this.containerOuter.classList.add(this.config.classNames.focusState);
|
||||
if(this.passedElement.type === 'select-one' || this.passedElement.type === 'select-multiple'){
|
||||
this.showDropdown();
|
||||
}
|
||||
|
@ -874,9 +885,9 @@ export class Choices {
|
|||
* @private
|
||||
*/
|
||||
_onBlur(e) {
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
|
||||
if(e.target === this.input && !hasActiveDropdown) {
|
||||
this.containerOuter.classList.remove(this.options.classNames.focusState);
|
||||
this.containerOuter.classList.remove(this.config.classNames.focusState);
|
||||
} else {
|
||||
this.hideDropdown();
|
||||
}
|
||||
|
@ -891,7 +902,7 @@ export class Choices {
|
|||
*/
|
||||
_regexFilter(value) {
|
||||
if(!value) return;
|
||||
const expression = new RegExp(this.options.regexFilter, 'i');
|
||||
const expression = new RegExp(this.config.regexFilter, 'i');
|
||||
return expression.test(value);
|
||||
}
|
||||
|
||||
|
@ -963,16 +974,16 @@ export class Choices {
|
|||
const options = Array.from(this.dropdown.querySelectorAll('[data-option-selectable]'));
|
||||
|
||||
if(options && options.length) {
|
||||
const highlightedOptions = Array.from(this.dropdown.querySelectorAll(`.${this.options.classNames.highlightedState}`));
|
||||
const highlightedOptions = Array.from(this.dropdown.querySelectorAll(`.${this.config.classNames.highlightedState}`));
|
||||
|
||||
// Remove any highlighted options
|
||||
highlightedOptions.forEach((el) => {
|
||||
el.classList.remove(this.options.classNames.highlightedState);
|
||||
el.classList.remove(this.config.classNames.highlightedState);
|
||||
});
|
||||
|
||||
if(el){
|
||||
// Highlight given option
|
||||
el.classList.add(this.options.classNames.highlightedState);
|
||||
el.classList.add(this.config.classNames.highlightedState);
|
||||
this.highlightPosition = options.indexOf(el);
|
||||
} else {
|
||||
// Highlight option based on last known highlight location
|
||||
|
@ -987,7 +998,7 @@ export class Choices {
|
|||
}
|
||||
|
||||
if(!el) el = options[0];
|
||||
el.classList.add(this.options.classNames.highlightedState);
|
||||
el.classList.add(this.config.classNames.highlightedState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -999,20 +1010,20 @@ export class Choices {
|
|||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
_addItem(value, label, choiceId = -1, callback = this.options.callbackOnAddItem) {
|
||||
_addItem(value, label, choiceId = -1, callback = this.config.callbackOnAddItem) {
|
||||
const items = this.store.getItems();
|
||||
let passedValue = value.trim();
|
||||
let passedLabel = label || passedValue;
|
||||
let passedOptionId = choiceId || -1;
|
||||
|
||||
// If a prepended value has been passed, prepend it
|
||||
if(this.options.prependValue) {
|
||||
passedValue = this.options.prependValue + passedValue.toString();
|
||||
if(this.config.prependValue) {
|
||||
passedValue = this.config.prependValue + passedValue.toString();
|
||||
}
|
||||
|
||||
// If an appended value has been passed, append it
|
||||
if(this.options.appendValue) {
|
||||
passedValue = passedValue + this.options.appendValue.toString();
|
||||
if(this.config.appendValue) {
|
||||
passedValue = passedValue + this.config.appendValue.toString();
|
||||
}
|
||||
|
||||
// Generate unique id
|
||||
|
@ -1042,7 +1053,7 @@ export class Choices {
|
|||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
_removeItem(item, callback = this.options.callbackOnRemoveItem) {
|
||||
_removeItem(item, callback = this.config.callbackOnRemoveItem) {
|
||||
if(!item || !isType('Object', item)) {
|
||||
console.error('removeItem: No item object was passed to be removed');
|
||||
return;
|
||||
|
@ -1115,7 +1126,7 @@ export class Choices {
|
|||
*/
|
||||
_getTemplate(template, ...args) {
|
||||
if(!template) return;
|
||||
const templates = this.options.templates;
|
||||
const templates = this.config.templates;
|
||||
return templates[template](...args);
|
||||
}
|
||||
|
||||
|
@ -1125,7 +1136,7 @@ export class Choices {
|
|||
* @private
|
||||
*/
|
||||
_createTemplates() {
|
||||
const classNames = this.options.classNames;
|
||||
const classNames = this.config.classNames;
|
||||
const templates = {
|
||||
containerOuter: () => {
|
||||
return strToEl(`<div class="${ classNames.containerOuter }" data-type="${ this.passedElement.type }"></div>`);
|
||||
|
@ -1166,7 +1177,7 @@ export class Choices {
|
|||
`);
|
||||
},
|
||||
item: (data) => {
|
||||
if(this.options.removeItemButton && this.passedElement.type !== 'select-one') {
|
||||
if(this.config.removeItemButton && this.passedElement.type !== 'select-one') {
|
||||
return strToEl(`
|
||||
<div class="${ classNames.item } ${ data.selected ? classNames.selectedState : ''} ${ !data.disabled ? classNames.itemSelectable : '' }" data-item data-id="${ data.id }" data-value="${ data.value }" data-deletable>
|
||||
${ data.label }
|
||||
|
@ -1183,7 +1194,7 @@ export class Choices {
|
|||
},
|
||||
};
|
||||
|
||||
this.options.templates = extend(this.options.templates, templates);
|
||||
this.config.templates = extend(this.config.templates, templates);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1207,11 +1218,11 @@ export class Choices {
|
|||
this.dropdown = dropdown;
|
||||
|
||||
// Hide passed input
|
||||
this.passedElement.classList.add(this.options.classNames.input, this.options.classNames.hiddenState);
|
||||
this.passedElement.classList.add(this.config.classNames.input, this.config.classNames.hiddenState);
|
||||
this.passedElement.tabIndex = '-1';
|
||||
this.passedElement.setAttribute('style', 'display:none;');
|
||||
this.passedElement.setAttribute('aria-hidden', 'true');
|
||||
this.passedElement.removeAttribute('data-choice');
|
||||
this.passedElement.setAttribute('data-choice', '');
|
||||
|
||||
// Wrap input in container preserving DOM ordering
|
||||
wrap(this.passedElement, containerInner);
|
||||
|
@ -1220,15 +1231,15 @@ export class Choices {
|
|||
wrap(containerInner, containerOuter);
|
||||
|
||||
// If placeholder has been enabled and we have a value
|
||||
if (this.options.placeholder && (this.options.placeholderValue || this.passedElement.placeholder)) {
|
||||
const placeholder = this.options.placeholderValue || this.passedElement.placeholder;
|
||||
if (this.config.placeholder && (this.config.placeholderValue || this.passedElement.placeholder)) {
|
||||
const placeholder = this.config.placeholderValue || this.passedElement.placeholder;
|
||||
input.placeholder = placeholder;
|
||||
if(this.passedElement.type !== 'select-one') {
|
||||
input.style.width = getWidthOfInput(input);
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.options.addItems) this.disable();
|
||||
if(!this.config.addItems) this.disable();
|
||||
|
||||
containerOuter.appendChild(containerInner);
|
||||
containerOuter.appendChild(dropdown);
|
||||
|
@ -1237,7 +1248,7 @@ export class Choices {
|
|||
|
||||
if(this.passedElement.type === 'select-multiple' || this.passedElement.type === 'text') {
|
||||
containerInner.appendChild(input);
|
||||
} else if(this.options.searchOptions) {
|
||||
} else if(this.config.searchOptions) {
|
||||
dropdown.insertBefore(input, dropdown.firstChild);
|
||||
}
|
||||
|
||||
|
@ -1346,7 +1357,7 @@ export class Choices {
|
|||
|
||||
if(this.passedElement.type === 'text') {
|
||||
// Assign hidden input array of values
|
||||
this.passedElement.setAttribute('value', itemsFiltered.join(this.options.delimiter));
|
||||
this.passedElement.setAttribute('value', itemsFiltered.join(this.config.delimiter));
|
||||
} else {
|
||||
const selectedOptionsFragment = document.createDocumentFragment();
|
||||
|
||||
|
|
|
@ -439,4 +439,13 @@ export const getWidthOfInput = (input) => {
|
|||
}
|
||||
|
||||
return `${width}px`;
|
||||
}
|
||||
};
|
||||
|
||||
export const sortByAlpha = (a, b) => {
|
||||
const labelA = a.label.toLowerCase();
|
||||
const labelB = b.label.toLowerCase();
|
||||
|
||||
if (labelA < labelB) return -1;
|
||||
if (labelA > labelB) return 1;
|
||||
return 0;
|
||||
};
|
|
@ -1,3 +1,5 @@
|
|||
import { sortByAlpha } from './../lib/utils.js';
|
||||
|
||||
const choices = (state = [], action) => {
|
||||
switch (action.type) {
|
||||
case 'ADD_CHOICE':
|
||||
|
@ -10,7 +12,7 @@ const choices = (state = [], action) => {
|
|||
selected: false,
|
||||
active: true,
|
||||
score: 9999,
|
||||
}];
|
||||
}].sort(sortByAlpha);
|
||||
|
||||
case 'ADD_ITEM':
|
||||
// When an item is added and it has an associated choice,
|
||||
|
@ -63,9 +65,8 @@ const choices = (state = [], action) => {
|
|||
case 'ACTIVATE_CHOICES':
|
||||
return state.map((choice) => {
|
||||
choice.active = action.active;
|
||||
|
||||
return choice;
|
||||
});
|
||||
}).sort(sortByAlpha);
|
||||
|
||||
|
||||
default:
|
||||
|
|
12
index.html
12
index.html
|
@ -42,14 +42,14 @@
|
|||
</select>
|
||||
|
||||
<label for="choices-9">With pre-selected option</label>
|
||||
<select id="choices-9" name="choices-9" data-choice placeholder="Choose an option" multiple>
|
||||
<select id="choices-9" name="choices-9" placeholder="Choose an option" multiple>
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2" selected>Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-10">Option groups</label>
|
||||
<select id="choices-10" name="choices-10" data-choice placeholder="This is a placeholder" multiple>
|
||||
<select id="choices-10" name="choices-10" placeholder="This is a placeholder" multiple>
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
|
@ -86,17 +86,17 @@
|
|||
|
||||
<h2>Single select input</h2>
|
||||
<label for="choices-11">Default</label>
|
||||
<select id="choices-11" name="choices-11" data-choice placeholder="This is a placeholder">
|
||||
<select id="choices-11" name="choices-11" placeholder="This is a placeholder">
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-12">Options from remote source</label>
|
||||
<select name="choices-12" id="choices-12" data-choice placeholder="Pick an Arctic Monkeys record"></select>
|
||||
<select name="choices-12" id="choices-12" placeholder="Pick an Arctic Monkeys record"></select>
|
||||
|
||||
<label for="choices-13">Option groups</label>
|
||||
<select id="choices-13" name="choices-13" data-choice placeholder="This is a placeholder">
|
||||
<select id="choices-13" name="choices-13" placeholder="This is a placeholder">
|
||||
<optgroup label="UK">
|
||||
<option value="London">London</option>
|
||||
<option value="Manchester">Manchester</option>
|
||||
|
@ -180,7 +180,7 @@
|
|||
});
|
||||
})
|
||||
|
||||
const choicesMultiple = new Choices('[data-choice]', {
|
||||
const choicesMultiple = new Choices('select', {
|
||||
placeholderValue: 'This is a placeholder set in the config',
|
||||
removeButton: true
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue