Resolve bug #637 (#754)

* Add is-selected class when item is selected

* Remove console.log

* Update README
This commit is contained in:
Josh Johnson 2019-11-13 14:49:23 +00:00 committed by GitHub
parent f745be449d
commit 84b952e115
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 113 additions and 29 deletions

View file

@ -147,6 +147,7 @@ Or include Choices directly:
openState: 'is-open',
disabledState: 'is-disabled',
highlightedState: 'is-highlighted',
selectedState: 'is-selected',
flippedState: 'is-flipped',
loadingState: 'is-loading',
noResults: 'has-no-results',
@ -578,6 +579,7 @@ classNames: {
openState: 'is-open',
disabledState: 'is-disabled',
highlightedState: 'is-highlighted',
selectedState: 'is-selected',
flippedState: 'is-flipped',
selectedState: 'is-highlighted',
}

View file

@ -28,6 +28,7 @@ export const DEFAULT_CLASSNAMES = {
openState: 'is-open',
disabledState: 'is-disabled',
highlightedState: 'is-highlighted',
selectedState: 'is-selected',
flippedState: 'is-flipped',
loadingState: 'is-loading',
noResults: 'has-no-results',

View file

@ -35,6 +35,7 @@ describe('constants', () => {
'openState',
'disabledState',
'highlightedState',
'selectedState',
'flippedState',
'loadingState',
'noResults',

View file

@ -2,9 +2,22 @@
* Helpers to create HTML elements used by Choices
* Can be overridden by providing `callbackOnCreateTemplates` option
* @typedef {import('../../types/index').Choices.Templates} Templates
* @typedef {import('../../types/index').Choices.ClassNames} ClassNames
* @typedef {import('../../types/index').Choices.Options} Options
* @typedef {import('../../types/index').Choices.Item} Item
* @typedef {import('../../types/index').Choices.Choice} Choice
* @typedef {import('../../types/index').Choices.Group} Group
*/
export const TEMPLATES = /** @type {Templates} */ ({
/**
* @param {Partial<ClassNames>} classNames
* @param {"ltr" | "rtl" | "auto"} dir
* @param {boolean} isSelectElement
* @param {boolean} isSelectOneElement
* @param {boolean} searchEnabled
* @param {"select-one" | "select-multiple" | "text"} passedElementType
*/
containerOuter(
{ containerOuter },
dir,
@ -40,18 +53,29 @@ export const TEMPLATES = /** @type {Templates} */ ({
return div;
},
/**
* @param {Partial<ClassNames>} classNames
*/
containerInner({ containerInner }) {
return Object.assign(document.createElement('div'), {
className: containerInner,
});
},
/**
* @param {Partial<ClassNames>} classNames
* @param {boolean} isSelectOneElement
*/
itemList({ list, listSingle, listItems }, isSelectOneElement) {
return Object.assign(document.createElement('div'), {
className: `${list} ${isSelectOneElement ? listSingle : listItems}`,
});
},
/**
* @param {Partial<ClassNames>} classNames
* @param {string} value
*/
placeholder({ placeholder }, value) {
return Object.assign(document.createElement('div'), {
className: placeholder,
@ -59,6 +83,11 @@ export const TEMPLATES = /** @type {Templates} */ ({
});
},
/**
* @param {Partial<ClassNames>} classNames
* @param {Item} item
* @param {boolean} removeItemButton
*/
item(
{ item, button, highlightedState, itemSelectable, placeholder },
{
@ -122,6 +151,10 @@ export const TEMPLATES = /** @type {Templates} */ ({
return div;
},
/**
* @param {Partial<ClassNames>} classNames
* @param {boolean} isSelectOneElement
*/
choiceList({ list }, isSelectOneElement) {
const div = Object.assign(document.createElement('div'), {
className: list,
@ -135,6 +168,10 @@ export const TEMPLATES = /** @type {Templates} */ ({
return div;
},
/**
* @param {Partial<ClassNames>} classNames
* @param {Group} group
*/
choiceGroup({ group, groupHeading, itemDisabled }, { id, value, disabled }) {
const div = Object.assign(document.createElement('div'), {
className: `${group} ${disabled ? itemDisabled : ''}`,
@ -162,15 +199,28 @@ export const TEMPLATES = /** @type {Templates} */ ({
return div;
},
/**
* @param {Partial<ClassNames>} classNames
* @param {Choice} choice
* @param {Options['itemSelectText']} selectText
*/
choice(
{ item, itemChoice, itemSelectable, itemDisabled, placeholder },
{
item,
itemChoice,
itemSelectable,
selectedState,
itemDisabled,
placeholder,
},
{
id,
value,
label,
groupId,
elementId,
disabled,
disabled: isDisabled,
selected: isSelected,
placeholder: isPlaceholder,
},
selectText,
@ -178,11 +228,17 @@ export const TEMPLATES = /** @type {Templates} */ ({
const div = Object.assign(document.createElement('div'), {
id: elementId,
innerHTML: label,
className: `${item} ${itemChoice} ${
disabled ? itemDisabled : itemSelectable
} ${isPlaceholder ? placeholder : ''}`,
className: `${item} ${itemChoice}`,
});
if (isSelected) {
div.classList.add(selectedState);
}
if (isPlaceholder) {
div.classList.add(placeholder);
}
div.setAttribute('role', groupId > 0 ? 'treeitem' : 'option');
Object.assign(div.dataset, {
@ -192,16 +248,22 @@ export const TEMPLATES = /** @type {Templates} */ ({
selectText,
});
if (disabled) {
if (isDisabled) {
div.classList.add(itemDisabled);
div.dataset.choiceDisabled = '';
div.setAttribute('aria-disabled', 'true');
} else {
div.classList.add(itemSelectable);
div.dataset.choiceSelectable = '';
}
return div;
},
/**
* @param {Partial<ClassNames>} classNames
* @param {string} placeholderValue
*/
input({ input, inputCloned }, placeholderValue) {
const inp = Object.assign(document.createElement('input'), {
type: 'text',
@ -218,6 +280,9 @@ export const TEMPLATES = /** @type {Templates} */ ({
return inp;
},
/**
* @param {Partial<ClassNames>} classNames
*/
dropdown({ list, listDropdown }) {
const div = document.createElement('div');
@ -227,6 +292,12 @@ export const TEMPLATES = /** @type {Templates} */ ({
return div;
},
/**
*
* @param {Partial<ClassNames>} classNames
* @param {string} innerHTML
* @param {"no-choices" | "no-results" | ""} type
*/
notice({ item, itemChoice, noResults, noChoices }, innerHTML, type = '') {
const classes = [item, itemChoice];
@ -242,6 +313,9 @@ export const TEMPLATES = /** @type {Templates} */ ({
});
},
/**
* @param {Item} option
*/
option({ label, value, customProperties, active, disabled }) {
const opt = new Option(label, value, false, active);

View file

@ -24,7 +24,7 @@ function expectEqualElements(element1, element2) {
describe('templates', () => {
describe('containerOuter', () => {
const classes = {
containerOuter: 'test',
containerOuter: 'class-1',
};
const direction = 'rtl';
@ -158,7 +158,7 @@ describe('templates', () => {
describe('containerInner', () => {
it('returns expected html', () => {
const classes = {
containerInner: 'test',
containerInner: 'class-1',
};
const expectedOutput = strToEl(
`<div class="${classes.containerInner}"></div>`,
@ -171,9 +171,9 @@ describe('templates', () => {
describe('itemList', () => {
const classes = {
list: 'test 1',
listSingle: 'test 2',
listItems: 'test 3',
list: 'class-1',
listSingle: 'class-2',
listItems: 'class-3',
};
describe('select one element', () => {
@ -202,7 +202,7 @@ describe('templates', () => {
describe('placeholder', () => {
it('returns expected html', () => {
const classes = {
placeholder: 'test',
placeholder: 'class-1',
};
const value = 'test';
const expectedOutput = strToEl(`
@ -215,7 +215,7 @@ describe('templates', () => {
describe('choiceList', () => {
const classes = {
list: 'test',
list: 'class-1',
};
describe('select one element', () => {
@ -252,9 +252,9 @@ describe('templates', () => {
describe('choiceGroup', () => {
const classes = {
group: 'test 1',
groupHeading: 'test 2',
itemDisabled: 'test 3',
group: 'class-1',
groupHeading: 'class-2',
itemDisabled: 'class-3',
};
let data;
@ -316,11 +316,12 @@ describe('templates', () => {
describe('choice', () => {
const classes = {
item: 'test 1',
itemChoice: 'test 2',
itemDisabled: 'test 3',
itemSelectable: 'test 4',
placeholder: 'test 5',
item: 'class-1',
itemChoice: 'class-2',
itemDisabled: 'class-3',
itemSelectable: 'class-4',
placeholder: 'class-5',
selectedState: 'class-6',
};
const itemSelectText = 'test 6';
@ -356,6 +357,8 @@ describe('templates', () => {
`);
const actualOutput = templates.choice(classes, data, itemSelectText);
console.log(actualOutput);
expectEqualElements(actualOutput, expectedOutput);
});
});
@ -451,8 +454,8 @@ describe('templates', () => {
describe('input', () => {
const classes = {
input: 'test 1',
inputCloned: 'test 2',
input: 'class-1',
inputCloned: 'class-2',
};
it('returns expected html', () => {
@ -479,9 +482,10 @@ describe('templates', () => {
describe('dropdown', () => {
const classes = {
list: 'test-1',
listDropdown: 'test-2',
list: 'class-1',
listDropdown: 'class-2',
};
it('returns expected html', () => {
const value = 'test';
const expectedOutput = strToEl(
@ -495,10 +499,10 @@ describe('templates', () => {
describe('notice', () => {
const classes = {
item: 'test-1',
itemChoice: 'test-2',
noResults: 'test-3',
noChoices: 'test-4',
item: 'class-1',
itemChoice: 'class-2',
noResults: 'class-3',
noChoices: 'class-4',
};
const label = 'test';

2
types/index.d.ts vendored
View file

@ -266,6 +266,8 @@ declare namespace Choices {
disabledState: string;
/** @default 'is-highlighted' */
highlightedState: string;
/** @default 'is-selected' */
selectedState: string;
/** @default 'is-flipped' */
flippedState: string;
/** @default 'is-loading' */