Choices/assets/scripts/src/choices.js

867 lines
28 KiB
JavaScript
Raw Normal View History

'use strict';
2016-03-30 16:04:21 +02:00
import { createStore } from 'redux';
import rootReducer from './reducers/index.js';
import { addItem, removeItem, selectItem, addOption, selectOption } from './actions/index';
2016-04-04 22:44:32 +02:00
import { hasClass, wrap, getSiblings, isType, strToEl, extend } from './lib/utils.js';
/**
* Choices
*
* To do:
2016-04-13 15:43:27 +02:00
* - Dispatch events
* - Remove item by clicking a target
* - Set input width based on the size of the contents
* - Map options to items
* - Single select input support
* - Populate options by function
*/
2016-03-18 13:26:38 +01:00
export class Choices {
constructor(element = '[data-choice]', options) {
const fakeEl = document.createElement("fakeel");
const userOptions = options || {};
// If there are multiple elements, create a new instance
// for each element besides the first one (as that already has an instance)
if(isType('String', element)) {
const elements = document.querySelectorAll(element);
if(elements.length > 1) {
for (let i = 1; i < elements.length; i++) {
let el = elements[i];
new Choices(el, options);
}
}
}
const defaultOptions = {
items: [],
addItems: true,
removeItems: true,
2016-03-21 19:53:26 +01:00
editItems: false,
maxItems: false,
delimiter: ',',
allowDuplicates: true,
regexFilter: false,
debug: false,
placeholder: false,
prependValue: false,
appendValue: false,
selectAll: true,
2016-04-10 23:54:56 +02:00
classNames: {
2016-04-11 15:13:50 +02:00
containerOuter: 'choices',
containerInner: 'choices__inner',
input: 'choices__input',
inputCloned: 'choices__input--cloned',
list: 'choices__list',
listItems: 'choices__list--items',
listDropdown: 'choices__list--dropdown',
item: 'choices__item',
itemSelectable: 'choices__item--selectable',
itemDisabled: 'choices__item--disabled',
itemOption: 'choices__item--option',
2016-04-11 15:13:50 +02:00
activeState: 'is-active',
disabledState: 'is-disabled',
hiddenState: 'is-hidden',
selectedState: 'is-selected'
2016-04-10 23:54:56 +02:00
},
2016-03-18 13:26:38 +01:00
callbackOnInit: function() {},
callbackOnRender: function() {},
2016-03-24 00:00:32 +01:00
callbackOnRemoveItem: function() {},
callbackOnAddItem: function() {}
};
2016-03-15 23:42:10 +01:00
2016-04-04 22:44:32 +02:00
// Initial instance state
this.initialised = false;
// Merge options with user options
2016-04-04 22:44:32 +02:00
this.options = extend(defaultOptions, userOptions || {});
// Create data store
this.store = createStore(rootReducer);
2016-03-30 16:04:21 +02:00
2016-04-04 22:44:32 +02:00
// Cutting the mustard
this.supports = 'querySelector' in document && 'addEventListener' in document && 'classList' in fakeEl;
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
this.passedElement = isType('String', element) ? document.querySelector(element) : element;
// Set preset items - this looks out of place
this.presetItems = [];
if(this.options.items.length) {
this.presetItems = this.options.items;
} else if(this.passedElement.value !== '') {
this.presetItems = this.passedElement.value.split(this.options.delimiter);
}
// Bind methods
2016-04-08 10:07:41 +02:00
this.init = this.init.bind(this);
this.render = this.render.bind(this);
this.destroy = this.destroy.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.onClick = this.onClick.bind(this);
2016-03-18 13:26:38 +01:00
2016-04-04 22:44:32 +02:00
// Let's have it large
2016-03-18 13:26:38 +01:00
this.init();
}
2016-03-16 10:03:59 +01:00
2016-04-04 22:44:32 +02:00
/* State tests */
2016-03-18 12:13:35 +01:00
2016-04-04 22:44:32 +02:00
/**
* Whether input is disabled
* @return {Boolean}
*/
isDisabled() {
2016-04-04 22:44:32 +02:00
return (this.input.disabled) ? true : false;
}
2016-03-15 23:42:10 +01:00
2016-04-04 22:44:32 +02:00
/**
* Whether there are no values
* @return {Boolean}
*/
isEmpty() {
return (this.store.getState().items.length === 0) ? true : false;
}
/* Event handling */
2016-04-04 22:44:32 +02:00
/**
* Handle keydown event
* @param {Object} e Event
* @return
*/
onKeyDown(e) {
const items = this.getItems();
const activeItems = this.getItemsFilteredByActive();
const ctrlDownKey = e.ctrlKey || e.metaKey;
const deleteKey = 8 || 46;
const enterKey = 13;
const aKey = 65;
// If we are typing in the input
if(e.target === this.input) {
2016-04-04 22:44:32 +02:00
// If CTRL + A or CMD + A have been pressed and there are items to select
if (ctrlDownKey && e.keyCode === aKey && this.list && this.list.children) {
const handleSelectAll = () => {
if(this.options.removeItems && !this.input.value && this.options.selectAll && this.input === document.activeElement) {
this.selectAll(this.list.children);
}
};
handleSelectAll();
}
// If enter key is pressed and the input has a value
if (e.keyCode === enterKey && e.target.value) {
const value = this.input.value;
const handleEnter = () => {
let canUpdate = true;
// If there is a max entry limit and we have reached that limit
// don't update
if (this.options.maxItems && this.options.maxItems <= this.list.children.length) {
canUpdate = false;
}
// If no duplicates are allowed, and the value already exists
// in the array, don't update
if (this.options.allowDuplicates === false && this.passedElement.value) {
2016-04-12 15:54:07 +02:00
canUpdate = !items.some((item) => {
2016-04-04 22:44:32 +02:00
return item.value === value;
});
}
// All is good, update
if (canUpdate && this.options.addItems) {
if(this.passedElement.type === 'text') {
let canAddItem = true;
// If a user has supplied a regular expression filter
if(this.options.regexFilter) {
// Determine whether we can update based on whether
// our regular expression passes
canAddItem = this.regexFilter(value);
}
// All is good, add
if(canAddItem) {
2016-04-04 15:43:22 +02:00
this.addItem(value);
this.clearInput(this.passedElement);
}
}
}
};
handleEnter();
}
2016-03-15 23:42:10 +01:00
}
// If backspace or delete key is pressed and the input has no value
if (e.keyCode === deleteKey && !e.target.value) {
2016-03-18 13:26:38 +01:00
const handleBackspaceKey = () => {
if(this.options.removeItems) {
const inputIsFocussed = this.input === document.activeElement;
const lastItem = activeItems[activeItems.length - 1];
const selectedItems = items.some((item) => {
return item.selected === true;
});
if(items && lastItem && !this.options.editItems && inputIsFocussed && this.options.removeItems) {
this.selectItem(lastItem);
}
// If editing the last item is allowed and there is a last item and
// there are not other selected items (minus the last item), we can edit
// the item value. Otherwise if we can remove items, remove all items
if(items && this.options.removeItems && this.options.editItems && lastItem && !selectedItems && inputIsFocussed) {
this.input.value = lastItem.value;
this.removeItem(lastItem);
} else {
2016-04-12 15:54:07 +02:00
this.removeAllItems(true);
}
2016-03-21 19:53:26 +01:00
}
};
e.preventDefault();
handleBackspaceKey();
2016-03-15 23:42:10 +01:00
}
}
2016-03-15 23:42:10 +01:00
2016-04-04 22:44:32 +02:00
/**
* Handle click event
* @param {Object} e Event
* @return
*/
onClick(e) {
if(this.dropdown) {
this.toggleDropdown();
}
2016-04-11 15:13:50 +02:00
// If click is affecting a child node of our element
if(this.containerOuter.contains(e.target)) {
if(this.input !== document.activeElement) {
this.input.focus();
}
2016-04-11 15:13:50 +02:00
if(e.target.hasAttribute('data-choice-item')) {
const items = this.getItems();
const target = e.target;
const handleClick = (target) => {
2016-04-11 15:13:50 +02:00
if(this.options.removeItems) {
const passedId = target.getAttribute('data-choice-id');
2016-04-11 15:13:50 +02:00
// We only want to select one item with a click
// so we deselect any items that aren't the target
items.forEach((item) => {
if(item.id === parseInt(passedId) && !item.selected) {
this.selectItem(item);
2016-04-11 15:13:50 +02:00
} else {
this.deselectItem(item);
2016-04-11 15:13:50 +02:00
}
});
2016-04-11 15:13:50 +02:00
}
}
2016-04-11 15:13:50 +02:00
handleClick(target);
2016-04-10 23:54:56 +02:00
} else if(e.target.hasAttribute('data-choice-selectable')) {
const options = this.getOptions();
const id = e.target.getAttribute('data-choice-id');
const option = options.find((option) => {
return option.id === parseInt(id);
});
if(!option.selected) {
this.selectOption(id, true);
2016-04-14 15:43:36 +02:00
this.addItem(option.value, option.id);
}
2016-04-11 15:13:50 +02:00
}
2016-04-12 15:31:07 +02:00
} else {
// Click is outside of our element so close dropdown and de-select items
this.deselectAll();
if(this.dropdown && this.dropdown.classList.contains(this.options.classNames.activeState)) {
this.toggleDropdown();
}
2016-04-09 12:29:56 +02:00
}
2016-04-11 15:13:50 +02:00
2016-04-09 12:29:56 +02:00
}
/* Methods */
2016-03-15 23:42:10 +01:00
2016-04-04 22:44:32 +02:00
/**
* Set value of input to blank
* @return
*/
clearInput() {
if (this.input.value) this.input.value = '';
}
2016-03-15 23:42:10 +01:00
2016-04-04 22:44:32 +02:00
/**
* Tests value against a regular expression
* @param {string} value Value to test
* @return {Boolean} Whether test passed/failed
*/
regexFilter(value) {
const expression = new RegExp(this.options.regexFilter, 'i');
const passesTest = expression.test(value);
return passesTest;
}
/**
* Get Element based on a given value
* @param {String} value Value to search for
* @return {Element} First Element with given value
*/
getItemById(id) {
if(!id) {
console.error('getItemById: An id must be a number');
return;
}
const items = this.getItems();
const itemObject = items.find((item) => {
return item.id === parseInt(id);
});
const item = this.list.querySelector(`[data-choice-id='${ itemObject.id }']`);
return item;
}
2016-04-04 22:44:32 +02:00
/**
* Select item (a selected item can be deleted)
* @param {Element} item Element to select
* @return
*/
selectItem(item) {
if(!item) return;
const id = item.id;
2016-04-12 15:31:07 +02:00
this.store.dispatch(selectItem(id, true));
2016-03-24 00:00:32 +01:00
}
2016-04-04 22:44:32 +02:00
/**
* Deselect item
* @param {Element} item Element to de-select
* @return
*/
deselectItem(item) {
if(!item) return;
const id = item.id;
2016-04-12 15:31:07 +02:00
this.store.dispatch(selectItem(id, false));
}
2016-03-24 00:00:32 +01:00
2016-04-04 22:44:32 +02:00
/**
* Select items within array
* @param {Array} items Array of items to select
* @return
*/
selectAll() {
const items = this.getItems();
items.forEach((item) => {
this.selectItem(item);
});
}
deselectAll() {
const items = this.getItems();
items.forEach((item) => {
this.deselectItem(item);
});
}
2016-04-14 15:43:36 +02:00
selectOption(id, value = true) {
if(!id) return;
this.store.dispatch(selectOption(id, value));
2016-03-24 00:00:32 +01:00
}
2016-04-04 22:44:32 +02:00
/**
* Add item to store with correct value
* @param {String} value Value to add to store
*/
2016-04-14 15:43:36 +02:00
addItem(value, optionId = -1, callback = this.options.callbackOnAddItem) {
2016-03-18 13:26:38 +01:00
if (this.options.debug) console.debug('Add item');
let passedValue = value;
// 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();
}
2016-04-04 15:43:22 +02:00
// Generate unique id
let id = this.store.getState().items.length + 1;
2016-04-11 15:13:50 +02:00
// Close dropdown
if(this.dropdown && this.dropdown.classList.contains('is-active')) {
this.toggleDropdown();
}
// Run callback if it is a function
if(callback){
if(isType('Function', callback)) {
callback(id, value);
2016-03-24 00:00:32 +01:00
} else {
console.error('callbackOnAddItem: Callback is not a function');
2016-03-24 00:00:32 +01:00
}
}
2016-04-14 15:43:36 +02:00
this.store.dispatch(addItem(passedValue, id, optionId));
}
2016-03-15 23:42:10 +01:00
2016-04-04 22:44:32 +02:00
/**
* Remove item from store
* @param
*/
removeItem(item, callback = this.options.callbackOnRemoveItem) {
if(!item) {
2016-04-08 10:07:41 +02:00
console.error('removeItem: No item or value was passed to be removed');
2016-03-24 00:00:32 +01:00
return;
}
let id = item.id;
let value = item.value;
2016-04-14 15:43:36 +02:00
let optionId = item.optionId;
2016-04-08 10:07:41 +02:00
// Run callback
if(callback){
if(isType('Function', callback)) {
callback(value);
} else {
console.error('callbackOnRemoveItem: Callback is not a function');
2016-04-08 10:07:41 +02:00
}
}
2016-04-14 15:43:36 +02:00
this.store.dispatch(removeItem(id, optionId));
}
2016-04-04 22:44:32 +02:00
/**
* Remove all items from array
2016-04-12 15:54:07 +02:00
* @param {Boolean} selectedOnly Optionally remove only selected items
2016-04-04 22:44:32 +02:00
* @return
*/
2016-04-12 15:54:07 +02:00
removeAllItems(selectedOnly = false) {
let items = this.getItems();
2016-03-21 19:53:26 +01:00
2016-04-12 15:54:07 +02:00
items.forEach((item) => {
if(selectedOnly) {
if(item.selected && item.active){
this.removeItem(item);
2016-04-12 15:54:07 +02:00
}
} else {
if(item.active) {
this.removeItem(item);
2016-04-12 15:54:07 +02:00
}
2016-03-21 19:53:26 +01:00
}
2016-04-12 15:54:07 +02:00
});
2016-03-21 19:53:26 +01:00
}
2016-04-09 12:29:56 +02:00
toggleDropdown() {
if(!this.dropdown) {
console.error('No dropdown set');
return;
}
const isActive = this.dropdown.classList.contains('is-active');
this.dropdown.classList[isActive ? 'remove' : 'add']('is-active');
}
2016-04-14 15:43:36 +02:00
addOptionToDropdown(option) {
2016-04-12 15:31:07 +02:00
// Generate unique id
2016-04-14 15:43:36 +02:00
const state = this.store.getState();
const id = state.options.length + 1;
const value = option.value;
const isSelected = option.selected;
2016-04-12 15:31:07 +02:00
this.store.dispatch(addOption(value, id));
2016-04-14 15:43:36 +02:00
if(isSelected) {
this.selectOption(id);
this.addItem(option.value, id);
}
2016-04-09 12:29:56 +02:00
}
/* Getters */
/**
* Get items in state
* @return {Array} Array of item objects
*/
getItems() {
const state = this.store.getState();
return state.items;
}
/**
* Get items in state if they are active
* @return {Array} Array of item objects
*/
getItemsFilteredByActive() {
const items = this.getItems();
const valueArray = items.filter((item) => {
return item.active === true;
}, []);
return valueArray;
}
/**
* Get items in state reduced to just their values
* @return {Array} Array of items
*/
getItemsReducedToValues() {
const items = this.getItems();
const valueArray = items.reduce((prev, current) => {
prev.push(current.value);
return prev;
}, []);
return valueArray;
}
/**
* Get options in state
* @return {Array} Array of item options
*/
getOptions() {
const state = this.store.getState();
return state.options;
}
2016-04-04 22:44:32 +02:00
/* Rendering */
2016-03-21 19:53:26 +01:00
2016-04-04 22:44:32 +02:00
/**
* Create DOM structure around passed text element
* @return
*/
generateTextInput() {
/*
Template:
<div class="choices choices--active">
<div class="choices__inner">
<input id="1" type="text" data-choice="" class="choices__input choices__input--hidden" tabindex="-1" style="display:none;" aria-hidden="true">
<ul class="choices__list choices__list--items"></ul>
<input type="text" class="choices__input choices__input--cloned">
</div>
</div>
*/
2016-04-11 15:13:50 +02:00
let containerOuter = strToEl(`<div class="${ this.options.classNames.containerOuter }"></div>`);
let containerInner = strToEl(`<div class="${ this.options.classNames.containerInner }"></div>`);
// Hide passed input
2016-04-11 15:13:50 +02:00
this.passedElement.classList.add(this.options.classNames.input, this.options.classNames.hiddenState);
this.passedElement.tabIndex = '-1';
this.passedElement.setAttribute('style', 'display:none;');
this.passedElement.setAttribute('aria-hidden', 'true');
// Wrap input in container preserving DOM ordering
wrap(this.passedElement, containerInner);
// Wrapper inner container with outer container
wrap(containerInner, containerOuter);
2016-04-11 15:13:50 +02:00
let list = strToEl(`<ul class="${ this.options.classNames.list } ${ this.options.classNames.listItems }"></ul>`);
let input = strToEl(`<input type="text" class="${ this.options.classNames.input } ${ this.options.classNames.inputCloned }">`);
if (this.passedElement.placeholder) {
input.placeholder = this.passedElement.placeholder;
}
if(!this.options.addItems) {
input.disabled = true;
2016-04-11 15:13:50 +02:00
containerOuter.classList.add(this.options.classNames.disabledState);
}
containerOuter.appendChild(containerInner);
containerInner.appendChild(list);
containerInner.appendChild(input);
this.containerOuter = containerOuter;
this.containerInner = containerInner;
this.input = input;
this.list = list;
// Add any preset values seperated by delimiter
this.presetItems.forEach((value) => {
this.addItem(value);
});
// Subscribe to store
this.store.subscribe(this.render);
// Render any items
this.render();
// Trigger event listeners
this.addEventListeners();
}
/**
* Create DOM structure around passed select element
* @return
*/
generateMultipleSelectInput() {
const containerOuter = strToEl(`<div class="${ this.options.classNames.containerOuter }"></div>`);
const containerInner = strToEl(`<div class="${ this.options.classNames.containerInner }"></div>`);
// Hide passed input
2016-04-11 15:13:50 +02:00
this.passedElement.classList.add(this.options.classNames.input, this.options.classNames.hiddenState);
this.passedElement.tabIndex = '-1';
this.passedElement.setAttribute('style', 'display:none;');
this.passedElement.setAttribute('aria-hidden', 'true');
2016-03-16 21:24:11 +01:00
// Wrap input in container preserving DOM ordering
wrap(this.passedElement, containerInner);
2016-03-18 13:26:38 +01:00
// Wrapper inner container with outer container
wrap(containerInner, containerOuter);
const list = strToEl(`<ul class="${ this.options.classNames.list } ${ this.options.classNames.listItems }"></ul>`);
const input = strToEl(`<input type="text" class="${ this.options.classNames.input } ${ this.options.classNames.inputCloned }">`);
const dropdown = strToEl(`<div class="${ this.options.classNames.list } ${ this.options.classNames.listDropdown }"></div>`);
2016-03-18 13:26:38 +01:00
if (input.placeholder) {
input.placeholder = this.passedElement.placeholder;
}
2016-03-18 13:26:38 +01:00
if(!this.options.addItems) {
input.disabled = true;
}
2016-04-04 23:52:49 +02:00
containerOuter.appendChild(containerInner);
containerOuter.appendChild(dropdown);
containerInner.appendChild(list);
containerInner.appendChild(input);
2016-04-04 23:52:49 +02:00
this.containerOuter = containerOuter;
this.containerInner = containerInner;
this.input = input;
this.list = list;
this.dropdown = dropdown;
const passedOptions = Array.prototype.slice.call(this.passedElement.options);
passedOptions.forEach((option) => {
2016-04-14 15:43:36 +02:00
this.addOptionToDropdown(option);
});
2016-04-09 12:29:56 +02:00
2016-04-04 22:44:32 +02:00
// Subscribe to store
this.store.subscribe(this.render);
// Render any items
this.render();
2016-04-04 23:52:49 +02:00
// Trigger event listeners
this.addEventListeners();
}
/**
* Trigger event listeners
*/
2016-04-04 23:52:49 +02:00
addEventListeners() {
document.addEventListener('keydown', this.onKeyDown);
2016-04-11 15:13:50 +02:00
document.addEventListener('click', this.onClick);
2016-04-04 23:52:49 +02:00
}
/**
* Destroy event listeners
*/
2016-04-04 23:52:49 +02:00
removeEventListeners() {
document.removeEventListener('keydown', this.onKeyDown);
2016-04-11 15:13:50 +02:00
document.removeEventListener('click', this.onClick);
}
2016-04-04 22:44:32 +02:00
/**
* Render DOM with values
* @return
*/
render(callback = this.options.callbackOnRender) {
const classNames = this.options.classNames;
const items = this.getItems();
const options = this.getOptions();
2016-04-04 15:43:22 +02:00
2016-04-12 15:31:07 +02:00
// OPTIONS
if(this.dropdown) {
// Clear options
this.dropdown.innerHTML = '';
2016-04-13 15:42:23 +02:00
// Create a fragment to store our list items (so we don't have to update the DOM for each item)
const optionListFragment = document.createDocumentFragment();
2016-04-12 15:31:07 +02:00
// Add each option to dropdown
if(options) {
options.forEach((option) => {
const dropdownItem = strToEl(`<li class="${ classNames.item } ${ classNames.itemOption } ${ option.selected ? classNames.selectedState + ' ' + classNames.itemDisabled : classNames.itemSelectable }" data-choice-selectable data-choice-id="${ option.id }" data-choice-value="${ option.value }">${ option.value }</li>`);
optionListFragment.appendChild(dropdownItem);
});
} else {
const dropdownItem = strToEl(`<li class="${ classNames.item }">No options to select</li>`);
optionListFragment.appendChild(dropdownItem);
}
this.dropdown.appendChild(optionListFragment);
2016-04-12 15:31:07 +02:00
}
// ITEMS
2016-04-04 22:44:32 +02:00
// Simplify store data to just values
const itemsFiltered = this.getItemsReducedToValues();
2016-04-04 22:44:32 +02:00
// Assign hidden input array of values
this.passedElement.value = itemsFiltered.join(this.options.delimiter);
2016-04-04 22:44:32 +02:00
// Clear list
this.list.innerHTML = '';
// Create a fragment to store our list items (so we don't have to update the DOM for each item)
const itemListFragment = document.createDocumentFragment();
2016-04-04 22:44:32 +02:00
// Add each list item to list
items.forEach((item) => {
2016-04-04 15:43:22 +02:00
if(item.active) {
// Create new list element
const listItem = strToEl(`<li class="${ classNames.item } ${ this.options.removeItems ? classNames.itemSelectable : '' } ${ item.selected ? classNames.selectedState : '' }" data-choice-item data-choice-id="${ item.id }" data-choice-selected="${ item.selected }">${ item.value }</li>`);
2016-04-04 15:43:22 +02:00
// Append it to list
itemListFragment.appendChild(listItem);
2016-04-04 15:43:22 +02:00
}
});
this.list.appendChild(itemListFragment);
// Run callback if it is a function
if(callback){
if(isType('Function', callback)) {
2016-04-12 15:31:07 +02:00
callback(items, options);
} else {
console.error('callbackOnRender: Callback is not a function');
}
}
2016-04-04 15:43:22 +02:00
}
2016-04-04 22:44:32 +02:00
/**
* Determine how an input should be rendered
* @return {Element} Input to test
*/
renderInput(input) {
2016-03-18 13:26:38 +01:00
if (this.options.debug) console.debug('Render');
2016-04-04 22:44:32 +02:00
switch (input.type) {
case "text":
this.generateTextInput();
break;
case "select-one":
// this.generateSelectInput();
break;
case "select-multiple":
this.generateMultipleSelectInput();
break;
default:
this.generateMultipleSelectInput();
break;
}
}
2016-04-04 22:44:32 +02:00
/**
* Initialise Choices
* @return
*/
init(callback = this.options.callbackOnInit) {
2016-04-04 22:44:32 +02:00
if (!this.supports) console.error('init: Your browser doesn\'nt support shit');
this.initialised = true;
this.renderInput(this.passedElement);
// Run callback if it is a function
if(callback){
if(isType('Function', callback)) {
callback();
} else {
console.error('callbackOnInit: Callback is not a function');
}
}
2016-04-04 22:44:32 +02:00
}
/**
* Destroy Choices and nullify values
* @return
*/
destroy() {
this.options = null;
this.passedElement = null;
this.initialised = null;
}
};
2016-03-15 23:42:10 +01:00
document.addEventListener('DOMContentLoaded', () => {
const firstElement = document.getElementById('choices-1');
const choices1 = new Choices(firstElement, {
2016-04-04 22:44:32 +02:00
delimiter: ' ',
2016-04-04 15:43:22 +02:00
editItems: true,
maxItems: 5,
2016-04-14 15:43:36 +02:00
// callbackOnRemoveItem: function(value) {
// console.log(value);
// },
// callbackOnAddItem: function(id, value) {
// console.log(id, value);
// },
// callbackOnRender: function(items) {
// console.log(items);
// }
2016-04-04 15:43:22 +02:00
});
const choices2 = new Choices('#choices-2', {
2016-04-04 15:43:22 +02:00
allowDuplicates: false,
editItems: true,
});
const choices3 = new Choices('#choices-3', {
2016-04-04 15:43:22 +02:00
allowDuplicates: false,
editItems: true,
regexFilter: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
2016-04-04 15:43:22 +02:00
});
const choices4 = new Choices('#choices-4', {
addItems: false,
removeItems: false,
});
2016-03-15 23:42:10 +01:00
const choices5 = new Choices('#choices-5', {
2016-04-04 15:43:22 +02:00
prependValue: 'item-',
appendValue: `-${Date.now()}`,
2016-04-04 15:43:22 +02:00
});
2016-04-12 15:31:07 +02:00
choices5.removeAllItems();
const choices6 = new Choices('#choices-6', {
items: ['josh@joshuajohnson.co.uk', 'joe@bloggs.co.uk'],
});
2016-04-08 10:07:41 +02:00
const choices7 = new Choices('#choices-7', {
2016-04-14 15:43:36 +02:00
// callbackOnRender: function(items, options) {
// console.log(items);
// },
});
const choicesMultiple = new Choices('[data-choice]', {
2016-04-12 15:31:07 +02:00
callbackOnRender: function(items, options) {
console.log(items);
2016-04-14 15:43:36 +02:00
},
2016-04-12 15:31:07 +02:00
});
2016-04-14 15:43:36 +02:00
// choices6.addItem('josh2@joshuajohnson.co.uk', () => { console.log('Custom add item callback')});
// choices6.removeItem('josh@joshuajohnson.co.uk');
// console.log(choices6.getItemById(1));
});