mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-09 17:16:36 +02:00
Merge branch 'feature/select-add-items'
This commit is contained in:
commit
4f03f7310c
|
@ -191,11 +191,11 @@ Pass an array of objects:
|
|||
**Usage:** The amount of items a user can input/select ("-1" indicates no limit).
|
||||
|
||||
### addItems
|
||||
**Type:** `Boolean` **Default:** `true`
|
||||
**Type:** `Boolean` **Default:** `true` (for text inputs) `false` (for select elements)
|
||||
|
||||
**Input types affected:** `text`
|
||||
**Input types affected:** `text`, `select-one`, `select-multiple`
|
||||
|
||||
**Usage:** Whether a user can add items.
|
||||
**Usage:** Whether a user can add items.
|
||||
|
||||
### removeItems
|
||||
**Type:** `Boolean` **Default:** `true`
|
||||
|
|
218
assets/scripts/dist/choices.js
vendored
218
assets/scripts/dist/choices.js
vendored
|
@ -1,4 +1,8 @@
|
|||
<<<<<<< HEAD
|
||||
/*! choices.js v2.7.8 | (c) 2017 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
|
||||
=======
|
||||
/*! choices.js v2.5.0 | (c) 2016 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
|
||||
>>>>>>> 291143b... Add dist files
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory();
|
||||
|
@ -180,18 +184,6 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
callbackOnCreateTemplates: null
|
||||
};
|
||||
|
||||
// Merge options with user options
|
||||
this.config = (0, _utils.extend)(defaultConfig, userConfig);
|
||||
|
||||
// Create data store
|
||||
this.store = new _index2.default(this.render);
|
||||
|
||||
// State tracking
|
||||
this.initialised = false;
|
||||
this.currentState = {};
|
||||
this.prevState = {};
|
||||
this.currentValue = '';
|
||||
|
||||
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
|
||||
this.element = element;
|
||||
this.passedElement = (0, _utils.isType)('String', element) ? document.querySelector(element) : element;
|
||||
|
@ -203,8 +195,14 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
return;
|
||||
}
|
||||
|
||||
this.highlightPosition = 0;
|
||||
this.canSearch = this.config.search;
|
||||
// It only makes sense for addItems to be true for
|
||||
// text inputs by default
|
||||
if (this.isSelectElement) {
|
||||
defaultConfig.addItems = false;
|
||||
}
|
||||
|
||||
// Merge options with user options
|
||||
this.config = (0, _utils.extend)(defaultConfig, userConfig);
|
||||
|
||||
// Assing preset choices from passed object
|
||||
this.presetChoices = this.config.choices;
|
||||
|
@ -236,7 +234,16 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
this._onPaste = this._onPaste.bind(this);
|
||||
this._onInput = this._onInput.bind(this);
|
||||
|
||||
// Monitor touch taps/scrolls
|
||||
// Create data store
|
||||
this.store = new _index2.default(this.render);
|
||||
|
||||
// State tracking
|
||||
this.initialised = false;
|
||||
this.currentState = {};
|
||||
this.prevState = {};
|
||||
this.currentValue = '';
|
||||
this.highlightPosition = 0;
|
||||
this.canSearch = this.config.search;
|
||||
this.wasTap = true;
|
||||
|
||||
// Cutting the mustard
|
||||
|
@ -475,7 +482,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
if (this.currentState !== this.prevState) {
|
||||
// Choices
|
||||
if (this.currentState.choices !== this.prevState.choices || this.currentState.groups !== this.prevState.groups) {
|
||||
if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'select-one') {
|
||||
if (!this.isTextElement) {
|
||||
// Get active groups/choices
|
||||
var activeGroups = this.store.getGroupsFilteredByActive();
|
||||
var activeChoices = this.store.getChoicesFilteredByActive();
|
||||
|
@ -501,8 +508,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
// If we actually have anything to add to our dropdown
|
||||
// append it and highlight the first choice
|
||||
this.choiceList.appendChild(choiceListFragment);
|
||||
this._highlightChoice();
|
||||
} else {
|
||||
<<<<<<< HEAD
|
||||
// Otherwise show a notice
|
||||
var dropdownItem = void 0;
|
||||
var notice = void 0;
|
||||
|
@ -513,6 +520,16 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
} else {
|
||||
notice = (0, _utils.isType)('Function', this.config.noChoicesText) ? this.config.noChoicesText() : this.config.noChoicesText;
|
||||
dropdownItem = this._getTemplate('notice', notice);
|
||||
=======
|
||||
var activeItems = this.store.getItemsFilteredByActive();
|
||||
var canAddItem = this._canAddItem(activeItems, this.input.value);
|
||||
var dropdownItem = this._getTemplate('notice', this.config.noChoicesText);
|
||||
|
||||
if (this.config.addItems && canAddItem.notice) {
|
||||
dropdownItem = this._getTemplate('notice', canAddItem.notice);
|
||||
} else if (this.isSearching) {
|
||||
dropdownItem = this._getTemplate('notice', this.config.noResultsText);
|
||||
>>>>>>> 291143b... Add dist files
|
||||
}
|
||||
|
||||
this.choiceList.appendChild(dropdownItem);
|
||||
|
@ -522,11 +539,11 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
// Items
|
||||
if (this.currentState.items !== this.prevState.items) {
|
||||
var activeItems = this.store.getItemsFilteredByActive();
|
||||
if (activeItems) {
|
||||
var _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)
|
||||
var itemListFragment = this.renderItems(activeItems);
|
||||
var itemListFragment = this.renderItems(_activeItems);
|
||||
|
||||
// Clear list
|
||||
this.itemList.innerHTML = '';
|
||||
|
@ -1222,10 +1239,10 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
if (canAddItem.response) {
|
||||
this._addItem(choice.value, choice.label, choice.id, choice.groupId);
|
||||
this._triggerChange(choice.value);
|
||||
}
|
||||
}
|
||||
|
||||
this._triggerChange(choice.value);
|
||||
this.clearInput(this.passedElement);
|
||||
|
||||
// We wont to close the dropdown if we are dealing with a single select box
|
||||
|
@ -1281,20 +1298,20 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var canAddItem = true;
|
||||
var notice = (0, _utils.isType)('Function', this.config.addItemText) ? this.config.addItemText(value) : this.config.addItemText;
|
||||
|
||||
if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'text') {
|
||||
if (this.config.maxItemCount > 0 && this.config.maxItemCount <= this.itemList.children.length) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
canAddItem = false;
|
||||
notice = (0, _utils.isType)('Function', this.config.maxItemText) ? this.config.maxItemText(this.config.maxItemCount) : this.config.maxItemText;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.passedElement.type === 'text' && this.config.addItems) {
|
||||
if (this.config.addItems) {
|
||||
var isUnique = !activeItems.some(function (item) {
|
||||
return item.value === value.trim();
|
||||
return item.value === value.trim() || item.label === value.trim();
|
||||
});
|
||||
|
||||
if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'text') {
|
||||
if (this.config.maxItemCount > 0 && this.config.maxItemCount <= this.itemList.children.length) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
canAddItem = false;
|
||||
notice = (0, _utils.isType)('Function', this.config.maxItemText) ? this.config.maxItemText(this.config.maxItemCount) : this.config.maxItemText;
|
||||
}
|
||||
}
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if (this.config.regexFilter) {
|
||||
// Determine whether we can update based on whether
|
||||
|
@ -1417,7 +1434,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
this.currentValue = newValue;
|
||||
this.highlightPosition = 0;
|
||||
this.isSearching = true;
|
||||
this.store.dispatch((0, _index3.filterChoices)(results));
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1441,10 +1459,26 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
if (this.input === document.activeElement) {
|
||||
// Check that we have a value to search and the input was an alphanumeric character
|
||||
if (value && value.length > this.config.searchFloor) {
|
||||
<<<<<<< HEAD
|
||||
// Check flag to filter search input
|
||||
if (this.config.searchChoices) {
|
||||
// Filter available choices
|
||||
this._searchChoices(value);
|
||||
=======
|
||||
// Filter available choices
|
||||
var results = this._searchChoices(value);
|
||||
if (results) {
|
||||
this.store.dispatch((0, _index3.filterChoices)(results));
|
||||
}
|
||||
|
||||
// Run callback if it is a function
|
||||
if (callback) {
|
||||
if ((0, _utils.isType)('Function', callback)) {
|
||||
callback.call(this, value);
|
||||
} else {
|
||||
console.error('callbackOnSearch: Callback is not a function');
|
||||
}
|
||||
>>>>>>> 291143b... Add dist files
|
||||
}
|
||||
// Trigger search event
|
||||
(0, _utils.triggerEvent)(this.passedElement, 'search', {
|
||||
|
@ -1588,26 +1622,112 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
};
|
||||
|
||||
var onEnterKey = function onEnterKey() {
|
||||
var highlighted = _this17.dropdown.querySelector('.' + _this17.config.classNames.highlightedState);
|
||||
|
||||
if (hasActiveDropdown && highlighted) {
|
||||
// If we have a highlighted choice, select it
|
||||
_this17._handleChoiceAction(activeItems, highlighted);
|
||||
} else if (passedElementType === 'select-one') {
|
||||
// Open single select dropdown if it's not active
|
||||
if (!hasActiveDropdown) {
|
||||
_this17.showDropdown(true);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// If enter key is pressed and the input has a value
|
||||
<<<<<<< HEAD
|
||||
if (passedElementType === 'text' && target.value) {
|
||||
var value = _this16.input.value;
|
||||
var canAddItem = _this16._canAddItem(activeItems, value);
|
||||
=======
|
||||
if (target.value) {
|
||||
<<<<<<< HEAD
|
||||
var value = _this17.input.value;
|
||||
var canAddItem = _this17._canAddItem(activeItems, value);
|
||||
>>>>>>> 291143b... Add dist files
|
||||
|
||||
// All is good, add
|
||||
if (canAddItem.response) {
|
||||
<<<<<<< HEAD
|
||||
if (hasActiveDropdown) {
|
||||
_this16.hideDropdown();
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
_this16._addItem(value);
|
||||
_this16._triggerChange(value);
|
||||
_this16.clearInput(_this16.passedElement);
|
||||
=======
|
||||
=======
|
||||
// Track whether we will end up adding an item
|
||||
var willAddItem = _this17.isTextElement || _this17.isSelectElement && _this17.config.addItems;
|
||||
>>>>>>> acb2451... Update dist files, after FF from main repo
|
||||
=======
|
||||
(function () {
|
||||
var value = _this17.input.value;
|
||||
var canAddItem = _this17._canAddItem(activeItems, value);
|
||||
|
||||
// All is good, add
|
||||
if (canAddItem.response) {
|
||||
// Track whether we will end up adding an item
|
||||
var willAddItem = _this17.isTextElement || _this17.isSelectElement && _this17.config.addItems;
|
||||
>>>>>>> c4dd94f... Update dist files
|
||||
|
||||
if (willAddItem) {
|
||||
if (hasActiveDropdown) {
|
||||
_this17.hideDropdown();
|
||||
}
|
||||
|
||||
if (_this17.isTextElement) {
|
||||
_this17._addItem(value);
|
||||
} else {
|
||||
var matchingChoices = [];
|
||||
var isUnique = void 0;
|
||||
var duplicateItems = _this17.config.duplicateItems;
|
||||
if (!duplicateItems) {
|
||||
matchingChoices = _this17.store.getChoices().filter(function (choice) {
|
||||
return choice.label === value.trim();
|
||||
});
|
||||
isUnique = !_this17.store.getItemsFilteredByActive().some(function (item) {
|
||||
return item.label === value.trim();
|
||||
});
|
||||
}
|
||||
if (duplicateItems || matchingChoices.length === 0 && isUnique) {
|
||||
_this17._addChoice(true, false, value, value);
|
||||
}
|
||||
if (duplicateItems || isUnique) {
|
||||
if (matchingChoices[0]) {
|
||||
_this17._addItem(matchingChoices[0].value, matchingChoices[0].label, matchingChoices[0].id);
|
||||
}
|
||||
}
|
||||
_this17.containerOuter.focus();
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
_this17._triggerChange(value);
|
||||
_this17.clearInput(_this17.passedElement);
|
||||
>>>>>>> 291143b... Add dist files
|
||||
=======
|
||||
_this17._triggerChange(value);
|
||||
_this17.clearInput(_this17.passedElement);
|
||||
}
|
||||
>>>>>>> acb2451... Update dist files, after FF from main repo
|
||||
}
|
||||
=======
|
||||
_this17._triggerChange(value);
|
||||
_this17.clearInput(_this17.passedElement);
|
||||
}
|
||||
}
|
||||
})();
|
||||
>>>>>>> c4dd94f... Update dist files
|
||||
}
|
||||
|
||||
if (target.hasAttribute('data-button')) {
|
||||
_this16._handleButtonAction(activeItems, target);
|
||||
e.preventDefault();
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
if (hasActiveDropdown) {
|
||||
e.preventDefault();
|
||||
|
@ -1624,6 +1744,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
=======
|
||||
>>>>>>> 291143b... Add dist files
|
||||
};
|
||||
|
||||
var onEscapeKey = function onEscapeKey() {
|
||||
|
@ -2493,7 +2615,10 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
}
|
||||
}
|
||||
|
||||
if (!this.config.addItems) this.disable();
|
||||
// Disable text input if no entry allowed
|
||||
if (!this.config.addItems && this.isTextElement) {
|
||||
this.disable();
|
||||
}
|
||||
|
||||
containerOuter.appendChild(containerInner);
|
||||
containerOuter.appendChild(dropdown);
|
||||
|
@ -4064,7 +4189,12 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
if (value == null) {
|
||||
return value === undefined ? undefinedTag : nullTag;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
return (symToStringTag && symToStringTag in Object(value))
|
||||
=======
|
||||
value = Object(value);
|
||||
return (symToStringTag && symToStringTag in value)
|
||||
>>>>>>> 291143b... Add dist files
|
||||
? getRawTag(value)
|
||||
: objectToString(value);
|
||||
}
|
||||
|
@ -4304,16 +4434,16 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
/* 18 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = function(module) {
|
||||
if(!module.webpackPolyfill) {
|
||||
module.deprecate = function() {};
|
||||
module.paths = [];
|
||||
// module.parent = undefined by default
|
||||
module.children = [];
|
||||
module.webpackPolyfill = 1;
|
||||
}
|
||||
return module;
|
||||
}
|
||||
module.exports = function(module) {
|
||||
if(!module.webpackPolyfill) {
|
||||
module.deprecate = function() {};
|
||||
module.paths = [];
|
||||
// module.parent = undefined by default
|
||||
module.children = [];
|
||||
module.webpackPolyfill = 1;
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
|
||||
/***/ },
|
||||
|
|
26
assets/scripts/dist/choices.js.map
vendored
26
assets/scripts/dist/choices.js.map
vendored
File diff suppressed because one or more lines are too long
28
assets/scripts/dist/choices.min.js
vendored
28
assets/scripts/dist/choices.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -116,18 +116,6 @@ class Choices {
|
|||
callbackOnCreateTemplates: null,
|
||||
};
|
||||
|
||||
// Merge options with user options
|
||||
this.config = extend(defaultConfig, userConfig);
|
||||
|
||||
// Create data store
|
||||
this.store = new Store(this.render);
|
||||
|
||||
// State tracking
|
||||
this.initialised = false;
|
||||
this.currentState = {};
|
||||
this.prevState = {};
|
||||
this.currentValue = '';
|
||||
|
||||
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
|
||||
this.element = element;
|
||||
this.passedElement = isType('String', element) ? document.querySelector(element) : element;
|
||||
|
@ -139,8 +127,14 @@ class Choices {
|
|||
return;
|
||||
}
|
||||
|
||||
this.highlightPosition = 0;
|
||||
this.canSearch = this.config.search;
|
||||
// It only makes sense for addItems to be true for
|
||||
// text inputs by default
|
||||
if (this.isSelectElement) {
|
||||
defaultConfig.addItems = false;
|
||||
}
|
||||
|
||||
// Merge options with user options
|
||||
this.config = extend(defaultConfig, userConfig);
|
||||
|
||||
// Assing preset choices from passed object
|
||||
this.presetChoices = this.config.choices;
|
||||
|
@ -172,7 +166,16 @@ class Choices {
|
|||
this._onPaste = this._onPaste.bind(this);
|
||||
this._onInput = this._onInput.bind(this);
|
||||
|
||||
// Monitor touch taps/scrolls
|
||||
// Create data store
|
||||
this.store = new Store(this.render);
|
||||
|
||||
// State tracking
|
||||
this.initialised = false;
|
||||
this.currentState = {};
|
||||
this.prevState = {};
|
||||
this.currentValue = '';
|
||||
this.highlightPosition = 0;
|
||||
this.canSearch = this.config.search;
|
||||
this.wasTap = true;
|
||||
|
||||
// Cutting the mustard
|
||||
|
@ -385,8 +388,7 @@ class Choices {
|
|||
// Choices
|
||||
if (this.currentState.choices !== this.prevState.choices ||
|
||||
this.currentState.groups !== this.prevState.groups) {
|
||||
if (this.passedElement.type === 'select-multiple' ||
|
||||
this.passedElement.type === 'select-one') {
|
||||
if (!this.isTextElement) {
|
||||
// Get active groups/choices
|
||||
const activeGroups = this.store.getGroupsFilteredByActive();
|
||||
const activeChoices = this.store.getChoicesFilteredByActive();
|
||||
|
@ -412,18 +414,15 @@ class Choices {
|
|||
// If we actually have anything to add to our dropdown
|
||||
// append it and highlight the first choice
|
||||
this.choiceList.appendChild(choiceListFragment);
|
||||
this._highlightChoice();
|
||||
} else {
|
||||
// Otherwise show a notice
|
||||
let dropdownItem;
|
||||
let notice;
|
||||
const activeItems = this.store.getItemsFilteredByActive();
|
||||
const canAddItem = this._canAddItem(activeItems, this.input.value);
|
||||
let dropdownItem = this._getTemplate('notice', this.config.noChoicesText);
|
||||
|
||||
if (this.isSearching) {
|
||||
notice = isType('Function', this.config.noResultsText) ? this.config.noResultsText() : this.config.noResultsText;
|
||||
dropdownItem = this._getTemplate('notice', notice);
|
||||
} else {
|
||||
notice = isType('Function', this.config.noChoicesText) ? this.config.noChoicesText() : this.config.noChoicesText;
|
||||
dropdownItem = this._getTemplate('notice', notice);
|
||||
if (this.config.addItems && canAddItem.notice) {
|
||||
dropdownItem = this._getTemplate('notice', canAddItem.notice);
|
||||
} else if (this.isSearching) {
|
||||
dropdownItem = this._getTemplate('notice', this.config.noResultsText);
|
||||
}
|
||||
|
||||
this.choiceList.appendChild(dropdownItem);
|
||||
|
@ -1033,10 +1032,10 @@ class Choices {
|
|||
|
||||
if (canAddItem.response) {
|
||||
this._addItem(choice.value, choice.label, choice.id, choice.groupId);
|
||||
this._triggerChange(choice.value);
|
||||
}
|
||||
}
|
||||
|
||||
this._triggerChange(choice.value);
|
||||
this.clearInput(this.passedElement);
|
||||
|
||||
// We wont to close the dropdown if we are dealing with a single select box
|
||||
|
@ -1084,17 +1083,17 @@ class Choices {
|
|||
let canAddItem = true;
|
||||
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.config.maxItemCount > 0 && this.config.maxItemCount <= this.itemList.children.length) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
canAddItem = false;
|
||||
notice = isType('Function', this.config.maxItemText) ? this.config.maxItemText(this.config.maxItemCount) : this.config.maxItemText;
|
||||
}
|
||||
}
|
||||
if (this.config.addItems) {
|
||||
const isUnique = !activeItems.some((item) => (item.value === value.trim()) || (item.label === value.trim()));
|
||||
|
||||
if (this.passedElement.type === 'text' && this.config.addItems) {
|
||||
const isUnique = !activeItems.some((item) => item.value === value.trim());
|
||||
if (this.passedElement.type === 'select-multiple' || this.passedElement.type === 'text') {
|
||||
if (this.config.maxItemCount > 0 && this.config.maxItemCount <= this.itemList.children.length) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
canAddItem = false;
|
||||
notice = isType('Function', this.config.maxItemText) ? this.config.maxItemText(this.config.maxItemCount) : this.config.maxItemText;
|
||||
}
|
||||
}
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if (this.config.regexFilter) {
|
||||
|
@ -1205,7 +1204,8 @@ class Choices {
|
|||
this.currentValue = newValue;
|
||||
this.highlightPosition = 0;
|
||||
this.isSearching = true;
|
||||
this.store.dispatch(filterChoices(results));
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1227,10 @@ class Choices {
|
|||
// Check flag to filter search input
|
||||
if (this.config.searchChoices) {
|
||||
// Filter available choices
|
||||
this._searchChoices(value);
|
||||
const results = this._searchChoices(value);
|
||||
if (results) {
|
||||
this.store.dispatch(filterChoices(results));
|
||||
}
|
||||
}
|
||||
// Trigger search event
|
||||
triggerEvent(this.passedElement, 'search', {
|
||||
|
@ -1357,19 +1360,66 @@ class Choices {
|
|||
};
|
||||
|
||||
const onEnterKey = () => {
|
||||
const highlighted = this.dropdown.querySelector(`.${this.config.classNames.highlightedState}`);
|
||||
|
||||
if (hasActiveDropdown && highlighted) {
|
||||
// If we have a highlighted choice, select it
|
||||
this._handleChoiceAction(activeItems, highlighted);
|
||||
} else if (passedElementType === 'select-one') {
|
||||
// Open single select dropdown if it's not active
|
||||
if (!hasActiveDropdown) {
|
||||
this.showDropdown(true);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// If enter key is pressed and the input has a value
|
||||
if (passedElementType === 'text' && target.value) {
|
||||
if (target.value) {
|
||||
const value = this.input.value;
|
||||
const canAddItem = this._canAddItem(activeItems, value);
|
||||
|
||||
// All is good, add
|
||||
if (canAddItem.response) {
|
||||
if (hasActiveDropdown) {
|
||||
this.hideDropdown();
|
||||
// Track whether we will end up adding an item
|
||||
const willAddItem = this.isTextElement || (this.isSelectElement && this.config.addItems);
|
||||
|
||||
if (willAddItem) {
|
||||
if (hasActiveDropdown) {
|
||||
this.hideDropdown();
|
||||
}
|
||||
|
||||
if (this.isTextElement) {
|
||||
this._addItem(value);
|
||||
} else {
|
||||
let matchingChoices = [];
|
||||
let isUnique;
|
||||
const duplicateItems = this.config.duplicateItems;
|
||||
if (!duplicateItems) {
|
||||
matchingChoices = this.store
|
||||
.getChoices()
|
||||
.filter((choice) => choice.label === value.trim());
|
||||
isUnique = !this.store
|
||||
.getItemsFilteredByActive()
|
||||
.some((item) => item.label === value.trim());
|
||||
}
|
||||
if (duplicateItems || (matchingChoices.length === 0 && isUnique)) {
|
||||
this._addChoice(true, false, value, value);
|
||||
}
|
||||
if (duplicateItems || isUnique) {
|
||||
if (matchingChoices[0]) {
|
||||
this._addItem(
|
||||
matchingChoices[0].value,
|
||||
matchingChoices[0].label,
|
||||
matchingChoices[0].id
|
||||
);
|
||||
}
|
||||
}
|
||||
this.containerOuter.focus();
|
||||
}
|
||||
|
||||
this._triggerChange(value);
|
||||
this.clearInput(this.passedElement);
|
||||
}
|
||||
this._addItem(value);
|
||||
this._triggerChange(value);
|
||||
this.clearInput(this.passedElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2214,7 +2264,10 @@ class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
if (!this.config.addItems) this.disable();
|
||||
// Disable text input if no entry allowed
|
||||
if (!this.config.addItems && this.isTextElement) {
|
||||
this.disable();
|
||||
}
|
||||
|
||||
containerOuter.appendChild(containerInner);
|
||||
containerOuter.appendChild(dropdown);
|
||||
|
|
46
index.html
46
index.html
|
@ -141,11 +141,19 @@
|
|||
<p id="message"></p>
|
||||
<select id="choices-multiple-labels" multiple></select>
|
||||
|
||||
<label for="choices-multiple-add-items">Add items if they don't exist</label>
|
||||
<select class="form-control" name="choices-multiple-add-items" id="choices-multiple-add-items" placeholder="This is a placeholder" multiple>
|
||||
<option value="React">England</option>
|
||||
<option value="React">Wales</option>
|
||||
<option value="React">Scotland</option>
|
||||
<option value="React">Northern Ireland</option>
|
||||
</select>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Single select input</h2>
|
||||
<label for="choices-single-default">Default</label>
|
||||
<select class="form-control" data-trigger name="choices-single-default" id="choices-single-default" placeholder="This is a search placeholder">
|
||||
<label for="choices-single-placeholder">Default</label>
|
||||
<select class="form-control" data-trigger name="choices-single-placeholder" id="choices-single-placeholder" placeholder="This is a search placeholder">
|
||||
<option selected disabled>This is a placeholder</option>
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
|
@ -242,6 +250,14 @@
|
|||
<option value="Vue">Vue</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-single-add-items">Add items if they don't exist</label>
|
||||
<select class="form-control" name="choices-single-add-items" id="choices-single-add-items" placeholder="This is a placeholder">
|
||||
<option value="React">England</option>
|
||||
<option value="React">Wales</option>
|
||||
<option value="React">Scotland</option>
|
||||
<option value="React">Northern Ireland</option>
|
||||
</select>
|
||||
|
||||
<p>Below is an example of how you could have two select inputs depend on eachother. 'Boroughs' will only be enabled if the value of 'States' is 'New York'</p>
|
||||
<label for="states">States</label>
|
||||
<select class="form-control" name="states" id="states" placeholder="Choose a state">
|
||||
|
@ -355,6 +371,13 @@
|
|||
document.getElementById('message').innerHTML = 'You just removed "' + event.detail.label + '"';
|
||||
});
|
||||
|
||||
var multipleAddItems = new Choices('#choices-multiple-add-items', {
|
||||
addItems: true,
|
||||
duplicateItems: false,
|
||||
});
|
||||
|
||||
var multipleAddItems = new Choices('#choices-single-placeholder');
|
||||
|
||||
var singleFetch = new Choices('#choices-single-remote-fetch', {
|
||||
placeholder: true,
|
||||
placeholderValue: 'Pick an Arctic Monkeys record'
|
||||
|
@ -444,6 +467,10 @@
|
|||
|
||||
var singleNoSorting = new Choices('#choices-single-no-sorting', {
|
||||
shouldSort: false,
|
||||
addItems: true,
|
||||
callbackOnChange: function(a, b) {
|
||||
console.log(this.currentState);
|
||||
}
|
||||
});
|
||||
|
||||
var states = new Choices(document.getElementById('states'));
|
||||
|
@ -456,6 +483,11 @@
|
|||
}
|
||||
});
|
||||
|
||||
var singleAddItems = new Choices('#choices-single-add-items', {
|
||||
addItems: true,
|
||||
duplicateItems: false,
|
||||
});
|
||||
|
||||
var customTemplates = new Choices(document.getElementById('choices-single-custom-templates'), {
|
||||
callbackOnCreateTemplates: function (strToEl) {
|
||||
var classNames = this.config.classNames;
|
||||
|
@ -494,6 +526,16 @@
|
|||
}
|
||||
});
|
||||
|
||||
var states = new Choices(document.getElementById('states'), {
|
||||
callbackOnChange: function(value) {
|
||||
if(value === 'New York') {
|
||||
boroughs.enable();
|
||||
} else {
|
||||
boroughs.disable();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var boroughs = new Choices(document.getElementById('boroughs')).disable();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -284,7 +284,7 @@ describe('Choices', () => {
|
|||
this.choices = new Choices(this.input);
|
||||
this.choices.input.focus();
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
// Key down to third choice
|
||||
this.choices._onKeyDown({
|
||||
target: this.choices.input,
|
||||
|
@ -317,7 +317,7 @@ describe('Choices', () => {
|
|||
preventDefault: () => {}
|
||||
});
|
||||
|
||||
expect(this.choices.currentState.items.length).toBe(2);
|
||||
expect(this.choices.currentState.items.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should trigger add/change event on selection', function() {
|
||||
|
@ -333,12 +333,16 @@ describe('Choices', () => {
|
|||
this.choices.input.focus();
|
||||
|
||||
// Key down to second choice
|
||||
this.choices._onKeyDown({
|
||||
target: this.choices.input,
|
||||
keyCode: 40,
|
||||
ctrlKey: false,
|
||||
preventDefault: () => {}
|
||||
});
|
||||
let count = 0;
|
||||
while (count < 2) {
|
||||
this.choices._onKeyDown({
|
||||
target: this.choices.input,
|
||||
keyCode: 40,
|
||||
ctrlKey: false,
|
||||
preventDefault: () => {}
|
||||
});
|
||||
count++;
|
||||
}
|
||||
|
||||
// Key down to select choice
|
||||
this.choices._onKeyDown({
|
||||
|
|
Loading…
Reference in a new issue