Merge updated master into bugfix

This commit is contained in:
Marshall Adams 2017-05-30 11:11:19 -07:00
commit e4df3a8cb7
9 changed files with 355 additions and 216 deletions

View file

@ -56,6 +56,7 @@ Or include Choices directly:
// Passing options (with default options) // Passing options (with default options)
const choices = new Choices(elements, { const choices = new Choices(elements, {
silent: false,
items: [], items: [],
choices: [], choices: [],
maxItemCount: -1, maxItemCount: -1,
@ -66,7 +67,7 @@ Or include Choices directly:
duplicateItems: true, duplicateItems: true,
delimiter: ',', delimiter: ',',
paste: true, paste: true,
search: true, searchEnabled: true,
searchChoices: true, searchChoices: true,
searchFloor: 1, searchFloor: 1,
searchFields: ['label', 'value'], searchFields: ['label', 'value'],
@ -133,6 +134,14 @@ Or include Choices directly:
## Configuration options ## Configuration options
### silent
**Type:** `Boolean` **Default:** `false`
**Input types affected:** `text`, `select-single`, `select-multiple`
**Usage:** Optionally suppress console errors and warnings.
### items ### items
**Type:** `Array` **Default:** `[]` **Type:** `Array` **Default:** `[]`
@ -148,14 +157,14 @@ Pass an array of objects:
``` ```
[{ [{
value: 'Value 1', value: 'Value 1',
label: 'Label 1', label: 'Label 1',
id: 1 id: 1
}, },
{ {
value: 'Value 2', value: 'Value 2',
label: 'Label 2', label: 'Label 2',
id: 2 id: 2
}] }]
``` ```
@ -170,16 +179,16 @@ Pass an array of objects:
``` ```
[{ [{
value: 'Option 1', value: 'Option 1',
label: 'Option 1', label: 'Option 1',
selected: true, selected: true,
disabled: false, disabled: false,
}, },
{ {
value: 'Option 2', value: 'Option 2',
label: 'Option 2', label: 'Option 2',
selected: false, selected: false,
disabled: true, disabled: true,
}] }]
``` ```
@ -239,19 +248,19 @@ Pass an array of objects:
**Usage:** Whether a user can paste into the input. **Usage:** Whether a user can paste into the input.
### search ### searchEnabled
**Type:** `Boolean` **Default:** `true` **Type:** `Boolean` **Default:** `true`
**Input types affected:** `select-one` **Input types affected:** `select-one`
**Usage:** Whether a user should be allowed to search avaiable choices. Note that multiple select boxes will always show search inputs. **Usage:** Whether a search area should be shown. **Note:** Multiple select boxes will *always* show search areas.
### searchChoices ### searchChoices
**Type:** `Boolean` **Default:** `true` **Type:** `Boolean` **Default:** `true`
**Input types affected:** `select-one` **Input types affected:** `select-one`
**Usage:** Whether the plugin should filter the choices by input or not. If `false`, the search event will still emit. **Usage:** Whether choices should be filtered by input or not. If `false`, the search event will still emit, but choices will not be filtered.
### searchFields ### searchFields

View file

@ -1,4 +1,4 @@
/*! choices.js v2.8.1 | (c) 2017 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ /*! choices.js v2.8.3 | (c) 2017 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
(function webpackUniversalModuleDefinition(root, factory) { (function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object') if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(); module.exports = factory();
@ -53,14 +53,14 @@ return /******/ (function(modules) { // webpackBootstrap
/************************************************************************/ /************************************************************************/
/******/ ([ /******/ ([
/* 0 */ /* 0 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(1); module.exports = __webpack_require__(1);
/***/ }, /***/ }),
/* 1 */ /* 1 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
'use strict'; 'use strict';
@ -113,6 +113,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
var defaultConfig = { var defaultConfig = {
silent: false,
items: [], items: [],
choices: [], choices: [],
maxItemCount: -1, maxItemCount: -1,
@ -123,7 +124,7 @@ return /******/ (function(modules) { // webpackBootstrap
duplicateItems: true, duplicateItems: true,
delimiter: ',', delimiter: ',',
paste: true, paste: true,
search: true, searchEnabled: true,
searchChoices: true, searchChoices: true,
searchFloor: 1, searchFloor: 1,
searchFields: ['label', 'value'], searchFields: ['label', 'value'],
@ -195,16 +196,18 @@ return /******/ (function(modules) { // webpackBootstrap
// Retrieve triggering element (i.e. element with 'data-choice' trigger) // Retrieve triggering element (i.e. element with 'data-choice' trigger)
this.element = element; this.element = element;
this.passedElement = (0, _utils.isType)('String', element) ? document.querySelector(element) : element; this.passedElement = (0, _utils.isType)('String', element) ? document.querySelector(element) : element;
this.isSelectElement = this.passedElement.type === 'select-one' || this.passedElement.type === 'select-multiple';
this.isTextElement = this.passedElement.type === 'text'; this.isTextElement = this.passedElement.type === 'text';
this.isSelectElement = this.passedElement.type === 'select-one' || this.passedElement.type === 'select-multiple';
if (!this.passedElement) { if (!this.passedElement) {
console.error('Passed element not found'); if (!this.config.silent) {
console.error('Passed element not found');
}
return; return;
} }
this.highlightPosition = 0; this.highlightPosition = 0;
this.canSearch = this.config.search; this.canSearch = this.config.searchEnabled;
// Assing preset choices from passed object // Assing preset choices from passed object
this.presetChoices = this.config.choices; this.presetChoices = this.config.choices;
@ -241,7 +244,9 @@ return /******/ (function(modules) { // webpackBootstrap
// Cutting the mustard // Cutting the mustard
var cuttingTheMustard = 'classList' in document.documentElement; var cuttingTheMustard = 'classList' in document.documentElement;
if (!cuttingTheMustard) console.error('Choices: Your browser doesn\'t support Choices'); if (!cuttingTheMustard && !this.config.silent) {
console.error('Choices: Your browser doesn\'t support Choices');
}
// Input type check // Input type check
var isValidType = ['select-one', 'select-multiple', 'text'].some(function (type) { var isValidType = ['select-one', 'select-multiple', 'text'].some(function (type) {
@ -251,11 +256,13 @@ return /******/ (function(modules) { // webpackBootstrap
if (canInit) { if (canInit) {
// If element has already been initalised with Choices // If element has already been initalised with Choices
if (this.passedElement.getAttribute('data-choice') === 'active') return; if (this.passedElement.getAttribute('data-choice') === 'active') {
return;
}
// Let's go // Let's go
this.init(); this.init();
} else { } else if (!this.config.silent) {
console.error('Incompatible input passed'); console.error('Incompatible input passed');
} }
} }
@ -274,7 +281,9 @@ return /******/ (function(modules) { // webpackBootstrap
_createClass(Choices, [{ _createClass(Choices, [{
key: 'init', key: 'init',
value: function init() { value: function init() {
if (this.initialised === true) return; if (this.initialised === true) {
return;
}
var callback = this.config.callbackOnInit; var callback = this.config.callbackOnInit;
@ -308,7 +317,9 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: 'destroy', key: 'destroy',
value: function destroy() { value: function destroy() {
if (this.initialised === false) return; if (this.initialised === false) {
return;
}
// Remove all event listeners // Remove all event listeners
this._removeEventListeners(); this._removeEventListeners();
@ -566,7 +577,10 @@ return /******/ (function(modules) { // webpackBootstrap
value: function highlightItem(item) { value: function highlightItem(item) {
var runEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var runEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
if (!item) return; if (!item) {
return;
}
var id = item.id; var id = item.id;
var groupId = item.groupId; var groupId = item.groupId;
var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; var group = groupId >= 0 ? this.store.getGroupById(groupId) : null;
@ -603,7 +617,10 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: 'unhighlightItem', key: 'unhighlightItem',
value: function unhighlightItem(item) { value: function unhighlightItem(item) {
if (!item) return; if (!item) {
return;
}
var id = item.id; var id = item.id;
var groupId = item.groupId; var groupId = item.groupId;
var group = groupId >= 0 ? this.store.getGroupById(groupId) : null; var group = groupId >= 0 ? this.store.getGroupById(groupId) : null;
@ -679,7 +696,9 @@ return /******/ (function(modules) { // webpackBootstrap
var _this7 = this; var _this7 = this;
if (!value || !(0, _utils.isType)('String', value)) { if (!value || !(0, _utils.isType)('String', value)) {
console.error('removeItemsByValue: No value was passed to be removed'); if (!this.config.silent) {
console.error('removeItemsByValue: No value was passed to be removed');
}
return; return;
} }
@ -897,7 +916,10 @@ return /******/ (function(modules) { // webpackBootstrap
handleValue = function handleValue(item) { handleValue = function handleValue(item) {
var itemType = (0, _utils.getType)(item); var itemType = (0, _utils.getType)(item);
if (itemType === 'Object') { if (itemType === 'Object') {
if (!item.value) return; if (!item.value) {
return;
}
// If we are dealing with a select input, we need to create an option first // If we are dealing with a select input, we need to create an option first
// that is then selected. For text inputs we can just add items normally. // that is then selected. For text inputs we can just add items normally.
if (passedElementType !== 'text') { if (passedElementType !== 'text') {
@ -952,10 +974,10 @@ return /******/ (function(modules) { // webpackBootstrap
if (foundChoice) { if (foundChoice) {
if (!foundChoice.selected) { if (!foundChoice.selected) {
_this12._addItem(foundChoice.value, foundChoice.label, foundChoice.id, foundChoice.groupId); _this12._addItem(foundChoice.value, foundChoice.label, foundChoice.id, foundChoice.groupId);
} else { } else if (!_this12.config.silent) {
console.warn('Attempting to select choice already selected'); console.warn('Attempting to select choice already selected');
} }
} else { } else if (!_this12.config.silent) {
console.warn('Attempting to select choice that does not exist'); console.warn('Attempting to select choice that does not exist');
} }
}); });
@ -982,7 +1004,9 @@ return /******/ (function(modules) { // webpackBootstrap
if (this.initialised === true) { if (this.initialised === true) {
if (this.isSelectElement) { if (this.isSelectElement) {
if (!(0, _utils.isType)('Array', choices) || !value) return; if (!(0, _utils.isType)('Array', choices) || !value) {
return;
}
// Clear choices if needed // Clear choices if needed
if (replaceChoices) { if (replaceChoices) {
this._clearChoices(); this._clearChoices();
@ -1032,7 +1056,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (this.passedElement.type !== 'select-one') { if (this.passedElement.type !== 'select-one') {
this._setInputWidth(); this._setInputWidth();
} }
if (this.passedElement.type !== 'text' && this.config.search) { if (this.passedElement.type !== 'text' && this.config.searchEnabled) {
this.isSearching = false; this.isSearching = false;
this.store.dispatch((0, _index3.activateChoices)(true)); this.store.dispatch((0, _index3.activateChoices)(true));
} }
@ -1123,7 +1147,9 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_triggerChange', key: '_triggerChange',
value: function _triggerChange(value) { value: function _triggerChange(value) {
if (!value) return; if (!value) {
return;
}
(0, _utils.triggerEvent)(this.passedElement, 'change', { (0, _utils.triggerEvent)(this.passedElement, 'change', {
value: value value: value
@ -1141,7 +1167,9 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_handleButtonAction', key: '_handleButtonAction',
value: function _handleButtonAction(activeItems, element) { value: function _handleButtonAction(activeItems, element) {
if (!activeItems || !element) return; if (!activeItems || !element) {
return;
}
// If we are clicking on a button // If we are clicking on a button
if (this.config.removeItems && this.config.removeItemButton) { if (this.config.removeItems && this.config.removeItemButton) {
@ -1180,7 +1208,9 @@ return /******/ (function(modules) { // webpackBootstrap
var hasShiftKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var hasShiftKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
if (!activeItems || !element) return; if (!activeItems || !element) {
return;
}
// If we are clicking on an item // If we are clicking on an item
if (this.config.removeItems && this.passedElement.type !== 'select-one') { if (this.config.removeItems && this.passedElement.type !== 'select-one') {
@ -1201,7 +1231,9 @@ return /******/ (function(modules) { // webpackBootstrap
// Focus input as without focus, a user cannot do anything with a // Focus input as without focus, a user cannot do anything with a
// highlighted item // highlighted item
if (document.activeElement !== this.input) this.input.focus(); if (document.activeElement !== this.input) {
this.input.focus();
}
} }
} }
@ -1215,7 +1247,9 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_handleChoiceAction', key: '_handleChoiceAction',
value: function _handleChoiceAction(activeItems, element) { value: function _handleChoiceAction(activeItems, element) {
if (!activeItems || !element) return; if (!activeItems || !element) {
return;
}
// If we are clicking on an option // If we are clicking on an option
var id = element.getAttribute('data-id'); var id = element.getAttribute('data-id');
@ -1300,23 +1334,23 @@ return /******/ (function(modules) { // webpackBootstrap
} }
if (this.passedElement.type === 'text' && this.config.addItems && canAddItem) { if (this.passedElement.type === 'text' && this.config.addItems && canAddItem) {
var isUnique = !activeItems.some(function (item) {
return item.value === value.trim();
});
// If a user has supplied a regular expression filter // If a user has supplied a regular expression filter
if (this.config.regexFilter) { if (this.config.regexFilter) {
// Determine whether we can update based on whether // Determine whether we can update based on whether
// our regular expression passes // our regular expression passes
canAddItem = this._regexFilter(value); canAddItem = this._regexFilter(value);
} }
}
// If no duplicates are allowed, and the value already exists // If no duplicates are allowed, and the value already exists
// in the array // in the array
if (this.config.duplicateItems === false && !isUnique) { var isUnique = !activeItems.some(function (item) {
canAddItem = false; return item.value === value.trim();
notice = (0, _utils.isType)('Function', this.config.uniqueItemText) ? this.config.uniqueItemText(value) : this.config.uniqueItemText; });
}
if (!isUnique && !this.config.duplicateItems && this.passedElement.type !== 'select-one' && canAddItem) {
canAddItem = false;
notice = (0, _utils.isType)('Function', this.config.uniqueItemText) ? this.config.uniqueItemText(value) : this.config.uniqueItemText;
} }
return { return {
@ -1375,7 +1409,9 @@ return /******/ (function(modules) { // webpackBootstrap
var _this15 = this; var _this15 = this;
return function (results, value, label) { return function (results, value, label) {
if (!results || !value) return; if (!results || !value) {
return;
}
var parsedResults = (0, _utils.isType)('Object', results) ? [results] : results; var parsedResults = (0, _utils.isType)('Object', results) ? [results] : results;
@ -1440,7 +1476,10 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_handleSearch', key: '_handleSearch',
value: function _handleSearch(value) { value: function _handleSearch(value) {
if (!value) return; if (!value) {
return;
}
var choices = this.store.getChoices(); var choices = this.store.getChoices();
var hasUnactiveChoices = choices.some(function (option) { var hasUnactiveChoices = choices.some(function (option) {
return option.active !== true; return option.active !== true;
@ -1449,7 +1488,7 @@ return /******/ (function(modules) { // webpackBootstrap
// Run callback if it is a function // Run callback if it is a function
if (this.input === document.activeElement) { if (this.input === document.activeElement) {
// Check that we have a value to search and the input was an alphanumeric character // Check that we have a value to search and the input was an alphanumeric character
if (value && value.length > this.config.searchFloor) { if (value && value.length >= this.config.searchFloor) {
// Check flag to filter search input // Check flag to filter search input
if (this.config.searchChoices) { if (this.config.searchChoices) {
// Filter available choices // Filter available choices
@ -1532,7 +1571,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_setInputWidth', key: '_setInputWidth',
value: function _setInputWidth() { value: function _setInputWidth() {
if (this.config.placeholder && (this.config.placeholderValue || this.passedElement.getAttribute('placeholder'))) { if (this.config.placeholderValue || this.passedElement.getAttribute('placeholder') && this.config.placeholder) {
// If there is a placeholder, we only want to set the width of the input when it is a greater // If there is a placeholder, we only want to set the width of the input when it is a greater
// length than 75% of the placeholder. This stops the input jumping around. // length than 75% of the placeholder. This stops the input jumping around.
var placeholder = this.config.placeholder ? this.config.placeholderValue || this.passedElement.getAttribute('placeholder') : false; var placeholder = this.config.placeholder ? this.config.placeholderValue || this.passedElement.getAttribute('placeholder') : false;
@ -1557,7 +1596,9 @@ return /******/ (function(modules) { // webpackBootstrap
var _this16 = this, var _this16 = this,
_keyDownActions; _keyDownActions;
if (e.target !== this.input && !this.containerOuter.contains(e.target)) return; if (e.target !== this.input && !this.containerOuter.contains(e.target)) {
return;
}
var target = e.target; var target = e.target;
var passedElementType = this.passedElement.type; var passedElementType = this.passedElement.type;
@ -1583,7 +1624,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.showDropdown(true); this.showDropdown(true);
} }
this.canSearch = this.config.search; this.canSearch = this.config.searchEnabled;
var onAKey = function onAKey() { var onAKey = function onAKey() {
// If CTRL + A or CMD + A have been pressed and there are items to select // If CTRL + A or CMD + A have been pressed and there are items to select
@ -1712,7 +1753,9 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_onKeyUp', key: '_onKeyUp',
value: function _onKeyUp(e) { value: function _onKeyUp(e) {
if (e.target !== this.input) return; if (e.target !== this.input) {
return;
}
var value = this.input.value; var value = this.input.value;
var activeItems = this.store.getItemsFilteredByActive(); var activeItems = this.store.getItemsFilteredByActive();
@ -2030,18 +2073,16 @@ return /******/ (function(modules) { // webpackBootstrap
_this18.hideDropdown(); _this18.hideDropdown();
} }
} }
if (target === _this18.input && hasActiveDropdown) {
if (target === _this18.input) {
// Hide dropdown if it is showing // Hide dropdown if it is showing
if (hasActiveDropdown) { _this18.hideDropdown();
_this18.hideDropdown();
}
} }
}, },
'select-multiple': function selectMultiple() { 'select-multiple': function selectMultiple() {
if (target === _this18.input) { if (target === _this18.input) {
// Remove the focus state // Remove the focus state
_this18.containerOuter.classList.remove(_this18.config.classNames.focusState); _this18.containerOuter.classList.remove(_this18.config.classNames.focusState);
// Hide dropdown if it is showing
if (hasActiveDropdown) { if (hasActiveDropdown) {
_this18.hideDropdown(); _this18.hideDropdown();
} }
@ -2067,7 +2108,10 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_regexFilter', key: '_regexFilter',
value: function _regexFilter(value) { value: function _regexFilter(value) {
if (!value) return; if (!value) {
return;
}
var regex = this.config.regexFilter; var regex = this.config.regexFilter;
var expression = new RegExp(regex.source, 'i'); var expression = new RegExp(regex.source, 'i');
return expression.test(value); return expression.test(value);
@ -2086,7 +2130,9 @@ return /******/ (function(modules) { // webpackBootstrap
value: function _scrollToChoice(choice, direction) { value: function _scrollToChoice(choice, direction) {
var _this19 = this; var _this19 = this;
if (!choice) return; if (!choice) {
return;
}
var dropdownHeight = this.choiceList.offsetHeight; var dropdownHeight = this.choiceList.offsetHeight;
var choiceHeight = choice.offsetHeight; var choiceHeight = choice.offsetHeight;
@ -2253,7 +2299,9 @@ return /******/ (function(modules) { // webpackBootstrap
key: '_removeItem', key: '_removeItem',
value: function _removeItem(item) { value: function _removeItem(item) {
if (!item || !(0, _utils.isType)('Object', item)) { if (!item || !(0, _utils.isType)('Object', item)) {
console.error('removeItem: No item object was passed to be removed'); if (!this.config.silent) {
console.error('removeItem: No item object was passed to be removed');
}
return; return;
} }
@ -2300,7 +2348,9 @@ return /******/ (function(modules) { // webpackBootstrap
value: function _addChoice(isSelected, isDisabled, value, label) { value: function _addChoice(isSelected, isDisabled, value, label) {
var groupId = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1; var groupId = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
if (typeof value === 'undefined' || value === null) return; if (typeof value === 'undefined' || value === null) {
return;
}
// Generate unique id // Generate unique id
var choices = this.store.getChoices(); var choices = this.store.getChoices();
@ -2380,7 +2430,9 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_getTemplate', key: '_getTemplate',
value: function _getTemplate(template) { value: function _getTemplate(template) {
if (!template) return; if (!template) {
return;
}
var templates = this.config.templates; var templates = this.config.templates;
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
@ -2483,6 +2535,7 @@ return /******/ (function(modules) { // webpackBootstrap
// Hide passed input // Hide passed input
this.passedElement.classList.add(this.config.classNames.input, this.config.classNames.hiddenState); this.passedElement.classList.add(this.config.classNames.input, this.config.classNames.hiddenState);
this.passedElement.tabIndex = '-1'; this.passedElement.tabIndex = '-1';
this.passedElement.setAttribute('style', 'display:none;'); this.passedElement.setAttribute('style', 'display:none;');
this.passedElement.setAttribute('aria-hidden', 'true'); this.passedElement.setAttribute('aria-hidden', 'true');
@ -2502,7 +2555,9 @@ return /******/ (function(modules) { // webpackBootstrap
} }
} }
if (!this.config.addItems) this.disable(); if (!this.config.addItems) {
this.disable();
}
containerOuter.appendChild(containerInner); containerOuter.appendChild(containerInner);
containerOuter.appendChild(dropdown); containerOuter.appendChild(dropdown);
@ -2518,7 +2573,7 @@ return /******/ (function(modules) { // webpackBootstrap
dropdown.insertBefore(input, dropdown.firstChild); dropdown.insertBefore(input, dropdown.firstChild);
} }
if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'select-one') { if (this.isSelectElement) {
var passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP')); var passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP'));
this.highlightPosition = 0; this.highlightPosition = 0;
@ -2577,7 +2632,9 @@ return /******/ (function(modules) { // webpackBootstrap
this.presetItems.forEach(function (item) { this.presetItems.forEach(function (item) {
var itemType = (0, _utils.getType)(item); var itemType = (0, _utils.getType)(item);
if (itemType === 'Object') { if (itemType === 'Object') {
if (!item.value) return; if (!item.value) {
return;
}
_this23._addItem(item.value, item.label, item.id); _this23._addItem(item.value, item.label, item.id);
} else if (itemType === 'String') { } else if (itemType === 'String') {
_this23._addItem(item); _this23._addItem(item);
@ -2595,9 +2652,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = Choices; module.exports = Choices;
/***/ }, /***/ }),
/* 2 */ /* 2 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
/** /**
* @license * @license
@ -2717,7 +2774,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
} }
Fuse.VERSION = '2.6.2' Fuse.VERSION = '2.7.3'
/** /**
* Sets a new list for Fuse to match against. * Sets a new list for Fuse to match against.
@ -2997,7 +3054,6 @@ return /******/ (function(modules) { // webpackBootstrap
var options = this.options var options = this.options
var getFn = options.getFn var getFn = options.getFn
var finalOutput = [] var finalOutput = []
var item
var i var i
var len var len
var results = this.results var results = this.results
@ -3057,8 +3113,7 @@ return /******/ (function(modules) { // webpackBootstrap
// since it contains other metadata // since it contains other metadata
for (i = 0, len = results.length; i < len; i++) { for (i = 0, len = results.length; i < len; i++) {
replaceValue(i) replaceValue(i)
item = getItemAtIndex(i) finalOutput.push(getItemAtIndex(i))
finalOutput.push(item)
} }
return finalOutput return finalOutput
@ -3334,12 +3389,11 @@ return /******/ (function(modules) { // webpackBootstrap
matchMask[j - 1] = 1 matchMask[j - 1] = 1
} }
if (i === 0) { bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch
// First pass: exact match.
bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch if (i !== 0) {
} else {
// Subsequent passes: fuzzy match. // Subsequent passes: fuzzy match.
bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch | (((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1) | lastBitArr[j + 1] bitArr[j] |= (((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1) | lastBitArr[j + 1]
} }
if (bitArr[j] & this.matchmask) { if (bitArr[j] & this.matchmask) {
score = this._bitapScore(i, j - 1) score = this._bitapScore(i, j - 1)
@ -3352,13 +3406,13 @@ return /******/ (function(modules) { // webpackBootstrap
bestLoc = j - 1 bestLoc = j - 1
locations.push(bestLoc) locations.push(bestLoc)
if (bestLoc > location) { // Already passed loc, downhill from here on in.
// When passing loc, don't exceed our current distance from loc. if (bestLoc <= location) {
start = Math.max(1, 2 * location - bestLoc)
} else {
// Already passed loc, downhill from here on in.
break break
} }
// When passing loc, don't exceed our current distance from loc.
start = Math.max(1, 2 * location - bestLoc)
} }
} }
} }
@ -3426,9 +3480,9 @@ return /******/ (function(modules) { // webpackBootstrap
})(this); })(this);
/***/ }, /***/ }),
/* 3 */ /* 3 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
'use strict'; 'use strict';
@ -3659,9 +3713,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = Store; module.exports = Store;
/***/ }, /***/ }),
/* 4 */ /* 4 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
'use strict'; 'use strict';
@ -3710,9 +3764,9 @@ return /******/ (function(modules) { // webpackBootstrap
exports.applyMiddleware = _applyMiddleware2['default']; exports.applyMiddleware = _applyMiddleware2['default'];
exports.compose = _compose2['default']; exports.compose = _compose2['default'];
/***/ }, /***/ }),
/* 5 */ /* 5 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
'use strict'; 'use strict';
@ -3976,9 +4030,9 @@ return /******/ (function(modules) { // webpackBootstrap
}, _ref2[_symbolObservable2['default']] = observable, _ref2; }, _ref2[_symbolObservable2['default']] = observable, _ref2;
} }
/***/ }, /***/ }),
/* 6 */ /* 6 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
var baseGetTag = __webpack_require__(7), var baseGetTag = __webpack_require__(7),
getPrototype = __webpack_require__(13), getPrototype = __webpack_require__(13),
@ -4044,9 +4098,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = isPlainObject; module.exports = isPlainObject;
/***/ }, /***/ }),
/* 7 */ /* 7 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
var Symbol = __webpack_require__(8), var Symbol = __webpack_require__(8),
getRawTag = __webpack_require__(11), getRawTag = __webpack_require__(11),
@ -4078,9 +4132,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = baseGetTag; module.exports = baseGetTag;
/***/ }, /***/ }),
/* 8 */ /* 8 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
var root = __webpack_require__(9); var root = __webpack_require__(9);
@ -4090,9 +4144,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = Symbol; module.exports = Symbol;
/***/ }, /***/ }),
/* 9 */ /* 9 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
var freeGlobal = __webpack_require__(10); var freeGlobal = __webpack_require__(10);
@ -4105,9 +4159,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = root; module.exports = root;
/***/ }, /***/ }),
/* 10 */ /* 10 */
/***/ function(module, exports) { /***/ (function(module, exports) {
/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ /* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
@ -4116,9 +4170,9 @@ return /******/ (function(modules) { // webpackBootstrap
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
/***/ }, /***/ }),
/* 11 */ /* 11 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
var Symbol = __webpack_require__(8); var Symbol = __webpack_require__(8);
@ -4168,9 +4222,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = getRawTag; module.exports = getRawTag;
/***/ }, /***/ }),
/* 12 */ /* 12 */
/***/ function(module, exports) { /***/ (function(module, exports) {
/** Used for built-in method references. */ /** Used for built-in method references. */
var objectProto = Object.prototype; var objectProto = Object.prototype;
@ -4196,9 +4250,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = objectToString; module.exports = objectToString;
/***/ }, /***/ }),
/* 13 */ /* 13 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
var overArg = __webpack_require__(14); var overArg = __webpack_require__(14);
@ -4208,9 +4262,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = getPrototype; module.exports = getPrototype;
/***/ }, /***/ }),
/* 14 */ /* 14 */
/***/ function(module, exports) { /***/ (function(module, exports) {
/** /**
* Creates a unary function that invokes `func` with its argument transformed. * Creates a unary function that invokes `func` with its argument transformed.
@ -4229,9 +4283,9 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = overArg; module.exports = overArg;
/***/ }, /***/ }),
/* 15 */ /* 15 */
/***/ function(module, exports) { /***/ (function(module, exports) {
/** /**
* Checks if `value` is object-like. A value is object-like if it's not `null` * Checks if `value` is object-like. A value is object-like if it's not `null`
@ -4264,16 +4318,16 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = isObjectLike; module.exports = isObjectLike;
/***/ }, /***/ }),
/* 16 */ /* 16 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(17); module.exports = __webpack_require__(17);
/***/ }, /***/ }),
/* 17 */ /* 17 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global, module) {'use strict'; /* WEBPACK VAR INJECTION */(function(global, module) {'use strict';
@ -4306,9 +4360,9 @@ return /******/ (function(modules) { // webpackBootstrap
exports['default'] = result; exports['default'] = result;
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(18)(module))) /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(18)(module)))
/***/ }, /***/ }),
/* 18 */ /* 18 */
/***/ function(module, exports) { /***/ (function(module, exports) {
module.exports = function(module) { module.exports = function(module) {
if(!module.webpackPolyfill) { if(!module.webpackPolyfill) {
@ -4322,9 +4376,9 @@ return /******/ (function(modules) { // webpackBootstrap
} }
/***/ }, /***/ }),
/* 19 */ /* 19 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -4350,9 +4404,9 @@ return /******/ (function(modules) { // webpackBootstrap
return result; return result;
}; };
/***/ }, /***/ }),
/* 20 */ /* 20 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
'use strict'; 'use strict';
@ -4497,9 +4551,9 @@ return /******/ (function(modules) { // webpackBootstrap
}; };
} }
/***/ }, /***/ }),
/* 21 */ /* 21 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -4527,9 +4581,9 @@ return /******/ (function(modules) { // webpackBootstrap
/* eslint-enable no-empty */ /* eslint-enable no-empty */
} }
/***/ }, /***/ }),
/* 22 */ /* 22 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -4583,9 +4637,9 @@ return /******/ (function(modules) { // webpackBootstrap
return boundActionCreators; return boundActionCreators;
} }
/***/ }, /***/ }),
/* 23 */ /* 23 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
'use strict'; 'use strict';
@ -4646,9 +4700,9 @@ return /******/ (function(modules) { // webpackBootstrap
}; };
} }
/***/ }, /***/ }),
/* 24 */ /* 24 */
/***/ function(module, exports) { /***/ (function(module, exports) {
"use strict"; "use strict";
@ -4689,9 +4743,9 @@ return /******/ (function(modules) { // webpackBootstrap
}; };
} }
/***/ }, /***/ }),
/* 25 */ /* 25 */
/***/ function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
'use strict'; 'use strict';
@ -4736,9 +4790,9 @@ return /******/ (function(modules) { // webpackBootstrap
exports.default = rootReducer; exports.default = rootReducer;
/***/ }, /***/ }),
/* 26 */ /* 26 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -4804,9 +4858,9 @@ return /******/ (function(modules) { // webpackBootstrap
exports.default = items; exports.default = items;
/***/ }, /***/ }),
/* 27 */ /* 27 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -4845,9 +4899,9 @@ return /******/ (function(modules) { // webpackBootstrap
exports.default = groups; exports.default = groups;
/***/ }, /***/ }),
/* 28 */ /* 28 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -4965,9 +5019,9 @@ return /******/ (function(modules) { // webpackBootstrap
exports.default = choices; exports.default = choices;
/***/ }, /***/ }),
/* 29 */ /* 29 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -5050,9 +5104,9 @@ return /******/ (function(modules) { // webpackBootstrap
}; };
}; };
/***/ }, /***/ }),
/* 30 */ /* 30 */
/***/ function(module, exports) { /***/ (function(module, exports) {
"use strict"; "use strict";
@ -5597,9 +5651,9 @@ return /******/ (function(modules) { // webpackBootstrap
return element.dispatchEvent(event); return element.dispatchEvent(event);
}; };
/***/ }, /***/ }),
/* 31 */ /* 31 */
/***/ function(module, exports) { /***/ (function(module, exports) {
'use strict'; 'use strict';
@ -5734,7 +5788,7 @@ return /******/ (function(modules) { // webpackBootstrap
window.CustomEvent = CustomEvent; window.CustomEvent = CustomEvent;
})(); })();
/***/ } /***/ })
/******/ ]) /******/ ])
}); });
; ;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -49,6 +49,7 @@ class Choices {
} }
const defaultConfig = { const defaultConfig = {
silent: false,
items: [], items: [],
choices: [], choices: [],
maxItemCount: -1, maxItemCount: -1,
@ -59,7 +60,7 @@ class Choices {
duplicateItems: true, duplicateItems: true,
delimiter: ',', delimiter: ',',
paste: true, paste: true,
search: true, searchEnabled: true,
searchChoices: true, searchChoices: true,
searchFloor: 1, searchFloor: 1,
searchFields: ['label', 'value'], searchFields: ['label', 'value'],
@ -131,16 +132,19 @@ class Choices {
// Retrieve triggering element (i.e. element with 'data-choice' trigger) // Retrieve triggering element (i.e. element with 'data-choice' trigger)
this.element = element; this.element = element;
this.passedElement = isType('String', element) ? document.querySelector(element) : element; this.passedElement = isType('String', element) ? document.querySelector(element) : element;
this.isSelectElement = this.passedElement.type === 'select-one' || this.passedElement.type === 'select-multiple';
this.isTextElement = this.passedElement.type === 'text'; this.isTextElement = this.passedElement.type === 'text';
this.isSelectElement = this.passedElement.type === 'select-one' ||
this.passedElement.type === 'select-multiple';
if (!this.passedElement) { if (!this.passedElement) {
console.error('Passed element not found'); if (!this.config.silent) {
console.error('Passed element not found');
}
return; return;
} }
this.highlightPosition = 0; this.highlightPosition = 0;
this.canSearch = this.config.search; this.canSearch = this.config.searchEnabled;
// Assing preset choices from passed object // Assing preset choices from passed object
this.presetChoices = this.config.choices; this.presetChoices = this.config.choices;
@ -150,7 +154,9 @@ class Choices {
// Then add any values passed from attribute // Then add any values passed from attribute
if (this.passedElement.value) { if (this.passedElement.value) {
this.presetItems = this.presetItems.concat(this.passedElement.value.split(this.config.delimiter)); this.presetItems = this.presetItems.concat(
this.passedElement.value.split(this.config.delimiter)
);
} }
// Bind methods // Bind methods
@ -177,7 +183,9 @@ class Choices {
// Cutting the mustard // Cutting the mustard
const cuttingTheMustard = 'classList' in document.documentElement; const cuttingTheMustard = 'classList' in document.documentElement;
if (!cuttingTheMustard) console.error('Choices: Your browser doesn\'t support Choices'); if (!cuttingTheMustard && !this.config.silent) {
console.error('Choices: Your browser doesn\'t support Choices');
}
// Input type check // Input type check
const isValidType = ['select-one', 'select-multiple', 'text'].some(type => type === this.passedElement.type); const isValidType = ['select-one', 'select-multiple', 'text'].some(type => type === this.passedElement.type);
@ -185,11 +193,13 @@ class Choices {
if (canInit) { if (canInit) {
// If element has already been initalised with Choices // If element has already been initalised with Choices
if (this.passedElement.getAttribute('data-choice') === 'active') return; if (this.passedElement.getAttribute('data-choice') === 'active') {
return;
}
// Let's go // Let's go
this.init(); this.init();
} else { } else if (!this.config.silent) {
console.error('Incompatible input passed'); console.error('Incompatible input passed');
} }
} }
@ -204,7 +214,9 @@ class Choices {
* @public * @public
*/ */
init() { init() {
if (this.initialised === true) return; if (this.initialised === true) {
return;
}
const callback = this.config.callbackOnInit; const callback = this.config.callbackOnInit;
@ -235,7 +247,9 @@ class Choices {
* @public * @public
*/ */
destroy() { destroy() {
if (this.initialised === false) return; if (this.initialised === false) {
return;
}
// Remove all event listeners // Remove all event listeners
this._removeEventListeners(); this._removeEventListeners();
@ -476,7 +490,10 @@ class Choices {
* @public * @public
*/ */
highlightItem(item, runEvent = true) { highlightItem(item, runEvent = true) {
if (!item) return; if (!item) {
return;
}
const id = item.id; const id = item.id;
const groupId = item.groupId; const groupId = item.groupId;
const group = groupId >= 0 ? this.store.getGroupById(groupId) : null; const group = groupId >= 0 ? this.store.getGroupById(groupId) : null;
@ -510,7 +527,10 @@ class Choices {
* @public * @public
*/ */
unhighlightItem(item) { unhighlightItem(item) {
if (!item) return; if (!item) {
return;
}
const id = item.id; const id = item.id;
const groupId = item.groupId; const groupId = item.groupId;
const group = groupId >= 0 ? this.store.getGroupById(groupId) : null; const group = groupId >= 0 ? this.store.getGroupById(groupId) : null;
@ -571,7 +591,9 @@ class Choices {
*/ */
removeItemsByValue(value) { removeItemsByValue(value) {
if (!value || !isType('String', value)) { if (!value || !isType('String', value)) {
console.error('removeItemsByValue: No value was passed to be removed'); if (!this.config.silent) {
console.error('removeItemsByValue: No value was passed to be removed');
}
return; return;
} }
@ -758,7 +780,10 @@ class Choices {
handleValue = (item) => { handleValue = (item) => {
const itemType = getType(item); const itemType = getType(item);
if (itemType === 'Object') { if (itemType === 'Object') {
if (!item.value) return; if (!item.value) {
return;
}
// If we are dealing with a select input, we need to create an option first // If we are dealing with a select input, we need to create an option first
// that is then selected. For text inputs we can just add items normally. // that is then selected. For text inputs we can just add items normally.
if (passedElementType !== 'text') { if (passedElementType !== 'text') {
@ -808,10 +833,10 @@ class Choices {
if (foundChoice) { if (foundChoice) {
if (!foundChoice.selected) { if (!foundChoice.selected) {
this._addItem(foundChoice.value, foundChoice.label, foundChoice.id, foundChoice.groupId); this._addItem(foundChoice.value, foundChoice.label, foundChoice.id, foundChoice.groupId);
} else { } else if (!this.config.silent) {
console.warn('Attempting to select choice already selected'); console.warn('Attempting to select choice already selected');
} }
} else { } else if (!this.config.silent) {
console.warn('Attempting to select choice that does not exist'); console.warn('Attempting to select choice that does not exist');
} }
}); });
@ -831,7 +856,9 @@ class Choices {
setChoices(choices, value, label, replaceChoices = false) { setChoices(choices, value, label, replaceChoices = false) {
if (this.initialised === true) { if (this.initialised === true) {
if (this.isSelectElement) { if (this.isSelectElement) {
if (!isType('Array', choices) || !value) return; if (!isType('Array', choices) || !value) {
return;
}
// Clear choices if needed // Clear choices if needed
if(replaceChoices) { if(replaceChoices) {
this._clearChoices(); this._clearChoices();
@ -875,7 +902,7 @@ class Choices {
if (this.passedElement.type !== 'select-one') { if (this.passedElement.type !== 'select-one') {
this._setInputWidth(); this._setInputWidth();
} }
if (this.passedElement.type !== 'text' && this.config.search) { if (this.passedElement.type !== 'text' && this.config.searchEnabled) {
this.isSearching = false; this.isSearching = false;
this.store.dispatch(activateChoices(true)); this.store.dispatch(activateChoices(true));
} }
@ -954,7 +981,9 @@ class Choices {
* @private * @private
*/ */
_triggerChange(value) { _triggerChange(value) {
if (!value) return; if (!value) {
return;
}
triggerEvent(this.passedElement, 'change', { triggerEvent(this.passedElement, 'change', {
value value
@ -969,7 +998,9 @@ class Choices {
* @private * @private
*/ */
_handleButtonAction(activeItems, element) { _handleButtonAction(activeItems, element) {
if (!activeItems || !element) return; if (!activeItems || !element) {
return;
}
// If we are clicking on a button // If we are clicking on a button
if (this.config.removeItems && this.config.removeItemButton) { if (this.config.removeItems && this.config.removeItemButton) {
@ -1000,7 +1031,9 @@ class Choices {
* @private * @private
*/ */
_handleItemAction(activeItems, element, hasShiftKey = false) { _handleItemAction(activeItems, element, hasShiftKey = false) {
if (!activeItems || !element) return; if (!activeItems || !element) {
return;
}
// If we are clicking on an item // If we are clicking on an item
if (this.config.removeItems && this.passedElement.type !== 'select-one') { if (this.config.removeItems && this.passedElement.type !== 'select-one') {
@ -1021,7 +1054,9 @@ class Choices {
// Focus input as without focus, a user cannot do anything with a // Focus input as without focus, a user cannot do anything with a
// highlighted item // highlighted item
if (document.activeElement !== this.input) this.input.focus(); if (document.activeElement !== this.input) {
this.input.focus();
}
} }
} }
@ -1032,7 +1067,9 @@ class Choices {
* @return {[type]} [description] * @return {[type]} [description]
*/ */
_handleChoiceAction(activeItems, element) { _handleChoiceAction(activeItems, element) {
if (!activeItems || !element) return; if (!activeItems || !element) {
return;
}
// If we are clicking on an option // If we are clicking on an option
const id = element.getAttribute('data-id'); const id = element.getAttribute('data-id');
@ -1097,7 +1134,9 @@ class Choices {
*/ */
_canAddItem(activeItems, value) { _canAddItem(activeItems, value) {
let canAddItem = true; let canAddItem = true;
let notice = isType('Function', this.config.addItemText) ? this.config.addItemText(value) : this.config.addItemText; let notice = isType('Function', this.config.addItemText) ?
this.config.addItemText(value) :
this.config.addItemText;
if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'text') { if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'text') {
if (this.config.maxItemCount > 0 && this.config.maxItemCount <= activeItems.length) { if (this.config.maxItemCount > 0 && this.config.maxItemCount <= activeItems.length) {
@ -1111,21 +1150,27 @@ class Choices {
} }
if (this.passedElement.type === 'text' && this.config.addItems && canAddItem) { if (this.passedElement.type === 'text' && this.config.addItems && canAddItem) {
const isUnique = !activeItems.some((item) => item.value === isType('String', value) ? value.trim() : value);
// If a user has supplied a regular expression filter // If a user has supplied a regular expression filter
if (this.config.regexFilter) { if (this.config.regexFilter) {
// Determine whether we can update based on whether // Determine whether we can update based on whether
// our regular expression passes // our regular expression passes
canAddItem = this._regexFilter(value); canAddItem = this._regexFilter(value);
} }
}
// If no duplicates are allowed, and the value already exists
// in the array // If no duplicates are allowed, and the value already exists
if (this.config.duplicateItems === false && !isUnique) { // in the array
canAddItem = false; const isUnique = !activeItems.some((item) => item.value === isType('String', value) ? value.trim() : value);
notice = isType('Function', this.config.uniqueItemText) ? this.config.uniqueItemText(value) : this.config.uniqueItemText;
} if (
!isUnique &&
!this.config.duplicateItems &&
this.passedElement.type !== 'select-one' &&
canAddItem
) {
canAddItem = false;
notice = isType('Function', this.config.uniqueItemText) ? this.config.uniqueItemText(value) : this.config.uniqueItemText;
} }
return { return {
@ -1174,7 +1219,9 @@ class Choices {
*/ */
_ajaxCallback() { _ajaxCallback() {
return (results, value, label) => { return (results, value, label) => {
if (!results || !value) return; if (!results || !value) {
return;
}
const parsedResults = isType('Object', results) ? [results] : results; const parsedResults = isType('Object', results) ? [results] : results;
@ -1233,14 +1280,17 @@ class Choices {
* @private * @private
*/ */
_handleSearch(value) { _handleSearch(value) {
if (!value) return; if (!value) {
return;
}
const choices = this.store.getChoices(); const choices = this.store.getChoices();
const hasUnactiveChoices = choices.some((option) => option.active !== true); const hasUnactiveChoices = choices.some((option) => option.active !== true);
// Run callback if it is a function // Run callback if it is a function
if (this.input === document.activeElement) { if (this.input === document.activeElement) {
// Check that we have a value to search and the input was an alphanumeric character // Check that we have a value to search and the input was an alphanumeric character
if (value && value.length > this.config.searchFloor) { if (value && value.length >= this.config.searchFloor) {
// Check flag to filter search input // Check flag to filter search input
if (this.config.searchChoices) { if (this.config.searchChoices) {
// Filter available choices // Filter available choices
@ -1314,7 +1364,8 @@ class Choices {
* @return * @return
*/ */
_setInputWidth() { _setInputWidth() {
if (this.config.placeholder && (this.config.placeholderValue || this.passedElement.getAttribute('placeholder'))) { if ((this.config.placeholderValue || this.passedElement.getAttribute('placeholder') &&
this.config.placeholder)) {
// If there is a placeholder, we only want to set the width of the input when it is a greater // If there is a placeholder, we only want to set the width of the input when it is a greater
// length than 75% of the placeholder. This stops the input jumping around. // length than 75% of the placeholder. This stops the input jumping around.
const placeholder = this.config.placeholder ? this.config.placeholderValue || const placeholder = this.config.placeholder ? this.config.placeholderValue ||
@ -1334,7 +1385,9 @@ class Choices {
* @return * @return
*/ */
_onKeyDown(e) { _onKeyDown(e) {
if (e.target !== this.input && !this.containerOuter.contains(e.target)) return; if (e.target !== this.input && !this.containerOuter.contains(e.target)) {
return;
}
const target = e.target; const target = e.target;
const passedElementType = this.passedElement.type; const passedElementType = this.passedElement.type;
@ -1360,7 +1413,7 @@ class Choices {
this.showDropdown(true); this.showDropdown(true);
} }
this.canSearch = this.config.search; this.canSearch = this.config.searchEnabled;
const onAKey = () => { const onAKey = () => {
// If CTRL + A or CMD + A have been pressed and there are items to select // If CTRL + A or CMD + A have been pressed and there are items to select
@ -1497,7 +1550,9 @@ class Choices {
* @private * @private
*/ */
_onKeyUp(e) { _onKeyUp(e) {
if (e.target !== this.input) return; if (e.target !== this.input) {
return;
}
const value = this.input.value; const value = this.input.value;
const activeItems = this.store.getItemsFilteredByActive(); const activeItems = this.store.getItemsFilteredByActive();
@ -1781,18 +1836,16 @@ class Choices {
this.hideDropdown(); this.hideDropdown();
} }
} }
if (target === this.input && hasActiveDropdown) {
if (target === this.input) {
// Hide dropdown if it is showing // Hide dropdown if it is showing
if (hasActiveDropdown) { this.hideDropdown();
this.hideDropdown();
}
} }
}, },
'select-multiple': () => { 'select-multiple': () => {
if (target === this.input) { if (target === this.input) {
// Remove the focus state // Remove the focus state
this.containerOuter.classList.remove(this.config.classNames.focusState); this.containerOuter.classList.remove(this.config.classNames.focusState);
// Hide dropdown if it is showing
if (hasActiveDropdown) { if (hasActiveDropdown) {
this.hideDropdown(); this.hideDropdown();
} }
@ -1815,7 +1868,10 @@ class Choices {
* @private * @private
*/ */
_regexFilter(value) { _regexFilter(value) {
if (!value) return; if (!value) {
return;
}
const regex = this.config.regexFilter; const regex = this.config.regexFilter;
const expression = new RegExp(regex.source, 'i'); const expression = new RegExp(regex.source, 'i');
return expression.test(value); return expression.test(value);
@ -1829,7 +1885,9 @@ class Choices {
* @private * @private
*/ */
_scrollToChoice(choice, direction) { _scrollToChoice(choice, direction) {
if (!choice) return; if (!choice) {
return;
}
const dropdownHeight = this.choiceList.offsetHeight; const dropdownHeight = this.choiceList.offsetHeight;
const choiceHeight = choice.offsetHeight; const choiceHeight = choice.offsetHeight;
@ -1982,7 +2040,9 @@ class Choices {
*/ */
_removeItem(item) { _removeItem(item) {
if (!item || !isType('Object', item)) { if (!item || !isType('Object', item)) {
console.error('removeItem: No item object was passed to be removed'); if (!this.config.silent) {
console.error('removeItem: No item object was passed to be removed');
}
return; return;
} }
@ -2024,7 +2084,9 @@ class Choices {
* @private * @private
*/ */
_addChoice(isSelected, isDisabled, value, label, groupId = -1) { _addChoice(isSelected, isDisabled, value, label, groupId = -1) {
if (typeof value === 'undefined' || value === null) return; if (typeof value === 'undefined' || value === null) {
return;
}
// Generate unique id // Generate unique id
const choices = this.store.getChoices(); const choices = this.store.getChoices();
@ -2090,7 +2152,9 @@ class Choices {
* @private * @private
*/ */
_getTemplate(template, ...args) { _getTemplate(template, ...args) {
if (!template) return; if (!template) {
return;
}
const templates = this.config.templates; const templates = this.config.templates;
return templates[template](...args); return templates[template](...args);
} }
@ -2201,7 +2265,10 @@ class Choices {
const choiceList = this._getTemplate('choiceList'); const choiceList = this._getTemplate('choiceList');
const input = this._getTemplate('input'); const input = this._getTemplate('input');
const dropdown = this._getTemplate('dropdown'); const dropdown = this._getTemplate('dropdown');
const placeholder = this.config.placeholder ? this.config.placeholderValue || this.passedElement.getAttribute('placeholder') : false; const placeholder = this.config.placeholder ?
this.config.placeholderValue ||
this.passedElement.getAttribute('placeholder') :
false;
this.containerOuter = containerOuter; this.containerOuter = containerOuter;
this.containerInner = containerInner; this.containerInner = containerInner;
@ -2211,7 +2278,11 @@ class Choices {
this.dropdown = dropdown; this.dropdown = dropdown;
// Hide passed input // Hide passed input
this.passedElement.classList.add(this.config.classNames.input, this.config.classNames.hiddenState); this.passedElement.classList.add(
this.config.classNames.input,
this.config.classNames.hiddenState
);
this.passedElement.tabIndex = '-1'; this.passedElement.tabIndex = '-1';
this.passedElement.setAttribute('style', 'display:none;'); this.passedElement.setAttribute('style', 'display:none;');
this.passedElement.setAttribute('aria-hidden', 'true'); this.passedElement.setAttribute('aria-hidden', 'true');
@ -2231,7 +2302,9 @@ class Choices {
} }
} }
if (!this.config.addItems) this.disable(); if (!this.config.addItems) {
this.disable();
}
containerOuter.appendChild(containerInner); containerOuter.appendChild(containerInner);
containerOuter.appendChild(dropdown); containerOuter.appendChild(dropdown);
@ -2247,7 +2320,7 @@ class Choices {
dropdown.insertBefore(input, dropdown.firstChild); dropdown.insertBefore(input, dropdown.firstChild);
} }
if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'select-one') { if (this.isSelectElement) {
const passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP')); const passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP'));
this.highlightPosition = 0; this.highlightPosition = 0;
@ -2306,7 +2379,9 @@ class Choices {
this.presetItems.forEach((item) => { this.presetItems.forEach((item) => {
const itemType = getType(item); const itemType = getType(item);
if (itemType === 'Object') { if (itemType === 'Object') {
if (!item.value) return; if (!item.value) {
return;
}
this._addItem(item.value, item.label, item.id); this._addItem(item.value, item.label, item.id);
} else if (itemType === 'String') { } else if (itemType === 'String') {
this._addItem(item); this._addItem(item);

View file

@ -1,6 +1,6 @@
{ {
"name": "choices.js", "name": "choices.js",
"version": "2.8.1", "version": "2.8.3",
"description": "A vanilla JS customisable text input/select box plugin", "description": "A vanilla JS customisable text input/select box plugin",
"main": [ "main": [
"./assets/scripts/dist/choices.js", "./assets/scripts/dist/choices.js",

View file

@ -15,7 +15,7 @@
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<!-- Ignore these --> <!-- Ignore these -->
<link rel="stylesheet" href="assets/styles/css/base.min.css?version=2.8.1"> <link rel="stylesheet" href="assets/styles/css/base.min.css?version=2.8.3">
<!-- End ignore these --> <!-- End ignore these -->
<!-- Optional includes --> <!-- Optional includes -->
@ -23,8 +23,8 @@
<!-- End optional includes --> <!-- End optional includes -->
<!-- Choices includes --> <!-- Choices includes -->
<link rel="stylesheet" href="assets/styles/css/choices.min.css?version=2.8.1"> <link rel="stylesheet" href="assets/styles/css/choices.min.css?version=2.8.3">
<script src="assets/scripts/dist/choices.min.js?version=2.8.1"></script> <script src="assets/scripts/dist/choices.min.js?version=2.8.3"></script>
<!-- End Choices includes --> <!-- End Choices includes -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
@ -140,7 +140,6 @@
<label for="label-event">Use label in event (add/remove)</label> <label for="label-event">Use label in event (add/remove)</label>
<p id="message"></p> <p id="message"></p>
<select id="choices-multiple-labels" multiple></select> <select id="choices-multiple-labels" multiple></select>
<hr> <hr>
<h2>Single select input</h2> <h2>Single select input</h2>
@ -313,6 +312,7 @@
var multipleDefault = new Choices(document.getElementById('choices-multiple-groups')); var multipleDefault = new Choices(document.getElementById('choices-multiple-groups'));
var multipleFetch = new Choices('#choices-multiple-remote-fetch', { var multipleFetch = new Choices('#choices-multiple-remote-fetch', {
searchChoices: false,
placeholder: true, placeholder: true,
placeholderValue: 'Pick an Strokes record', placeholderValue: 'Pick an Strokes record',
maxItemCount: 5, maxItemCount: 5,
@ -334,7 +334,6 @@
/* Use label on event */ /* Use label on event */
var choicesSelect = new Choices('#choices-multiple-labels', { var choicesSelect = new Choices('#choices-multiple-labels', {
search: false,
removeItemButton: true, removeItemButton: true,
choices: [ choices: [
{value: 'One', label: 'Label One'}, {value: 'One', label: 'Label One'},
@ -398,7 +397,7 @@
}); });
var singleNoSearch = new Choices('#choices-single-no-search', { var singleNoSearch = new Choices('#choices-single-no-search', {
search: false, searchEnabled: false,
removeItemButton: true, removeItemButton: true,
choices: [ choices: [
{value: 'One', label: 'Label One'}, {value: 'One', label: 'Label One'},

View file

@ -1,6 +1,6 @@
{ {
"name": "choices.js", "name": "choices.js",
"version": "2.8.1", "version": "2.8.3",
"description": "A vanilla JS customisable text input/select box plugin", "description": "A vanilla JS customisable text input/select box plugin",
"main": "./assets/scripts/dist/choices.min.js", "main": "./assets/scripts/dist/choices.min.js",
"scripts": { "scripts": {

View file

@ -64,6 +64,7 @@ describe('Choices', () => {
}); });
it('should have config options', function() { it('should have config options', function() {
expect(this.choices.config.silent).toEqual(jasmine.any(Boolean));
expect(this.choices.config.items).toEqual(jasmine.any(Array)); expect(this.choices.config.items).toEqual(jasmine.any(Array));
expect(this.choices.config.choices).toEqual(jasmine.any(Array)); expect(this.choices.config.choices).toEqual(jasmine.any(Array));
expect(this.choices.config.maxItemCount).toEqual(jasmine.any(Number)); expect(this.choices.config.maxItemCount).toEqual(jasmine.any(Number));
@ -74,7 +75,8 @@ describe('Choices', () => {
expect(this.choices.config.duplicateItems).toEqual(jasmine.any(Boolean)); expect(this.choices.config.duplicateItems).toEqual(jasmine.any(Boolean));
expect(this.choices.config.delimiter).toEqual(jasmine.any(String)); expect(this.choices.config.delimiter).toEqual(jasmine.any(String));
expect(this.choices.config.paste).toEqual(jasmine.any(Boolean)); expect(this.choices.config.paste).toEqual(jasmine.any(Boolean));
expect(this.choices.config.search).toEqual(jasmine.any(Boolean)); expect(this.choices.config.searchEnabled).toEqual(jasmine.any(Boolean));
expect(this.choices.config.searchChoices).toEqual(jasmine.any(Boolean));
expect(this.choices.config.searchFloor).toEqual(jasmine.any(Number)); expect(this.choices.config.searchFloor).toEqual(jasmine.any(Number));
expect(this.choices.config.searchFields).toEqual(jasmine.any(Array) || jasmine.any(String)); expect(this.choices.config.searchFields).toEqual(jasmine.any(Array) || jasmine.any(String));
expect(this.choices.config.position).toEqual(jasmine.any(String)); expect(this.choices.config.position).toEqual(jasmine.any(String));