mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-21 15:06:45 +02:00
Populate options from ajax api
This commit is contained in:
parent
57ad1dc31c
commit
ec8c324383
4
assets/scripts/dist/choices.min.js
vendored
4
assets/scripts/dist/choices.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -69,10 +69,9 @@ export class Choices {
|
|||
flippedState: 'is-flipped',
|
||||
selectedState: 'is-selected'
|
||||
},
|
||||
callbackOnInit: function() {},
|
||||
callbackOnRender: function() {},
|
||||
callbackOnRemoveItem: function() {},
|
||||
callbackOnAddItem: function() {}
|
||||
callbackOnInit: () => {},
|
||||
callbackOnRemoveItem: () => {},
|
||||
callbackOnAddItem: () => {}
|
||||
};
|
||||
|
||||
// Merge options with user options
|
||||
|
@ -82,6 +81,7 @@ export class Choices {
|
|||
this.store = new Store(this.render);
|
||||
|
||||
// State tracking
|
||||
this.initialised = false;
|
||||
this.currentState = {};
|
||||
this.prevState = {};
|
||||
|
||||
|
@ -102,6 +102,7 @@ export class Choices {
|
|||
this.init = this.init.bind(this);
|
||||
this.render = this.render.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this.disable = this.disable.bind(this);
|
||||
|
||||
// Bind event handlers
|
||||
this.onFocus = this.onFocus.bind(this);
|
||||
|
@ -137,39 +138,35 @@ export class Choices {
|
|||
handleEnter(activeItems, value) {
|
||||
let canUpdate = true;
|
||||
|
||||
if(this.passedElement.type === 'text') {
|
||||
if(this.options.addItems) {
|
||||
if (this.options.maxItems && this.options.maxItems <= this.list.children.length) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
canUpdate = false;
|
||||
} else if(this.options.allowDuplicates === false && this.passedElement.value) {
|
||||
// If no duplicates are allowed, and the value already exists
|
||||
// in the array, don't update
|
||||
canUpdate = !activeItems.some((item) => {
|
||||
return item.value === value;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if(this.options.addItems) {
|
||||
if (this.options.maxItems && this.options.maxItems <= this.list.children.length) {
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
canUpdate = false;
|
||||
} else if(this.options.allowDuplicates === false && this.passedElement.value) {
|
||||
// If no duplicates are allowed, and the value already exists
|
||||
// in the array, don't update
|
||||
canUpdate = !activeItems.some((item) => item.value === value );
|
||||
}
|
||||
} else {
|
||||
canUpdate = false;
|
||||
}
|
||||
|
||||
if (canUpdate) {
|
||||
let canAddItem = true;
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if(this.options.regexFilter) {
|
||||
// Determine whether we can update based on whether
|
||||
// our regular expression passes
|
||||
canAddItem = this.regexFilter(value);
|
||||
}
|
||||
|
||||
if (canUpdate) {
|
||||
let canAddItem = true;
|
||||
|
||||
// If a user has supplied a regular expression filter
|
||||
if(this.options.regexFilter) {
|
||||
// Determine whether we can update based on whether
|
||||
// our regular expression passes
|
||||
canAddItem = this.regexFilter(value);
|
||||
}
|
||||
|
||||
// All is good, add
|
||||
if(canAddItem) {
|
||||
this.toggleDropdown();
|
||||
this.addItem(value);
|
||||
this.clearInput(this.passedElement);
|
||||
}
|
||||
|
||||
// All is good, add
|
||||
if(canAddItem) {
|
||||
this.toggleDropdown();
|
||||
this.addItem(value);
|
||||
this.clearInput(this.passedElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -226,7 +223,7 @@ export class Choices {
|
|||
|
||||
// If a user is typing and the dropdown is not active
|
||||
if(this.passedElement.type !== 'text' && /[a-zA-Z0-9-_ ]/.test(keyString) && !hasActiveDropdown) {
|
||||
this.toggleDropdown();
|
||||
this.showDropdown();
|
||||
}
|
||||
|
||||
switch (e.keyCode) {
|
||||
|
@ -240,13 +237,17 @@ export class Choices {
|
|||
break;
|
||||
|
||||
case enterKey:
|
||||
if(this.passedElement.type === 'select-one') {
|
||||
this.toggleDropdown();
|
||||
}
|
||||
|
||||
// If enter key is pressed and the input has a value
|
||||
if(e.target.value && this.passedElement.type === 'text') {
|
||||
const value = this.input.value;
|
||||
this.handleEnter(activeItems, value);
|
||||
}
|
||||
|
||||
if(this.dropdown && hasActiveDropdown) {
|
||||
if(hasActiveDropdown) {
|
||||
const highlighted = this.dropdown.querySelector(`.${this.options.classNames.highlightedState}`);
|
||||
|
||||
if(highlighted) {
|
||||
|
@ -260,7 +261,7 @@ export class Choices {
|
|||
break;
|
||||
|
||||
case escapeKey:
|
||||
if(this.dropdown && hasActiveDropdown) {
|
||||
if(hasActiveDropdown) {
|
||||
this.toggleDropdown();
|
||||
}
|
||||
break;
|
||||
|
@ -268,7 +269,7 @@ export class Choices {
|
|||
case downKey:
|
||||
case upKey:
|
||||
// If up or down key is pressed, traverse through options
|
||||
if(this.dropdown && hasActiveDropdown) {
|
||||
if(hasActiveDropdown) {
|
||||
const currentEl = this.dropdown.querySelector(`.${this.options.classNames.highlightedState}`);
|
||||
const directionInt = e.keyCode === downKey ? 1 : -1;
|
||||
let nextEl;
|
||||
|
@ -321,7 +322,7 @@ export class Choices {
|
|||
if (this.options.maxItems && this.options.maxItems <= this.list.children.length) {
|
||||
dropdownItem = this.getTemplate('notice', `Only ${ this.options.maxItems } options can be selected.`);
|
||||
} else {
|
||||
dropdownItem = this.getTemplate('notice', `Add "${ this.input.value }"`);
|
||||
dropdownItem = this.getTemplate('notice', `Add "${ this.input.value }"`);
|
||||
}
|
||||
|
||||
this.dropdown.innerHTML = dropdownItem.outerHTML;
|
||||
|
@ -335,16 +336,14 @@ export class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
if(this.dropdown && this.options.allowSearch) {
|
||||
if(this.options.allowSearch) {
|
||||
if(this.input === document.activeElement) {
|
||||
const options = this.store.getOptions();
|
||||
const hasUnactiveOptions = options.some((option) => {
|
||||
return option.active !== true;
|
||||
});
|
||||
const hasUnactiveOptions = options.some((option) => option.active !== true);
|
||||
|
||||
// Check that have a value to search
|
||||
if(this.input.value && options.length) {
|
||||
const handleFilter = debounce(() => {
|
||||
const handleFilter = () => {
|
||||
// Ensure value *still* has a value after 500 delay
|
||||
if(this.input.value && this.input.value.length >= 1) {
|
||||
const haystack = this.store.getOptionsFiltedBySelectable();
|
||||
|
@ -361,7 +360,8 @@ export class Choices {
|
|||
this.isSearching = true;
|
||||
this.store.dispatch(filterOptions(results));
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
handleFilter();
|
||||
} else if(hasUnactiveOptions) {
|
||||
// Otherwise reset options to active
|
||||
|
@ -414,9 +414,7 @@ export class Choices {
|
|||
// If we are clicking on an option
|
||||
const options = this.store.getOptionsFilteredByActive();
|
||||
const id = e.target.getAttribute('data-id');
|
||||
const option = options.find((option) => {
|
||||
return option.id === parseInt(id);
|
||||
});
|
||||
const option = options.find((option) => option.id === parseInt(id));
|
||||
|
||||
if(!option.selected && !option.disabled) {
|
||||
this.addItem(option.value, option.label, option.id);
|
||||
|
@ -428,9 +426,7 @@ export class Choices {
|
|||
|
||||
} else {
|
||||
// Click is outside of our element so close dropdown and de-select items
|
||||
const hasSelectedItems = activeItems.some((item) => {
|
||||
return item.selected === true;
|
||||
});
|
||||
const hasSelectedItems = activeItems.some((item) => item.selected === true);
|
||||
|
||||
if(hasSelectedItems) {
|
||||
this.deselectAll();
|
||||
|
@ -478,8 +474,12 @@ export class Choices {
|
|||
* @return
|
||||
*/
|
||||
onFocus(e) {
|
||||
if(!this.containerOuter.classList.contains(this.options.classNames.activeState)) {
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
if(e.target === this.input && !hasActiveDropdown) {
|
||||
this.containerOuter.classList.add(this.options.classNames.focusState);
|
||||
if(this.passedElement.type === 'select-one' || this.passedElement.type === 'select-multiple'){
|
||||
this.showDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,8 +490,10 @@ export class Choices {
|
|||
*/
|
||||
onBlur(e) {
|
||||
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||
if(!hasActiveDropdown) {
|
||||
if(e.target === this.input && !hasActiveDropdown) {
|
||||
this.containerOuter.classList.remove(this.options.classNames.focusState);
|
||||
} else {
|
||||
this.hideDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,9 +512,7 @@ export class Choices {
|
|||
*/
|
||||
regexFilter(value) {
|
||||
const expression = new RegExp(this.options.regexFilter, 'i');
|
||||
const passesTest = expression.test(value);
|
||||
|
||||
return passesTest;
|
||||
return expression.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -691,7 +691,7 @@ export class Choices {
|
|||
// Run callback if it is a function
|
||||
if(callback){
|
||||
if(isType('Function', callback)) {
|
||||
callback(id, value);
|
||||
callback(id, passedValue, this.passedElement);
|
||||
} else {
|
||||
console.error('callbackOnAddItem: Callback is not a function');
|
||||
}
|
||||
|
@ -717,7 +717,7 @@ export class Choices {
|
|||
// Run callback
|
||||
if(callback){
|
||||
if(!isType('Function', callback)) console.error('callbackOnRemoveItem: Callback is not a function'); return;
|
||||
callback(value);
|
||||
callback(id, value, this.passedElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,6 +769,47 @@ export class Choices {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add option to dropdown
|
||||
* @param {Object} option Option to add
|
||||
* @param {Number} groupId ID of the options group
|
||||
* @return
|
||||
*/
|
||||
addOption(option, value, label, groupId = -1) {
|
||||
// Generate unique id
|
||||
const options = this.store.getOptions();
|
||||
const id = options.length + 1;
|
||||
const isDisabled = option && (option.disabled || option.parentNode.disabled);
|
||||
|
||||
this.store.dispatch(addOption(value, label, id, groupId, isDisabled));
|
||||
|
||||
if(option && option.selected && !isDisabled) {
|
||||
this.addItem(value, label, id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add group to dropdown
|
||||
* @param {Object} group Group to add
|
||||
* @param {Number} index Whether this is the first group to add
|
||||
*/
|
||||
addGroup(group, id, isFirst) {
|
||||
const groupOptions = Array.from(group.getElementsByTagName('OPTION'));
|
||||
const groupId = id;
|
||||
|
||||
if(groupOptions) {
|
||||
this.store.dispatch(addGroup(group.label, groupId, true, group.disabled));
|
||||
|
||||
groupOptions.forEach((option, optionIndex) => {
|
||||
// We want to pre-highlight the first option
|
||||
const highlighted = isFirst && optionIndex === 0 ? true : false;
|
||||
this.addOption(option, option.value, option.innerHTML, groupId);
|
||||
});
|
||||
} else {
|
||||
this.store.dispatch(addGroup(group.label, group.id, false, group.disabled));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show dropdown to user by adding active state class
|
||||
* @return
|
||||
|
@ -818,49 +859,37 @@ export class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add option to dropdown
|
||||
* @param {Object} option Option to add
|
||||
* @param {Number} groupId ID of the options group
|
||||
* @return
|
||||
/**
|
||||
* Disable
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
addOption(option, groupId = -1) {
|
||||
// Generate unique id
|
||||
const options = this.store.getOptions();
|
||||
const id = options.length + 1;
|
||||
const value = option.value;
|
||||
const label = option.innerHTML;
|
||||
const isDisabled = option.disabled || option.parentNode.disabled;
|
||||
|
||||
this.store.dispatch(addOption(value, label, id, groupId, isDisabled));
|
||||
|
||||
if(option.selected && !isDisabled) {
|
||||
this.addItem(value, label, id);
|
||||
disable() {
|
||||
this.passedElement.disabled = true;
|
||||
if(this.initialised) {
|
||||
this.input.disabled = true;
|
||||
this.containerOuter.classList.add(this.options.classNames.disabledState);
|
||||
}
|
||||
}
|
||||
|
||||
ajax(fn) {
|
||||
const callback = (results, title, label) => {
|
||||
if(results && results.length) {
|
||||
results.forEach((result) => {
|
||||
// Add each result to option dropdown
|
||||
this.addOption(null, result[title], result[label]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
fn(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add group to dropdown
|
||||
* @param {Object} group Group to add
|
||||
* @param {Number} index Whether this is the first group to add
|
||||
* Get template from name
|
||||
* @param {String} template Name of template to get
|
||||
* @param {...} args Data to pass to template
|
||||
* @return {HTMLElement} Template
|
||||
*/
|
||||
addGroup(group, id, isFirst) {
|
||||
const groupOptions = Array.from(group.getElementsByTagName('OPTION'));
|
||||
const groupId = id;
|
||||
|
||||
if(groupOptions) {
|
||||
this.store.dispatch(addGroup(group.label, groupId, true, group.disabled));
|
||||
|
||||
groupOptions.forEach((option, optionIndex) => {
|
||||
// We want to pre-highlight the first option
|
||||
const highlighted = isFirst && optionIndex === 0 ? true : false;
|
||||
this.addOption(option, groupId);
|
||||
});
|
||||
} else {
|
||||
this.store.dispatch(addGroup(group.label, group.id, false, group.disabled));
|
||||
}
|
||||
}
|
||||
|
||||
getTemplate(template, ...args) {
|
||||
if(!template) return;
|
||||
const templates = this.options.templates;
|
||||
|
@ -869,9 +898,7 @@ export class Choices {
|
|||
|
||||
/**
|
||||
* Create HTML element based on type and arguments
|
||||
* @param {String} template Template to create
|
||||
* @param {...} args Data
|
||||
* @return {HTMLElement}
|
||||
* @return
|
||||
*/
|
||||
createTemplates() {
|
||||
const classNames = this.options.classNames;
|
||||
|
@ -931,11 +958,18 @@ export class Choices {
|
|||
const input = this.getTemplate('input');
|
||||
const dropdown = this.getTemplate('dropdown');
|
||||
|
||||
this.containerOuter = containerOuter;
|
||||
this.containerInner = containerInner;
|
||||
this.input = input;
|
||||
this.list = list;
|
||||
this.dropdown = dropdown;
|
||||
|
||||
// Hide passed input
|
||||
this.passedElement.classList.add(this.options.classNames.input, this.options.classNames.hiddenState);
|
||||
this.passedElement.tabIndex = '-1';
|
||||
this.passedElement.setAttribute('style', 'display:none;');
|
||||
this.passedElement.setAttribute('aria-hidden', 'true');
|
||||
this.passedElement.removeAttribute('data-choice');
|
||||
|
||||
// Wrap input in container preserving DOM ordering
|
||||
wrap(this.passedElement, containerInner);
|
||||
|
@ -944,14 +978,13 @@ export class Choices {
|
|||
wrap(containerInner, containerOuter);
|
||||
|
||||
// If placeholder has been enabled and we have a value
|
||||
if (this.options.placeholder && this.options.placeholderValue && this.passedElement.type !== 'select-one') {
|
||||
if (this.options.placeholder && this.options.placeholderValue) {
|
||||
input.placeholder = this.options.placeholderValue;
|
||||
input.style.width = getWidthOfInput(input);
|
||||
}
|
||||
|
||||
if(!this.options.addItems) {
|
||||
input.disabled = true;
|
||||
containerOuter.classList.add(this.options.classNames.disabledState);
|
||||
this.disable();
|
||||
}
|
||||
|
||||
containerOuter.appendChild(containerInner);
|
||||
|
@ -974,24 +1007,16 @@ export class Choices {
|
|||
} else {
|
||||
const passedOptions = Array.from(this.passedElement.options);
|
||||
passedOptions.forEach((option) => {
|
||||
this.addOption(option);
|
||||
this.addOption(option, option.value, option.innerHTML);
|
||||
});
|
||||
}
|
||||
|
||||
} else if(this.passedElement.type === 'select-one') {
|
||||
console.log('select element');
|
||||
} else if(this.passedElement.type === 'text') {
|
||||
// Add any preset values seperated by delimiter
|
||||
this.presetItems.forEach((value) => {
|
||||
this.addItem(value);
|
||||
});
|
||||
}
|
||||
|
||||
this.containerOuter = containerOuter;
|
||||
this.containerInner = containerInner;
|
||||
this.input = input;
|
||||
this.list = list;
|
||||
this.dropdown = dropdown;
|
||||
}
|
||||
|
||||
renderGroups(groups, options, fragment) {
|
||||
|
@ -1006,7 +1031,11 @@ export class Choices {
|
|||
|
||||
groupOptions.forEach((option, j) => {
|
||||
const dropdownItem = this.getTemplate('option', option);
|
||||
dropdownGroup.appendChild(dropdownItem);
|
||||
if(this.passedElement.type === 'select-one') {
|
||||
dropdownGroup.appendChild(dropdownItem);
|
||||
} else if(!option.selected) {
|
||||
dropdownGroup.appendChild(dropdownItem);
|
||||
}
|
||||
});
|
||||
|
||||
fragment.appendChild(dropdownGroup);
|
||||
|
@ -1027,7 +1056,7 @@ export class Choices {
|
|||
|
||||
renderItems(items, fragment) {
|
||||
// Simplify store data to just values
|
||||
const itemsFiltered = this.store.getItemsReducedToValues();
|
||||
const itemsFiltered = this.store.getItemsReducedToValues(items);
|
||||
|
||||
// Assign hidden input array of values
|
||||
this.passedElement.value = itemsFiltered.join(this.options.delimiter);
|
||||
|
@ -1143,6 +1172,8 @@ export class Choices {
|
|||
* @return
|
||||
*/
|
||||
init(callback = this.options.callbackOnInit) {
|
||||
this.initialised = true;
|
||||
|
||||
// Create required elements
|
||||
this.createTemplates();
|
||||
|
||||
|
@ -1176,6 +1207,7 @@ export class Choices {
|
|||
this.passedElement.tabIndex = '';
|
||||
this.passedElement.removeAttribute('style', 'display:none;');
|
||||
this.passedElement.removeAttribute('aria-hidden');
|
||||
this.passedElement.addAttribute('data-choice');
|
||||
|
||||
this.containerOuter.outerHTML = this.passedElement.outerHTML;
|
||||
|
||||
|
|
|
@ -65,9 +65,7 @@ export class Store {
|
|||
* Get items from store reduced to just their values
|
||||
* @return {Array} Item objects
|
||||
*/
|
||||
getItemsReducedToValues() {
|
||||
const items = this.getItems();
|
||||
|
||||
getItemsReducedToValues(items = this.getItems()) {
|
||||
const values = items.reduce((prev, current) => {
|
||||
prev.push(current.value);
|
||||
return prev;
|
||||
|
|
|
@ -40,6 +40,31 @@ h1, h2, h3, h4, h5, h6 {
|
|||
.choices {
|
||||
margin-bottom: 2.4rem;
|
||||
position: relative; }
|
||||
.choices.is-disabled .choices__inner, .choices.is-disabled .choices__input {
|
||||
background-color: #eaeaea;
|
||||
cursor: not-allowed;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; }
|
||||
.choices.is-disabled .choices__item {
|
||||
cursor: not-allowed; }
|
||||
|
||||
.choices[data-type*="select-one"].is-open:after {
|
||||
border-color: transparent transparent #b7b7b7 transparent;
|
||||
margin-top: -7.5px; }
|
||||
|
||||
.choices[data-type*="select-one"]:after {
|
||||
content: "";
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-style: solid;
|
||||
border-color: #b7b7b7 transparent transparent transparent;
|
||||
border-width: 5px;
|
||||
position: absolute;
|
||||
right: 1.15rem;
|
||||
top: 50%;
|
||||
margin-top: -2.5px; }
|
||||
|
||||
.choices__inner {
|
||||
background-color: #f9f9f9;
|
||||
|
@ -78,11 +103,14 @@ h1, h2, h3, h4, h5, h6 {
|
|||
margin-right: .375rem;
|
||||
margin-bottom: .375rem;
|
||||
background-color: #00BCD4;
|
||||
border: 1px solid #00b1c7;
|
||||
border: 1px solid #00a5bb;
|
||||
color: #FFFFFF;
|
||||
word-break: break-all; }
|
||||
.choices__list--multiple .choices__item.is-selected {
|
||||
background-color: #00a5bb; }
|
||||
.is-disabled .choices__list--multiple .choices__item {
|
||||
background-color: #b7b7b7;
|
||||
border: 1px solid #aaaaaa; }
|
||||
|
||||
.choices__list--dropdown {
|
||||
display: none;
|
||||
|
@ -98,6 +126,8 @@ h1, h2, h3, h4, h5, h6 {
|
|||
max-height: 300px;
|
||||
overflow: auto;
|
||||
will-change: scroll-position; }
|
||||
.choices__list--dropdown.is-active {
|
||||
display: block; }
|
||||
.choices__list--dropdown .choices__item {
|
||||
padding: 1rem;
|
||||
font-size: 1.4rem; }
|
||||
|
@ -116,8 +146,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||
opacity: .5; }
|
||||
.is-open .choices__list--dropdown {
|
||||
border-color: #b7b7b7; }
|
||||
.choices__list--dropdown.is-active {
|
||||
display: block; }
|
||||
.is-flipped .choices__list--dropdown {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
|
|
2
assets/styles/css/choices.min.css
vendored
2
assets/styles/css/choices.min.css
vendored
|
@ -1 +1 @@
|
|||
*,:after,:before{box-sizing:border-box}body,html{margin:0;height:100%;widows:100%}html{font-size:62.5%}body{background-color:#333;font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:1.6rem;color:#fff}label{display:block;margin-bottom:.8rem;font-size:1.4rem;font-weight:500}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:1.2rem;font-weight:500}.container{display:block;margin:auto;max-width:35em;padding:2.4rem}.section{background-color:#fff;padding:2.4rem;color:#333}.choices{margin-bottom:2.4rem;position:relative}.choices__inner{background-color:#f9f9f9;padding:.75rem .75rem .375rem;border:1px solid #ddd;border-radius:.25rem;font-size:1.4rem;cursor:text;overflow:hidden}.choices__inner:focus{outline:1px solid #00bcd4;outline-offset:-1px}.is-focused .choices__inner{border-color:#b7b7b7}.is-open .choices__inner{border-radius:.25rem .25rem 0 0}.is-flipped.is-open .choices__inner{border-radius:0 0 .25rem .25rem}.choices__list{margin:0;padding-left:0;list-style-type:none}.choices__list--single{display:inline-block;padding:.4rem}.choices__list--multiple{display:inline}.choices__list--multiple .choices__item{display:inline-block;border-radius:2rem;padding:.4rem 1rem;font-size:1.2rem;margin-right:.375rem;margin-bottom:.375rem;background-color:#00bcd4;border:1px solid #00b1c7;color:#fff;word-break:break-all}.choices__list--multiple .choices__item.is-selected{background-color:#00a5bb}.choices__list--dropdown{display:none;z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;max-height:300px;overflow:auto;will-change:scroll-position}.choices__list--dropdown .choices__item{padding:1rem;font-size:1.4rem}.choices__list--dropdown .choices__item--selectable.is-highlighted:after,.choices__list--dropdown .choices__item.is-selected{opacity:.5}.choices__list--dropdown .choices__item.is-selected:hover{background-color:#fff}.choices__list--dropdown .choices__item--selectable:after{content:"Press to select";font-size:12px;opacity:0;float:right}.choices__list--dropdown .choices__item--selectable.is-highlighted{background-color:#f2f2f2}.is-open .choices__list--dropdown{border-color:#b7b7b7}.choices__list--dropdown.is-active{display:block}.is-flipped .choices__list--dropdown{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-radius:.25rem .25rem 0 0}.choices__item{cursor:default}.choices__item--selectable{cursor:pointer}.choices__item--disabled{cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;opacity:.5}.choices__group .choices__heading{font-weight:600;font-size:1.2rem;padding:1rem;border-bottom:1px solid #eaeaea;color:gray}.choices__input{background-color:#f9f9f9;font-size:1.4rem;padding:0;margin-bottom:.5rem;display:inline-block;vertical-align:baseline;border:0;border-radius:0;max-width:100%;padding:.4rem 0 .4rem .2rem}.choices__input:focus{outline:0}
|
||||
*,:after,:before{box-sizing:border-box}body,html{margin:0;height:100%;widows:100%}html{font-size:62.5%}body{background-color:#333;font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:1.6rem;color:#fff}label{display:block;margin-bottom:.8rem;font-size:1.4rem;font-weight:500}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:1.2rem;font-weight:500}.container{display:block;margin:auto;max-width:35em;padding:2.4rem}.section{background-color:#fff;padding:2.4rem;color:#333}.choices{margin-bottom:2.4rem;position:relative}.choices.is-disabled .choices__inner,.choices.is-disabled .choices__input{background-color:#eaeaea;cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.choices.is-disabled .choices__item{cursor:not-allowed}.choices[data-type*=select-one].is-open:after{border-color:transparent transparent #b7b7b7 transparent;margin-top:-7.5px}.choices[data-type*=select-one]:after{content:"";height:0;width:0;border-style:solid;border-color:#b7b7b7 transparent transparent transparent;border-width:5px;position:absolute;right:1.15rem;top:50%;margin-top:-2.5px}.choices__inner{background-color:#f9f9f9;padding:.75rem .75rem .375rem;border:1px solid #ddd;border-radius:.25rem;font-size:1.4rem;cursor:text;overflow:hidden}.choices__inner:focus{outline:1px solid #00bcd4;outline-offset:-1px}.is-focused .choices__inner{border-color:#b7b7b7}.is-open .choices__inner{border-radius:.25rem .25rem 0 0}.is-flipped.is-open .choices__inner{border-radius:0 0 .25rem .25rem}.choices__list{margin:0;padding-left:0;list-style-type:none}.choices__list--single{display:inline-block;padding:.4rem}.choices__list--multiple{display:inline}.choices__list--multiple .choices__item{display:inline-block;border-radius:2rem;padding:.4rem 1rem;font-size:1.2rem;margin-right:.375rem;margin-bottom:.375rem;background-color:#00bcd4;border:1px solid #00a5bb;color:#fff;word-break:break-all}.choices__list--multiple .choices__item.is-selected{background-color:#00a5bb}.is-disabled .choices__list--multiple .choices__item{background-color:#b7b7b7;border:1px solid #aaa}.choices__list--dropdown{display:none;z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem;max-height:300px;overflow:auto;will-change:scroll-position}.choices__list--dropdown.is-active{display:block}.choices__list--dropdown .choices__item{padding:1rem;font-size:1.4rem}.choices__list--dropdown .choices__item--selectable.is-highlighted:after,.choices__list--dropdown .choices__item.is-selected{opacity:.5}.choices__list--dropdown .choices__item.is-selected:hover{background-color:#fff}.choices__list--dropdown .choices__item--selectable:after{content:"Press to select";font-size:12px;opacity:0;float:right}.choices__list--dropdown .choices__item--selectable.is-highlighted{background-color:#f2f2f2}.is-open .choices__list--dropdown{border-color:#b7b7b7}.is-flipped .choices__list--dropdown{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-radius:.25rem .25rem 0 0}.choices__item{cursor:default}.choices__item--selectable{cursor:pointer}.choices__item--disabled{cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;opacity:.5}.choices__group .choices__heading{font-weight:600;font-size:1.2rem;padding:1rem;border-bottom:1px solid #eaeaea;color:gray}.choices__input{background-color:#f9f9f9;font-size:1.4rem;padding:0;margin-bottom:.5rem;display:inline-block;vertical-align:baseline;border:0;border-radius:0;max-width:100%;padding:.4rem 0 .4rem .2rem}.choices__input:focus{outline:0}
|
|
@ -50,6 +50,33 @@ h1, h2, h3, h4, h5, h6 {
|
|||
.choices {
|
||||
margin-bottom: $global-guttering;
|
||||
position: relative;
|
||||
&.is-disabled {
|
||||
.choices__inner, .choices__input {
|
||||
background-color: lighten(#DDDDDD, 5%);
|
||||
cursor: not-allowed;
|
||||
user-select: none;
|
||||
}
|
||||
.choices__item { cursor: not-allowed; }
|
||||
}
|
||||
}
|
||||
|
||||
.choices[data-type*="select-one"] {
|
||||
&.is-open:after {
|
||||
border-color: transparent transparent darken(#DDDDDD, 15%) transparent;
|
||||
margin-top: -7.5px;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-style: solid;
|
||||
border-color: darken(#DDDDDD, 15%) transparent transparent transparent;
|
||||
border-width: 5px;
|
||||
position: absolute;
|
||||
right: .75rem + .4rem;
|
||||
top: 50%;
|
||||
margin-top: -2.5px;
|
||||
}
|
||||
}
|
||||
|
||||
.choices__inner {
|
||||
|
@ -64,7 +91,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||
outline: 1px solid #00BCD4;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.is-focused & { border-color: darken(#DDDDDD, 15%); }
|
||||
.is-open & { border-radius: .25rem .25rem 0 0; }
|
||||
.is-flipped.is-open & { border-radius: 0 0 .25rem .25rem; }
|
||||
|
@ -76,8 +102,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||
list-style-type: none;
|
||||
}
|
||||
|
||||
.choices__list--options {}
|
||||
|
||||
.choices__list--single {
|
||||
display: inline-block;
|
||||
padding: .4rem;
|
||||
|
@ -93,10 +117,14 @@ h1, h2, h3, h4, h5, h6 {
|
|||
margin-right: .375rem;
|
||||
margin-bottom: .375rem;
|
||||
background-color: #00BCD4;
|
||||
border: 1px solid darken(#00BCD4, 2.5%);
|
||||
border: 1px solid darken(#00BCD4, 5%);
|
||||
color: #FFFFFF;
|
||||
word-break: break-all;
|
||||
&.is-selected { background-color: darken(#00BCD4, 5%); }
|
||||
.is-disabled & {
|
||||
background-color: darken(#DDDDDD, 15%);
|
||||
border: 1px solid darken(#DDDDDD, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +142,8 @@ h1, h2, h3, h4, h5, h6 {
|
|||
max-height: 300px;
|
||||
overflow: auto;
|
||||
will-change: scroll-position;
|
||||
&.is-active { display: block; }
|
||||
|
||||
.choices__item {
|
||||
padding: 1rem;
|
||||
font-size: 1.4rem;
|
||||
|
@ -136,8 +166,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||
}
|
||||
|
||||
.is-open & { border-color: darken(#DDDDDD, 15%); }
|
||||
|
||||
&.is-active { display: block; }
|
||||
.is-flipped & {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
|
|
92
index.html
92
index.html
|
@ -11,47 +11,35 @@
|
|||
<div class="container">
|
||||
<div class="section">
|
||||
<h1>Choices</h1>
|
||||
<label for="choices-1">Text input with no values and a limit of 5 items</label>
|
||||
<h2>Text inputs</h2>
|
||||
<label for="choices-1">Limited to 5</label>
|
||||
<input id="choices-1" type="text" value="preset-1 preset-2">
|
||||
|
||||
<label for="choices-2">Text input with preset values, custom classes and a placeholder. No duplicate values allowed</label>
|
||||
<label for="choices-2">Unique values only</label>
|
||||
<input id="choices-2" type="text" value="preset-1, preset-2" placeholder="This is a placeholder" class="custom class">
|
||||
|
||||
<label for="choices-3">Text input that only allows email addresses</label>
|
||||
<label for="choices-3">Email addresses only</label>
|
||||
<input id="choices-3" type="text" placeholder="This is a placeholder">
|
||||
|
||||
<label for="choices-4">Text input that disables adding items (destroyed)</label>
|
||||
<label for="choices-4">Disabled</label>
|
||||
<input id="choices-4" type="text" value="josh@joshuajohnson.co.uk, joe@bloggs.co.uk" placeholder="This is a placeholder">
|
||||
|
||||
<label for="choices-5">Text input that prepends and appends a value to each items return value</label>
|
||||
<label for="choices-5">Prepends and appends a value to each items return value</label>
|
||||
<input id="choices-5" type="text" value="preset-1, preset-2" placeholder="This is a placeholder">
|
||||
|
||||
<label for="choices-6">Text input with preset values passed through options</label>
|
||||
<label for="choices-6">Preset values passed through options</label>
|
||||
<input id="choices-6" type="text" placeholder="This is a placeholder">
|
||||
|
||||
<label for="choices-11">Single select box</label>
|
||||
<select id="choices-11" name="choices-11" data-choice placeholder="This is a placeholder">
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-7">Select box</label>
|
||||
<h2>Multiple select input</h2>
|
||||
<label for="choices-7">Default</label>
|
||||
<select name="choices-7" id="choices-7" placeholder="This is a placeholder" multiple>
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
<option value="Dropdown item 3" selected disabled>Dropdown item 3</option>
|
||||
<option value="Dropdown item 3" selected>Dropdown item 3</option>
|
||||
<option value="Dropdown item 4" disabled>Dropdown item 4</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-8">Select box</label>
|
||||
<select id="choices-8" name="choices-8" data-choice placeholder="This is a placeholder" multiple>
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-9">Select box with pre-selected option</label>
|
||||
<label for="choices-9">With pre-selected option</label>
|
||||
<select id="choices-9" name="choices-9" data-choice placeholder="Choose an option" multiple>
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2" selected>Dropdown item 2</option>
|
||||
|
@ -91,6 +79,17 @@
|
|||
<option value="Vancouver">Vancouver</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<h2>Single select input</h2>
|
||||
<label for="choices-11">Default</label>
|
||||
<select id="choices-11" name="choices-11" data-choice placeholder="This is a placeholder">
|
||||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2">Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-12">Options from remote source</label>
|
||||
<select name="choices-12" id="choices-12" data-choice placeholder="Pick an Arctic Monkeys record"></select>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
@ -100,15 +99,6 @@
|
|||
delimiter: ' ',
|
||||
editItems: true,
|
||||
maxItems: 5,
|
||||
// callbackOnRemoveItem: function(value) {
|
||||
// console.log(value);
|
||||
// },
|
||||
// callbackOnAddItem: function(id, value) {
|
||||
// console.log(id, value);
|
||||
// },
|
||||
// callbackOnRender: function(items) {
|
||||
// console.log(items);
|
||||
// }
|
||||
});
|
||||
|
||||
const choices2 = new Choices('#choices-2', {
|
||||
|
@ -126,43 +116,35 @@
|
|||
const choices4 = new Choices('#choices-4', {
|
||||
addItems: false,
|
||||
removeItems: false,
|
||||
});
|
||||
|
||||
choices4.destroy();
|
||||
}).disable();
|
||||
|
||||
const choices5 = new Choices('#choices-5', {
|
||||
prependValue: 'item-',
|
||||
appendValue: `-${Date.now()}`,
|
||||
// callbackOnRender: function(items, options) {
|
||||
// console.log(items);
|
||||
// },
|
||||
});
|
||||
|
||||
choices5.removeActiveItems();
|
||||
}).removeActiveItems();
|
||||
|
||||
const choices6 = new Choices('#choices-6', {
|
||||
items: ['josh@joshuajohnson.co.uk', 'joe@bloggs.co.uk'],
|
||||
// callbackOnRender: function(items, options, groups) {
|
||||
// console.log(items);
|
||||
// },
|
||||
});
|
||||
|
||||
const choices7 = new Choices('#choices-7', {
|
||||
// callbackOnRender: function(items, options) {
|
||||
// console.log(items);
|
||||
// },
|
||||
const choices7 = new Choices('#choices-7');
|
||||
|
||||
const choicesAjax = new Choices('#choices-12').ajax((callback) => {
|
||||
fetch('https://api.discogs.com/artists/391170/releases?token=QBRmstCkwXEvCjTclCpumbtNwvVkEzGAdELXyRyW')
|
||||
.then((response) => {
|
||||
response.json().then(function(data) {
|
||||
callback(data.releases, 'title', 'title');
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
callback();
|
||||
});
|
||||
});
|
||||
|
||||
const choicesMultiple = new Choices('[data-choice]', {
|
||||
placeholderValue: 'This is a placeholder set in the config',
|
||||
// callbackOnRender: function(items, options, groups) {
|
||||
// console.log(options);
|
||||
// },
|
||||
});
|
||||
|
||||
// choices6.addItem('josh2@joshuajohnson.co.uk', null, null, () => { console.log('Custom add item callback')});
|
||||
// choices6.removeItemsByValue('josh@joshuajohnson.co.uk');
|
||||
// console.log(choices6.getItemById(3));
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
Loading…
Reference in a new issue