mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-09 09:06:37 +02:00
Handling option groups + label/value differentation
This commit is contained in:
parent
fc0a72d2a2
commit
f63652471c
2
assets/scripts/dist/bundle.js
vendored
2
assets/scripts/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,8 @@
|
|||
export const addItem = (value, id, optionId) => {
|
||||
export const addItem = (value, label, id, optionId) => {
|
||||
return {
|
||||
type: 'ADD_ITEM',
|
||||
value: value,
|
||||
label: label,
|
||||
id: parseInt(id),
|
||||
optionId: parseInt(optionId)
|
||||
}
|
||||
|
@ -23,11 +24,13 @@ export const selectItem = (id, selected) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const addOption = (value, id) => {
|
||||
export const addOption = (value, label, id, groupId) => {
|
||||
return {
|
||||
type: 'ADD_OPTION',
|
||||
value: value,
|
||||
label: label,
|
||||
id: parseInt(id),
|
||||
groupId: parseInt(groupId)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -37,4 +40,12 @@ export const selectOption = (id, selected) => {
|
|||
id: parseInt(id),
|
||||
selected: selected,
|
||||
}
|
||||
};
|
||||
|
||||
export const addGroup = (value, id) => {
|
||||
return {
|
||||
type: 'ADD_GROUP',
|
||||
value: value,
|
||||
id: parseInt(id)
|
||||
}
|
||||
};
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import { createStore } from 'redux';
|
||||
import rootReducer from './reducers/index.js';
|
||||
import { addItem, removeItem, selectItem, addOption, selectOption } from './actions/index';
|
||||
import { hasClass, wrap, getSiblings, isType, strToEl, extend } from './lib/utils.js';
|
||||
import { addItem, removeItem, selectItem, addOption, selectOption, addGroup } from './actions/index';
|
||||
import { hasClass, wrap, getSiblings, isType, strToEl, extend, getWidthOfInput } from './lib/utils.js';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -61,6 +61,8 @@ export class Choices {
|
|||
itemSelectable: 'choices__item--selectable',
|
||||
itemDisabled: 'choices__item--disabled',
|
||||
itemOption: 'choices__item--option',
|
||||
group: 'choices__group',
|
||||
groupHeading : 'choices__heading',
|
||||
activeState: 'is-active',
|
||||
disabledState: 'is-disabled',
|
||||
hiddenState: 'is-hidden',
|
||||
|
@ -125,6 +127,14 @@ export class Choices {
|
|||
return (this.store.getState().items.length === 0) ? true : false;
|
||||
}
|
||||
|
||||
hasSelectedItems() {
|
||||
const items = this.getItems();
|
||||
|
||||
return items.some((item) => {
|
||||
return item.selected === true;
|
||||
});
|
||||
}
|
||||
|
||||
/* Event handling */
|
||||
|
||||
/**
|
||||
|
@ -143,6 +153,8 @@ export class Choices {
|
|||
// If we are typing in the input
|
||||
if(e.target === this.input) {
|
||||
|
||||
// this.input.style.width = getWidthOfInput(this.input);
|
||||
|
||||
// If CTRL + A or CMD + A have been pressed and there are items to select
|
||||
if (ctrlDownKey && e.keyCode === aKey && this.list && this.list.children) {
|
||||
const handleSelectAll = () => {
|
||||
|
@ -161,22 +173,24 @@ export class Choices {
|
|||
const handleEnter = () => {
|
||||
let canUpdate = true;
|
||||
|
||||
// If there is a max entry limit and we have reached that limit
|
||||
// don't update
|
||||
if (this.options.maxItems && this.options.maxItems <= this.list.children.length) {
|
||||
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 {
|
||||
canUpdate = false;
|
||||
}
|
||||
|
||||
// If no duplicates are allowed, and the value already exists
|
||||
// in the array, don't update
|
||||
if (this.options.allowDuplicates === false && this.passedElement.value) {
|
||||
canUpdate = !items.some((item) => {
|
||||
return item.value === value;
|
||||
});
|
||||
}
|
||||
|
||||
// All is good, update
|
||||
if (canUpdate && this.options.addItems) {
|
||||
if (canUpdate) {
|
||||
if(this.passedElement.type === 'text') {
|
||||
let canAddItem = true;
|
||||
|
||||
|
@ -280,13 +294,16 @@ export class Choices {
|
|||
|
||||
if(!option.selected) {
|
||||
this.selectOption(id, true);
|
||||
this.addItem(option.value, option.id);
|
||||
this.addItem(option.value, option.label, option.id);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Click is outside of our element so close dropdown and de-select items
|
||||
this.deselectAll();
|
||||
if(this.hasSelectedItems()) {
|
||||
this.deselectAll();
|
||||
}
|
||||
// If there is a dropdown and it is active
|
||||
if(this.dropdown && this.dropdown.classList.contains(this.options.classNames.activeState)) {
|
||||
this.toggleDropdown();
|
||||
}
|
||||
|
@ -392,10 +409,11 @@ export class Choices {
|
|||
* Add item to store with correct value
|
||||
* @param {String} value Value to add to store
|
||||
*/
|
||||
addItem(value, optionId = -1, callback = this.options.callbackOnAddItem) {
|
||||
addItem(value, label, optionId = -1, callback = this.options.callbackOnAddItem) {
|
||||
if (this.options.debug) console.debug('Add item');
|
||||
|
||||
let passedValue = value;
|
||||
let passedValue = value.trim();
|
||||
let passedLabel = label || passedValue;
|
||||
|
||||
// If a prepended value has been passed, prepend it
|
||||
if(this.options.prependValue) {
|
||||
|
@ -424,7 +442,7 @@ export class Choices {
|
|||
}
|
||||
}
|
||||
|
||||
this.store.dispatch(addItem(passedValue, id, optionId));
|
||||
this.store.dispatch(addItem(passedValue, passedLabel, id, optionId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -485,21 +503,26 @@ export class Choices {
|
|||
this.dropdown.classList[isActive ? 'remove' : 'add']('is-active');
|
||||
}
|
||||
|
||||
addOptionToDropdown(option) {
|
||||
addOption(option, groupId = -1) {
|
||||
// Generate unique id
|
||||
const state = this.store.getState();
|
||||
const id = state.options.length + 1;
|
||||
const value = option.value;
|
||||
const label = option.innerHTML;
|
||||
const isSelected = option.selected;
|
||||
|
||||
this.store.dispatch(addOption(value, id));
|
||||
this.store.dispatch(addOption(value, label, id, groupId));
|
||||
|
||||
if(isSelected) {
|
||||
this.selectOption(id);
|
||||
this.addItem(option.value, id);
|
||||
this.addItem(value, label, id);
|
||||
}
|
||||
}
|
||||
|
||||
addGroup(value, id) {
|
||||
this.store.dispatch(addGroup(value, id));
|
||||
}
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
|
@ -548,6 +571,11 @@ export class Choices {
|
|||
const state = this.store.getState();
|
||||
return state.options;
|
||||
}
|
||||
|
||||
getGroups() {
|
||||
const state = this.store.getState();
|
||||
return state.groups;
|
||||
}
|
||||
|
||||
/* Rendering */
|
||||
|
||||
|
@ -556,18 +584,6 @@ export class Choices {
|
|||
* @return
|
||||
*/
|
||||
generateTextInput() {
|
||||
/*
|
||||
Template:
|
||||
|
||||
<div class="choices choices--active">
|
||||
<div class="choices__inner">
|
||||
<input id="1" type="text" data-choice="" class="choices__input choices__input--hidden" tabindex="-1" style="display:none;" aria-hidden="true">
|
||||
<ul class="choices__list choices__list--items"></ul>
|
||||
<input type="text" class="choices__input choices__input--cloned">
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
|
||||
let containerOuter = strToEl(`<div class="${ this.options.classNames.containerOuter }"></div>`);
|
||||
let containerInner = strToEl(`<div class="${ this.options.classNames.containerInner }"></div>`);
|
||||
|
||||
|
@ -591,7 +607,8 @@ export class Choices {
|
|||
// ...and we have a value to set
|
||||
const placeholderValue = this.options.placeholderValue || this.passedElement.placeholder;
|
||||
if(placeholderValue) {
|
||||
input.placeholder = placeholderValue;
|
||||
input.placeholder = placeholderValue;
|
||||
input.style.width = getWidthOfInput(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -650,7 +667,8 @@ export class Choices {
|
|||
|
||||
// If placeholder has been enabled and we have a value
|
||||
if (this.options.placeholder && this.options.placeholderValue) {
|
||||
input.placeholder = this.options.placeholderValue;
|
||||
input.placeholder = this.options.placeholderValue;
|
||||
input.style.width = getWidthOfInput(input);
|
||||
}
|
||||
|
||||
if(!this.options.addItems) {
|
||||
|
@ -668,10 +686,29 @@ export class Choices {
|
|||
this.list = list;
|
||||
this.dropdown = dropdown;
|
||||
|
||||
const passedOptions = Array.prototype.slice.call(this.passedElement.options);
|
||||
passedOptions.forEach((option) => {
|
||||
this.addOptionToDropdown(option);
|
||||
});
|
||||
// const passedGroups;
|
||||
const passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP'));
|
||||
|
||||
if(passedGroups.length) {
|
||||
passedGroups.forEach((group, index) => {
|
||||
const groupOptions = Array.from(group.getElementsByTagName('OPTION'));
|
||||
const groupId = index;
|
||||
|
||||
this.addGroup(group.label, groupId);
|
||||
|
||||
groupOptions.forEach((option) => {
|
||||
this.addOption(option, groupId);
|
||||
});
|
||||
|
||||
});
|
||||
} else {
|
||||
const passedOptions = Array.from(this.passedElement.options);
|
||||
|
||||
passedOptions.forEach((option) => {
|
||||
this.addOption(option);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Subscribe to store
|
||||
this.store.subscribe(this.render);
|
||||
|
@ -725,6 +762,7 @@ export class Choices {
|
|||
const classNames = this.options.classNames;
|
||||
const items = this.getItems();
|
||||
const options = this.getOptions();
|
||||
const groups = this.getGroups();
|
||||
|
||||
// OPTIONS
|
||||
if(this.dropdown) {
|
||||
|
@ -734,16 +772,54 @@ export class Choices {
|
|||
// Create a fragment to store our list items (so we don't have to update the DOM for each item)
|
||||
const optionListFragment = document.createDocumentFragment();
|
||||
|
||||
// Add each option to dropdown
|
||||
if(options) {
|
||||
options.forEach((option) => {
|
||||
const dropdownItem = strToEl(`<li class="${ classNames.item } ${ classNames.itemOption } ${ option.selected ? classNames.selectedState + ' ' + classNames.itemDisabled : classNames.itemSelectable }" data-choice-selectable data-choice-id="${ option.id }" data-choice-value="${ option.value }">${ option.value }</li>`);
|
||||
optionListFragment.appendChild(dropdownItem);
|
||||
// If we have grouped options
|
||||
if(groups.length) {
|
||||
groups.forEach((group) => {
|
||||
|
||||
const dropdownGroup = strToEl(`
|
||||
<div class="${ classNames.group } ${ group.disabled ? classNames.itemDisabled : '' }" data-choice-value="${ group.value }" data-choice-group-id="${ group.id }">
|
||||
<div class="${ classNames.groupHeading }">${ group.value }</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
const childOptions = options.filter((option) => {
|
||||
return option.groupId === group.id;
|
||||
});
|
||||
|
||||
if(childOptions) {
|
||||
childOptions.forEach((option) => {
|
||||
const dropdownItem = strToEl(`
|
||||
<div class="${ classNames.item } ${ classNames.itemOption } ${ option.selected ? classNames.selectedState + ' ' + classNames.itemDisabled : classNames.itemSelectable }" data-choice-selectable data-choice-id="${ option.id }" data-choice-value="${ option.value }">
|
||||
${ option.label }
|
||||
</div>
|
||||
`);
|
||||
|
||||
dropdownGroup.appendChild(dropdownItem);
|
||||
});
|
||||
} else {
|
||||
const dropdownItem = strToEl(`<div class="${ classNames.item }">No options to select</div>`);
|
||||
dropdownGroup.appendChild(dropdownItem);
|
||||
}
|
||||
|
||||
optionListFragment.appendChild(dropdownGroup);
|
||||
});
|
||||
} else {
|
||||
const dropdownItem = strToEl(`<li class="${ classNames.item }">No options to select</li>`);
|
||||
optionListFragment.appendChild(dropdownItem);
|
||||
if(options) {
|
||||
options.forEach((option) => {
|
||||
const dropdownItem = strToEl(`
|
||||
<div class="${ classNames.item } ${ classNames.itemOption } ${ option.selected ? classNames.selectedState + ' ' + classNames.itemDisabled : classNames.itemSelectable }" data-choice-selectable data-choice-id="${ option.id }" data-choice-value="${ option.value }">
|
||||
${ option.label }
|
||||
</div>
|
||||
`);
|
||||
|
||||
optionListFragment.appendChild(dropdownItem);
|
||||
});
|
||||
} else {
|
||||
const dropdownItem = strToEl(`<div class="${ classNames.item }">No options to select</div>`);
|
||||
optionListFragment.appendChild(dropdownItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.dropdown.appendChild(optionListFragment);
|
||||
}
|
||||
|
@ -765,7 +841,11 @@ export class Choices {
|
|||
items.forEach((item) => {
|
||||
if(item.active) {
|
||||
// Create new list element
|
||||
const listItem = strToEl(`<li class="${ classNames.item } ${ this.options.removeItems ? classNames.itemSelectable : '' } ${ item.selected ? classNames.selectedState : '' }" data-choice-item data-choice-id="${ item.id }" data-choice-selected="${ item.selected }">${ item.value }</li>`);
|
||||
const listItem = strToEl(`
|
||||
<li class="${ classNames.item } ${ this.options.removeItems ? classNames.itemSelectable : '' } ${ item.selected ? classNames.selectedState : '' }" data-choice-item data-choice-id="${ item.id }" data-choice-selected="${ item.selected }">
|
||||
${ item.label }
|
||||
</li>
|
||||
`);
|
||||
|
||||
// Append it to list
|
||||
itemListFragment.appendChild(listItem);
|
||||
|
@ -777,7 +857,7 @@ export class Choices {
|
|||
// Run callback if it is a function
|
||||
if(callback){
|
||||
if(isType('Function', callback)) {
|
||||
callback(items, options);
|
||||
callback(items, options, groups);
|
||||
} else {
|
||||
console.error('callbackOnRender: Callback is not a function');
|
||||
}
|
||||
|
@ -889,8 +969,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
|
||||
const choicesMultiple = new Choices('[data-choice]', {
|
||||
placeholderValue: 'This is a placeholder set in the config',
|
||||
callbackOnRender: function(items, options) {
|
||||
console.log(items);
|
||||
callbackOnRender: function(items, options, groups) {
|
||||
console.log(options);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -371,15 +371,29 @@ export const strToEl = (function() {
|
|||
}());
|
||||
|
||||
/**
|
||||
* Calculates the width of a passed input based on its value
|
||||
* Sets the width of a passed input based on its value
|
||||
* @return {Number} Width of input
|
||||
*/
|
||||
export const getWidthOfInput = () => {
|
||||
let tmp = document.createElement('span');
|
||||
tmp.className = "tmp-element";
|
||||
tmp.innerHTML = inputEl.value.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||
document.body.appendChild(tmp);
|
||||
let theWidth = tmp.getBoundingClientRect().width;
|
||||
document.body.removeChild(tmp);
|
||||
return theWidth;
|
||||
export const getWidthOfInput = (input, initialWidth = 20) => {
|
||||
const value = input.value || input.placeholder;
|
||||
let width = input.offsetWidth;
|
||||
|
||||
if(value) {
|
||||
const testEl = strToEl(`<span class="offscreen">${value}</span>`);
|
||||
testEl.style.position = 'absolute';
|
||||
testEl.style.top = '-9999px';
|
||||
testEl.style.left = '-9999px';
|
||||
testEl.style.padding = '0';
|
||||
testEl.style.width = 'auto';
|
||||
|
||||
document.body.appendChild(testEl);
|
||||
|
||||
if(testEl.offsetWidth > initialWidth && testEl.offsetWidth != input.offsetWidth) {
|
||||
width = testEl.offsetWidth + initialWidth;
|
||||
}
|
||||
|
||||
document.body.removeChild(testEl);
|
||||
}
|
||||
|
||||
return `${width}px`;
|
||||
}
|
15
assets/scripts/src/reducers/groups.js
Normal file
15
assets/scripts/src/reducers/groups.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
const groups = (state = [], action) => {
|
||||
switch (action.type) {
|
||||
case 'ADD_GROUP':
|
||||
return [...state, {
|
||||
id: parseInt(action.id),
|
||||
value: action.value,
|
||||
disabled: false,
|
||||
}];
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default groups;
|
|
@ -1,9 +1,11 @@
|
|||
import { combineReducers } from 'redux';
|
||||
import items from './items';
|
||||
import groups from './groups';
|
||||
import options from './options';
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
items,
|
||||
groups,
|
||||
options
|
||||
})
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ const items = (state = [], action) => {
|
|||
id: action.id,
|
||||
optionId: action.optionId,
|
||||
value: action.value,
|
||||
label: action.label,
|
||||
active: true,
|
||||
selected: false
|
||||
}];
|
||||
|
|
|
@ -3,9 +3,11 @@ const options = (state = [], action) => {
|
|||
case 'ADD_OPTION':
|
||||
return [...state, {
|
||||
id: parseInt(action.id),
|
||||
groupId: action.groupId,
|
||||
value: action.value,
|
||||
label: action.label,
|
||||
disabled: false,
|
||||
selected: false
|
||||
selected: false,
|
||||
}];;
|
||||
|
||||
case 'SELECT_OPTION':
|
||||
|
|
|
@ -46,7 +46,8 @@ h1, h2, h3, h4, h5, h6 {
|
|||
padding: .75rem .75rem .375rem;
|
||||
border: 1px solid #DDDDDD;
|
||||
border-radius: .25rem;
|
||||
font-size: 1.4rem; }
|
||||
font-size: 1.4rem;
|
||||
cursor: text; }
|
||||
.choices__inner:focus {
|
||||
outline: 1px solid #00BCD4;
|
||||
outline-offset: -1px; }
|
||||
|
@ -67,7 +68,8 @@ h1, h2, h3, h4, h5, h6 {
|
|||
margin-bottom: .375rem;
|
||||
background-color: #00BCD4;
|
||||
border: 1px solid #00b1c7;
|
||||
color: #FFFFFF; }
|
||||
color: #FFFFFF;
|
||||
word-break: break-all; }
|
||||
.choices__list--items .choices__item.is-selected {
|
||||
background-color: #00a5bb; }
|
||||
|
||||
|
@ -85,12 +87,12 @@ h1, h2, h3, h4, h5, h6 {
|
|||
.choices__list--dropdown .choices__item {
|
||||
padding: 1rem;
|
||||
font-size: 1.4rem; }
|
||||
.choices__list--dropdown .choices__item:hover {
|
||||
background-color: #f9f9f9; }
|
||||
.choices__list--dropdown .choices__item.is-selected {
|
||||
opacity: .5; }
|
||||
.choices__list--dropdown .choices__item.is-selected:hover {
|
||||
background-color: #FFFFFF; }
|
||||
.choices__list--dropdown .choices__item--selectable:hover {
|
||||
background-color: #f9f9f9; }
|
||||
.choices__list--dropdown.is-active {
|
||||
display: block; }
|
||||
.choices__list--dropdown.is-flipped {
|
||||
|
@ -116,6 +118,12 @@ h1, h2, h3, h4, h5, h6 {
|
|||
-ms-user-select: none;
|
||||
user-select: none; }
|
||||
|
||||
.choices__group .choices__heading {
|
||||
font-size: 1.2rem;
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #EAEAEA;
|
||||
color: gray; }
|
||||
|
||||
.choices__input {
|
||||
background-color: #f9f9f9;
|
||||
font-size: 1.4rem;
|
||||
|
|
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}.choices__inner:focus{outline:1px solid #00bcd4;outline-offset:-1px}.choices__list{margin:0;padding-left:0;list-style-type:none}.choices__list--items{display:inline}.choices__list--items .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}.choices__list--items .choices__item.is-selected{background-color:#00a5bb}.choices__list--dropdown{z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;display:none;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.choices__list--dropdown .choices__item{padding:1rem;font-size:1.4rem}.choices__list--dropdown .choices__item:hover{background-color:#f9f9f9}.choices__list--dropdown .choices__item.is-selected{opacity:.5}.choices__list--dropdown .choices__item.is-selected:hover{background-color:#fff}.choices__list--dropdown.is-active{display:block}.choices__list--dropdown.is-flipped{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.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}.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__inner{background-color:#f9f9f9;padding:.75rem .75rem .375rem;border:1px solid #ddd;border-radius:.25rem;font-size:1.4rem;cursor:text}.choices__inner:focus{outline:1px solid #00bcd4;outline-offset:-1px}.choices__list{margin:0;padding-left:0;list-style-type:none}.choices__list--items{display:inline}.choices__list--items .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--items .choices__item.is-selected{background-color:#00a5bb}.choices__list--dropdown{z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;display:none;border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.choices__list--dropdown .choices__item{padding:1rem;font-size:1.4rem}.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:hover{background-color:#f9f9f9}.choices__list--dropdown.is-active{display:block}.choices__list--dropdown.is-flipped{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.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}.choices__group .choices__heading{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}
|
|
@ -58,6 +58,7 @@ h1, h2, h3, h4, h5, h6 {
|
|||
border: 1px solid #DDDDDD;
|
||||
border-radius: .25rem;
|
||||
font-size: 1.4rem;
|
||||
cursor: text;
|
||||
&:focus {
|
||||
outline: 1px solid #00BCD4;
|
||||
outline-offset: -1px;
|
||||
|
@ -84,6 +85,7 @@ h1, h2, h3, h4, h5, h6 {
|
|||
background-color: #00BCD4;
|
||||
border: 1px solid darken(#00BCD4, 2.5%);
|
||||
color: #FFFFFF;
|
||||
word-break: break-all;
|
||||
&.is-selected { background-color: darken(#00BCD4, 5%); }
|
||||
}
|
||||
}
|
||||
|
@ -102,12 +104,15 @@ h1, h2, h3, h4, h5, h6 {
|
|||
.choices__item {
|
||||
padding: 1rem;
|
||||
font-size: 1.4rem;
|
||||
&:hover { background-color: mix(#000000, #FFFFFF, 2.5%); }
|
||||
&.is-selected {
|
||||
opacity: .5;
|
||||
&:hover { background-color: #FFFFFF; }
|
||||
}
|
||||
}
|
||||
.choices__item--selectable {
|
||||
&:hover { background-color: mix(#000000, #FFFFFF, 2.5%); }
|
||||
}
|
||||
|
||||
&.is-active { display: block; }
|
||||
&.is-flipped {
|
||||
top: auto;
|
||||
|
@ -128,6 +133,15 @@ h1, h2, h3, h4, h5, h6 {
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.choices__group {
|
||||
.choices__heading {
|
||||
font-size: 1.2rem;
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #EAEAEA;
|
||||
color: lighten(#333, 30%);
|
||||
}
|
||||
}
|
||||
|
||||
.choices__input {
|
||||
background-color: mix(#000000, #FFFFFF, 2.5%);
|
||||
font-size: 1.4rem;
|
||||
|
|
24
index.html
24
index.html
|
@ -36,7 +36,7 @@
|
|||
<option value="Dropdown item 4" disabled="disabled">Dropdown item 4</option>
|
||||
</select>
|
||||
|
||||
<label for="choices-8">Select box</label>
|
||||
<!-- <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>
|
||||
|
@ -48,24 +48,24 @@
|
|||
<option value="Dropdown item 1">Dropdown item 1</option>
|
||||
<option value="Dropdown item 2" selected>Dropdown item 2</option>
|
||||
<option value="Dropdown item 3">Dropdown item 3</option>
|
||||
</select>
|
||||
</select> -->
|
||||
|
||||
<label for="choices-10">Select box with pre-selected option</label>
|
||||
<label for="choices-10">Select box with option groups</label>
|
||||
<select id="choices-10" name="choices-10" data-choice placeholder="This is a placeholder" multiple>
|
||||
<optgroup label="Group 1">
|
||||
<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>
|
||||
<option value="Value 1">Dropdown item 1</option>
|
||||
<option value="Value 2">Dropdown item 2</option>
|
||||
<option value="Value 3">Dropdown item 3</option>
|
||||
</optgroup>
|
||||
<optgroup label="Group 2">
|
||||
<option value="Dropdown item 4">Dropdown item 4</option>
|
||||
<option value="Dropdown item 5">Dropdown item 5</option>
|
||||
<option value="Dropdown item 6">Dropdown item 6</option>
|
||||
<option value="Value 4">Dropdown item 4</option>
|
||||
<option value="Value 5">Dropdown item 5</option>
|
||||
<option value="Value 6">Dropdown item 6</option>
|
||||
</optgroup>
|
||||
<optgroup label="Group 3" disabled>
|
||||
<option value="Dropdown item 4">Dropdown item 7</option>
|
||||
<option value="Dropdown item 5">Dropdown item 8</option>
|
||||
<option value="Dropdown item 6">Dropdown item 9</option>
|
||||
<option value="Value 7">Dropdown item 7</option>
|
||||
<option value="Value 8">Dropdown item 8</option>
|
||||
<option value="Value 9">Dropdown item 9</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue