mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-21 15:06:45 +02:00
Documentation + minor fixes
This commit is contained in:
parent
c9671c4625
commit
6a9f2cb354
204
README.md
204
README.md
|
@ -7,18 +7,18 @@ Coming soon.
|
|||
```html
|
||||
<script src="/assets/js/dist/choices.min.js"></script>
|
||||
<script>
|
||||
// Pass multiple elements:
|
||||
var choices = new Choices(elements);
|
||||
// Pass multiple elements:
|
||||
var choices = new Choices(elements);
|
||||
|
||||
// Pass single element:
|
||||
var choice = new Choices(element);
|
||||
// Pass single element:
|
||||
var choice = new Choices(element);
|
||||
|
||||
// Pass reference
|
||||
var choice = new Choices('[data-choice']);
|
||||
var choice = new Choices('.js-choice');
|
||||
// Pass reference
|
||||
var choice = new Choices('[data-choice']);
|
||||
var choice = new Choices('.js-choice');
|
||||
|
||||
// Passing options
|
||||
var choices = new Choices(elements, {
|
||||
// Passing options
|
||||
var choices = new Choices(elements, {
|
||||
items: [],
|
||||
addItems: true,
|
||||
removeItems: true,
|
||||
|
@ -45,126 +45,206 @@ To install via NPM, run `npm install --save-dev choices.js`
|
|||
|
||||
## Options
|
||||
#### items
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Array` <strong>Default:</strong> `[]`
|
||||
|
||||
Usage:
|
||||
Usage: Add pre-selected items to input.
|
||||
|
||||
Pass an array of strings:
|
||||
|
||||
`['value 1', 'value 2', 'value 3']`
|
||||
|
||||
Pass an array of objects:
|
||||
|
||||
```
|
||||
[{
|
||||
value: 'Value 1',
|
||||
label: 'Label 1',
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
value: 'Value 2',
|
||||
label: 'Label 2',
|
||||
id: 2
|
||||
}]
|
||||
```
|
||||
|
||||
#### addItems
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`true`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a user can add items.
|
||||
|
||||
#### removeItems
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`true`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a user can remove items (only affects text and multiple select input types).
|
||||
|
||||
#### removeButton
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`false`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a button should show that, when clicked, will remove an item (only affects text and multiple select input types).
|
||||
|
||||
#### editItems
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`false`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a user can edit selected items (only affects text input types).
|
||||
|
||||
#### maxItems
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`null`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Optionally set an item limit.
|
||||
|
||||
#### delimiter
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `String` <strong>Default:</strong>`,`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> What divides each value (only affects text input types).
|
||||
|
||||
#### allowDuplicates
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`true`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a user can input a duplicate item (only affects text input types).
|
||||
|
||||
#### allowPaste
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`true`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a user can paste into the input.
|
||||
|
||||
#### allowSearch
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`true`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a user can filter options by searching (only affects select input types).
|
||||
|
||||
#### regexFilter
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Regex` <strong>Default:</strong>`null`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> A filter that will need to pass for a user to successfully add an item (only affects text input types).
|
||||
|
||||
#### placeholder
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`true`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether the input should show a placeholder. Used in conjunction with `placeholderValue`. If `placeholder` is set to true and no value is passed to `placeholderValue`, the passed input's placeholder attribute will be used as the placeholder value.
|
||||
|
||||
#### placeholderValue
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `String` <strong>Default:</strong>`null`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> The value of the inputs placeholder.
|
||||
|
||||
#### prependValue
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `String` <strong>Default:</strong>`null`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Prepend a value to each item added to input (only affects text input types).
|
||||
|
||||
#### appendValue
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `String` <strong>Default:</strong>`null`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Append a value to each item added to input (only affects text input types).
|
||||
|
||||
#### selectAll
|
||||
Type: `` Default: ``
|
||||
#### highlightAll
|
||||
<strong>Type:</strong> `Boolean` <strong>Default:</strong>`true`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Whether a user can highlight items.
|
||||
|
||||
#### loadingText
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `String` <strong>Default:</strong>`Loading...`
|
||||
|
||||
Usage:
|
||||
|
||||
#### templates
|
||||
Type: `` Default: ``
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> The loading text that is shown when options are populated via an AJAX callback.
|
||||
|
||||
#### classNames
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Object` <strong>Default:</strong>
|
||||
|
||||
Usage:
|
||||
```
|
||||
classNames: {
|
||||
containerOuter: 'choices',
|
||||
containerInner: 'choices__inner',
|
||||
input: 'choices__input',
|
||||
inputCloned: 'choices__input--cloned',
|
||||
list: 'choices__list',
|
||||
listItems: 'choices__list--multiple',
|
||||
listSingle: 'choices__list--single',
|
||||
listDropdown: 'choices__list--dropdown',
|
||||
item: 'choices__item',
|
||||
itemSelectable: 'choices__item--selectable',
|
||||
itemDisabled: 'choices__item--disabled',
|
||||
itemOption: 'choices__item--option',
|
||||
group: 'choices__group',
|
||||
groupHeading : 'choices__heading',
|
||||
button: 'choices__button',
|
||||
activeState: 'is-active',
|
||||
focusState: 'is-focused',
|
||||
openState: 'is-open',
|
||||
disabledState: 'is-disabled',
|
||||
highlightedState: 'is-highlighted',
|
||||
hiddenState: 'is-hidden',
|
||||
flippedState: 'is-flipped',
|
||||
selectedState: 'is-selected',
|
||||
}
|
||||
```
|
||||
|
||||
<strong>Usage:</strong> Classes added to HTML generated by Choices.
|
||||
|
||||
#### callbackOnInit
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Function` <strong>Default:</strong>`() => {}`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Function to run once Choices initialises.
|
||||
|
||||
#### callbackOnAddItem
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Function` <strong>Default:</strong>`(id, value, passedInput) => {}`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Function to run each time an item is added.
|
||||
|
||||
#### callbackOnRemoveItem
|
||||
Type: `` Default: ``
|
||||
<strong>Type:</strong> `Function` <strong>Default:</strong>`(id, value, passedInput) => {}`
|
||||
|
||||
Usage:
|
||||
<strong>Usage:</strong> Function to run each time an item is removed.
|
||||
|
||||
|
||||
## Methods
|
||||
#### method();
|
||||
Usage:
|
||||
#### `highlightAll();`
|
||||
<strong>Usage:</strong> Highlight each chosen item (selected items can be removed).
|
||||
|
||||
#### `unhighlightAll();`
|
||||
<strong>Usage:</strong> Un-highlight each chosen item.
|
||||
|
||||
#### `removeItemsByValue(value);`
|
||||
<strong>Usage:</strong> Remove each item by a given value.
|
||||
|
||||
#### `removeActiveItems(excludedId);`
|
||||
<strong>Usage:</strong> Remove each selectable item.
|
||||
|
||||
#### `removeSelectedItems();`
|
||||
<strong>Usage:</strong> Remove each item the user has selected.
|
||||
|
||||
#### `showDropdown();`
|
||||
<strong>Usage:</strong> Show option list dropdown
|
||||
|
||||
#### `hideDropdown();`
|
||||
<strong>Usage:</strong> Hide option list dropdown
|
||||
|
||||
#### `toggleDropdown();`
|
||||
<strong>Usage:</strong> Toggle dropdown between showing/hidden.
|
||||
|
||||
#### `setValue(args);`
|
||||
<strong>Usage:</strong> Set value of input based on an array of objects or strings.
|
||||
|
||||
#### `clearValue();`
|
||||
<strong>Usage:</strong> Clear value of input.
|
||||
|
||||
#### `clearInput();`
|
||||
<strong>Usage:</strong> Clear input.
|
||||
|
||||
#### `disable();`
|
||||
<strong>Usage:</strong> Disable input from selecting further options.
|
||||
|
||||
#### `ajax(fn);`
|
||||
<strong>Usage:</strong> Populate options via a callback.
|
||||
|
||||
|
||||
## Browser compatibility
|
||||
Coming soon
|
||||
ES5 browsers and above (http://caniuse.com/#feat=es5).
|
||||
|
||||
## Development
|
||||
To setup a local environment: clone this repo, navigate into it's directory in a terminal window and run the following command:
|
||||
* ```npm install```
|
||||
|
||||
```npm install```
|
||||
|
||||
### NPM tasks
|
||||
* ```npm start```
|
||||
|
@ -172,7 +252,7 @@ To setup a local environment: clone this repo, navigate into it's directory in a
|
|||
* ```npm run css:watch```
|
||||
|
||||
## Contributions
|
||||
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using Gulp...bla bla bla
|
||||
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using npm scripts...bla bla bla
|
||||
|
||||
## License
|
||||
MIT License
|
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
|
@ -33,17 +33,17 @@ export class Choices {
|
|||
removeItems: true,
|
||||
removeButton: false,
|
||||
editItems: false,
|
||||
maxItems: false,
|
||||
maxItems: null,
|
||||
delimiter: ',',
|
||||
allowDuplicates: true,
|
||||
allowPaste: true,
|
||||
allowSearch: true,
|
||||
_regexFilter: false,
|
||||
regexFilter: null,
|
||||
placeholder: true,
|
||||
placeholderValue: '',
|
||||
prependValue: false,
|
||||
appendValue: false,
|
||||
selectAll: true,
|
||||
placeholderValue: null,
|
||||
prependValue: null,
|
||||
appendValue: null,
|
||||
highlightAll: true,
|
||||
loadingText: 'Loading...',
|
||||
templates: {},
|
||||
classNames: {
|
||||
|
@ -80,7 +80,7 @@ export class Choices {
|
|||
this.options = extend(defaultOptions, userOptions);
|
||||
|
||||
// Create data store
|
||||
this.store = new Store(this._render);
|
||||
this.store = new Store(this.render);
|
||||
|
||||
// State tracking
|
||||
this.initialised = false;
|
||||
|
@ -103,7 +103,7 @@ export class Choices {
|
|||
|
||||
// Bind methods
|
||||
this.init = this.init.bind(this);
|
||||
this._render = this._render.bind(this);
|
||||
this.render = this.render.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this.disable = this.disable.bind(this);
|
||||
|
||||
|
@ -148,10 +148,10 @@ export class Choices {
|
|||
// Generate input markup
|
||||
this._createInput();
|
||||
|
||||
this.store.subscribe(this._render);
|
||||
this.store.subscribe(this.render);
|
||||
|
||||
// Render any items
|
||||
this._render();
|
||||
this.render();
|
||||
|
||||
// Trigger event listeners
|
||||
this._addEventListeners();
|
||||
|
@ -217,11 +217,11 @@ export class Choices {
|
|||
}
|
||||
|
||||
/**
|
||||
* Select items within store
|
||||
* Highlight items within store
|
||||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
selectAll() {
|
||||
highlightAll() {
|
||||
const items = this.store.getItems();
|
||||
items.forEach((item) => {
|
||||
this.selectItem(item);
|
||||
|
@ -244,76 +244,6 @@ export class Choices {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item to store with correct value
|
||||
* @param {String} value Value to add to store
|
||||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
addItem(value, label, optionId = -1, callback = this.options.callbackOnAddItem) {
|
||||
const items = this.store.getItems();
|
||||
let passedValue = value.trim();
|
||||
let passedLabel = label || passedValue;
|
||||
let passedOptionId = optionId || -1;
|
||||
|
||||
// If a prepended value has been passed, prepend it
|
||||
if(this.options.prependValue) {
|
||||
passedValue = this.options.prependValue + passedValue.toString();
|
||||
}
|
||||
|
||||
// If an appended value has been passed, append it
|
||||
if(this.options.appendValue) {
|
||||
passedValue = passedValue + this.options.appendValue.toString();
|
||||
}
|
||||
|
||||
// Generate unique id
|
||||
const id = items ? items.length + 1 : 1;
|
||||
|
||||
this.store.dispatch(addItem(passedValue, passedLabel, id, passedOptionId));
|
||||
|
||||
if(this.passedElement.type === 'select-one') {
|
||||
this.removeActiveItems(id);
|
||||
}
|
||||
|
||||
// Run callback if it is a function
|
||||
if(callback){
|
||||
if(isType('Function', callback)) {
|
||||
callback(id, passedValue, this.passedElement);
|
||||
} else {
|
||||
console.error('callbackOnAddItem: Callback is not a function');
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item from store
|
||||
* @param
|
||||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
removeItem(item, callback = this.options.callbackOnRemoveItem) {
|
||||
if(!item || !isType('Object', item)) {
|
||||
console.error('removeItem: No item object was passed to be removed');
|
||||
return;
|
||||
}
|
||||
|
||||
const id = item.id;
|
||||
const value = item.value;
|
||||
const optionId = item.optionId;
|
||||
|
||||
this.store.dispatch(removeItem(id, optionId));
|
||||
|
||||
// Run callback
|
||||
if(callback){
|
||||
if(!isType('Function', callback)) console.error('callbackOnRemoveItem: Callback is not a function'); return;
|
||||
callback(id, value, this.passedElement);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the store by its value
|
||||
* @param {String} value Value to search for
|
||||
|
@ -327,7 +257,7 @@ export class Choices {
|
|||
|
||||
items.forEach((item) => {
|
||||
if(item.value === value) {
|
||||
this.removeItem(item);
|
||||
this._removeItem(item);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -337,7 +267,7 @@ export class Choices {
|
|||
/**
|
||||
* Remove all items from store array
|
||||
* Note: removed items are soft deleted
|
||||
* @param {Boolean} selectedOnly Optionally remove only selected items
|
||||
* @param {Number} excludedId Optionally exclude item by ID
|
||||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
|
@ -346,7 +276,7 @@ export class Choices {
|
|||
|
||||
items.forEach((item) => {
|
||||
if(item.active && excludedId !== item.id) {
|
||||
this.removeItem(item);
|
||||
this._removeItem(item);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -364,7 +294,7 @@ export class Choices {
|
|||
|
||||
items.forEach((item) => {
|
||||
if(item.selected && item.active) {
|
||||
this.removeItem(item);
|
||||
this._removeItem(item);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -443,13 +373,13 @@ export class Choices {
|
|||
if(this.passedElement.type !== 'text') {
|
||||
this._addOption(true, false, item.value, item.label, -1);
|
||||
} else {
|
||||
this.addItem(item.value, item.label, item.id);
|
||||
this._addItem(item.value, item.label, item.id);
|
||||
}
|
||||
} else if(isType('String', item)) {
|
||||
if(this.passedElement.type !== 'text') {
|
||||
this._addOption(true, false, item, item, -1);
|
||||
} else {
|
||||
this.addItem(item);
|
||||
this._addItem(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -501,7 +431,7 @@ export class Choices {
|
|||
results.forEach((result, index) => {
|
||||
// Add each result to option dropdown
|
||||
if(index === 0) {
|
||||
this.addItem(result[value], result[label], index);
|
||||
this._addItem(result[value], result[label], index);
|
||||
}
|
||||
this._addOption(false, false, result[value], result[label]);
|
||||
});
|
||||
|
@ -553,7 +483,7 @@ export class Choices {
|
|||
let canAddItem = true;
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if(this.options._regexFilter) {
|
||||
if(this.options.regexFilter) {
|
||||
// Determine whether we can update based on whether
|
||||
// our regular expression passes
|
||||
canAddItem = this._regexFilter(value);
|
||||
|
@ -562,7 +492,7 @@ export class Choices {
|
|||
// All is good, add
|
||||
if(canAddItem) {
|
||||
this.toggleDropdown();
|
||||
this.addItem(value);
|
||||
this._addItem(value);
|
||||
this.clearInput(this.passedElement);
|
||||
}
|
||||
}
|
||||
|
@ -583,7 +513,7 @@ export class Choices {
|
|||
// we can edit the item value. Otherwise if we can remove items, remove all selected items
|
||||
if(this.options.editItems && !hasSelectedItems && lastItem) {
|
||||
this.input.value = lastItem.value;
|
||||
this.removeItem(lastItem);
|
||||
this._removeItem(lastItem);
|
||||
} else {
|
||||
if(!hasSelectedItems) { this.selectItem(lastItem); }
|
||||
this.removeSelectedItems();
|
||||
|
@ -628,8 +558,9 @@ export class Choices {
|
|||
// 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.options.selectAll && this.input === document.activeElement) {
|
||||
this.selectAll(this.itemList.children);
|
||||
if(this.options.removeItems && !this.input.value && this.options.highlightAll && this.input === document.activeElement) {
|
||||
// Highlight items
|
||||
this.highlightAll(this.itemList.children);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -648,7 +579,7 @@ export class Choices {
|
|||
const value = highlighted.getAttribute('data-value');
|
||||
const label = highlighted.innerHTML;
|
||||
const id = highlighted.getAttribute('data-id');
|
||||
this.addItem(value, label, id);
|
||||
this._addItem(value, label, id);
|
||||
this.clearInput(this.passedElement);
|
||||
|
||||
if(this.passedElement.type === 'select-one') {
|
||||
|
@ -738,7 +669,7 @@ export class Choices {
|
|||
dropdownItem = this._getTemplate('notice', `Add "${ this.input.value }"`);
|
||||
}
|
||||
|
||||
if((this.options._regexFilter && this._regexFilter(this.input.value)) || !this.options._regexFilter) {
|
||||
if((this.options.regexFilter && this._regexFilter(this.input.value)) || !this.options.regexFilter) {
|
||||
this.dropdown.innerHTML = dropdownItem.outerHTML;
|
||||
if(!this.dropdown.classList.contains(this.options.classNames.activeState)) {
|
||||
this.showDropdown();
|
||||
|
@ -835,7 +766,7 @@ export class Choices {
|
|||
if(this.options.removeItems && this.options.removeButton) {
|
||||
const itemId = e.target.parentNode.getAttribute('data-id');
|
||||
const itemToRemove = activeItems.find((item) => item.id === parseInt(itemId));
|
||||
this.removeItem(itemToRemove);
|
||||
this._removeItem(itemToRemove);
|
||||
}
|
||||
} else if(e.target.hasAttribute('data-item')) {
|
||||
// If we are clicking on an item
|
||||
|
@ -860,7 +791,7 @@ export class Choices {
|
|||
const option = options.find((option) => option.id === parseInt(id));
|
||||
|
||||
if(!option.selected && !option.disabled) {
|
||||
this.addItem(option.value, option.label, option.id);
|
||||
this._addItem(option.value, option.label, option.id);
|
||||
if(this.passedElement.type === 'select-one') {
|
||||
this.input.value = "";
|
||||
this.isSearching = false;
|
||||
|
@ -875,8 +806,8 @@ export class Choices {
|
|||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
const hasSelectedItems = activeItems.some((item) => item.selected === true);
|
||||
|
||||
// De-select any selected items
|
||||
if(hasSelectedItems) this.deselectAll();
|
||||
// De-select any highlighted items
|
||||
if(hasSelectedItems) this.unhighlightAll();
|
||||
|
||||
// Remove focus state
|
||||
this.containerOuter.classList.remove(this.options.classNames.focusState);
|
||||
|
@ -957,7 +888,7 @@ export class Choices {
|
|||
*/
|
||||
_regexFilter(value) {
|
||||
if(!value) return;
|
||||
const expression = new RegExp(this.options._regexFilter, 'i');
|
||||
const expression = new RegExp(this.options.regexFilter, 'i');
|
||||
return expression.test(value);
|
||||
}
|
||||
|
||||
|
@ -1058,6 +989,77 @@ export class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add item to store with correct value
|
||||
* @param {String} value Value to add to store
|
||||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
_addItem(value, label, optionId = -1, callback = this.options.callbackOnAddItem) {
|
||||
const items = this.store.getItems();
|
||||
let passedValue = value.trim();
|
||||
let passedLabel = label || passedValue;
|
||||
let passedOptionId = optionId || -1;
|
||||
|
||||
// If a prepended value has been passed, prepend it
|
||||
if(this.options.prependValue) {
|
||||
passedValue = this.options.prependValue + passedValue.toString();
|
||||
}
|
||||
|
||||
// If an appended value has been passed, append it
|
||||
if(this.options.appendValue) {
|
||||
passedValue = passedValue + this.options.appendValue.toString();
|
||||
}
|
||||
|
||||
// Generate unique id
|
||||
const id = items ? items.length + 1 : 1;
|
||||
|
||||
this.store.dispatch(addItem(passedValue, passedLabel, id, passedOptionId));
|
||||
|
||||
if(this.passedElement.type === 'select-one') {
|
||||
this.removeActiveItems(id);
|
||||
}
|
||||
|
||||
// Run callback if it is a function
|
||||
if(callback){
|
||||
if(isType('Function', callback)) {
|
||||
callback(id, passedValue, this.passedElement);
|
||||
} else {
|
||||
console.error('callbackOnAddItem: Callback is not a function');
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item from store
|
||||
* @param
|
||||
* @return {Object} Class instance
|
||||
* @public
|
||||
*/
|
||||
_removeItem(item, callback = this.options.callbackOnRemoveItem) {
|
||||
if(!item || !isType('Object', item)) {
|
||||
console.error('removeItem: No item object was passed to be removed');
|
||||
return;
|
||||
}
|
||||
|
||||
const id = item.id;
|
||||
const value = item.value;
|
||||
const optionId = item.optionId;
|
||||
|
||||
this.store.dispatch(removeItem(id, optionId));
|
||||
|
||||
// Run callback
|
||||
if(callback){
|
||||
if(!isType('Function', callback)) console.error('callbackOnRemoveItem: Callback is not a function'); return;
|
||||
callback(id, value, this.passedElement);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add option to dropdown
|
||||
* @param {Object} option Option to add
|
||||
|
@ -1077,7 +1079,7 @@ export class Choices {
|
|||
this.store.dispatch(addOption(value, label, id, groupId, isDisabled));
|
||||
|
||||
if(isSelected && !isDisabled) {
|
||||
this.addItem(value, label, id);
|
||||
this._addItem(value, label, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1163,7 +1165,7 @@ export class Choices {
|
|||
`);
|
||||
},
|
||||
item: (data) => {
|
||||
if(this.options.removeButton) {
|
||||
if(this.options.removeButton && 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 }
|
||||
|
@ -1263,9 +1265,9 @@ export class Choices {
|
|||
this.presetItems.forEach((item) => {
|
||||
if(isType('Object', item)) {
|
||||
if(!item.value) return;
|
||||
this.addItem(item.value, item.label, item.id);
|
||||
this._addItem(item.value, item.label, item.id);
|
||||
} else if(isType('String', item)) {
|
||||
this.addItem(item);
|
||||
this._addItem(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1279,7 +1281,7 @@ export class Choices {
|
|||
* @return {DocumentFragment} Populated options fragment
|
||||
* @private
|
||||
*/
|
||||
_renderGroups(groups, options, fragment) {
|
||||
renderGroups(groups, options, fragment) {
|
||||
const groupFragment = fragment || document.createDocumentFragment();
|
||||
|
||||
groups.forEach((group, i) => {
|
||||
|
@ -1297,7 +1299,7 @@ export class Choices {
|
|||
|
||||
groupFragment.appendChild(dropdownGroup);
|
||||
|
||||
this._renderOptions(groupOptions, groupFragment);
|
||||
this.renderOptions(groupOptions, groupFragment);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1311,7 +1313,7 @@ export class Choices {
|
|||
* @return {DocumentFragment} Populated options fragment
|
||||
* @private
|
||||
*/
|
||||
_renderOptions(options, fragment) {
|
||||
renderOptions(options, fragment) {
|
||||
// Create a fragment to store our list items (so we don't have to update the DOM for each item)
|
||||
const optsFragment = fragment || document.createDocumentFragment();
|
||||
|
||||
|
@ -1335,7 +1337,7 @@ export class Choices {
|
|||
* @return
|
||||
* @private
|
||||
*/
|
||||
_renderItems(items, fragment) {
|
||||
renderItems(items, fragment) {
|
||||
// Create fragment to add elements to
|
||||
const itemListFragment = fragment || document.createDocumentFragment();
|
||||
// Simplify store data to just values
|
||||
|
@ -1378,10 +1380,10 @@ export class Choices {
|
|||
* @return
|
||||
* @private
|
||||
*/
|
||||
_render() {
|
||||
render() {
|
||||
this.currentState = this.store.getState();
|
||||
|
||||
// Only _render if our state has actually changed
|
||||
// Only render if our state has actually changed
|
||||
if(this.currentState !== this.prevState) {
|
||||
|
||||
// Options
|
||||
|
@ -1398,9 +1400,9 @@ export class Choices {
|
|||
|
||||
// If we have grouped options
|
||||
if(activeGroups.length >= 1 && this.isSearching !== true) {
|
||||
optListFragment = this._renderGroups(activeGroups, activeOptions, optListFragment);
|
||||
optListFragment = this.renderGroups(activeGroups, activeOptions, optListFragment);
|
||||
} else if(activeOptions.length >= 1) {
|
||||
optListFragment = this._renderOptions(activeOptions, optListFragment);
|
||||
optListFragment = this.renderOptions(activeOptions, optListFragment);
|
||||
}
|
||||
|
||||
if(optListFragment.children.length) {
|
||||
|
@ -1421,7 +1423,7 @@ export class Choices {
|
|||
const activeItems = this.store.getItemsFilteredByActive();
|
||||
if(activeItems) {
|
||||
// Create a fragment to store our list items (so we don't have to update the DOM for each item)
|
||||
const itemListFragment = this._renderItems(activeItems);
|
||||
const itemListFragment = this.renderItems(activeItems);
|
||||
|
||||
// Clear list
|
||||
this.itemList.innerHTML = '';
|
||||
|
|
|
@ -182,6 +182,7 @@
|
|||
|
||||
const choicesMultiple = new Choices('[data-choice]', {
|
||||
placeholderValue: 'This is a placeholder set in the config',
|
||||
removeButton: true
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue