Install prettier + resolve linting issues

This commit is contained in:
Josh Johnson 2018-05-28 13:55:44 +01:00
parent a6bfdc0993
commit f9455b1a25
32 changed files with 752 additions and 499 deletions

View file

@ -1,34 +1,24 @@
{
"extends": "airbnb",
"ecmaFeatures": {
"modules": true
},
"extends": ["prettier"],
"plugins": ["prettier"],
"env": {
"browser": true,
"node": true,
"mocha": true
},
"globals": {
"__DEV__": true,
"describe": true,
"it": true,
"before": true,
"after": true,
"beforeEach": true,
"afterEach": true,
"expect": true,
"browser": true,
"by": true,
"element": true,
"cy": true
"afterEach": true
},
"parser": "babel-eslint",
"rules": {
"strict": 0,
"no-underscore-dangle": 0,
"no-console": ["warn", {
"allow": ["warn", "error"]
}],
"space-before-function-paren": 0
"prettier/prettier": ["error", {
"singleQuote": true,
"trailingComma": "all"
}]
}
}

View file

@ -43,9 +43,11 @@
"csso": "^1.8.2",
"eslint": "^3.19.0",
"eslint-config-airbnb": "^15.1.0",
"eslint-config-prettier": "^2.9.0",
"eslint-loader": "^1.5.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-prettier": "^2.6.0",
"eslint-plugin-react": "^7.2.1",
"express": "^4.16.3",
"husky": "^0.14.3",
@ -55,6 +57,7 @@
"nodemon": "^1.9.1",
"nyc": "^11.0.3",
"postcss-cli": "^2.5.1",
"prettier": "^1.13.0",
"sinon": "^2.4.0",
"webpack": "^3.8.1",
"webpack-dev-middleware": "^2.0.0",

View file

@ -27,17 +27,19 @@ describe('actions/choices', () => {
keyCode,
};
expect(actions.addChoice(
value,
label,
id,
groupId,
disabled,
elementId,
customProperties,
placeholder,
keyCode,
)).to.eql(expectedAction);
expect(
actions.addChoice(
value,
label,
id,
groupId,
disabled,
elementId,
customProperties,
placeholder,
keyCode,
),
).to.eql(expectedAction);
});
});
@ -88,4 +90,3 @@ describe('actions/choices', () => {
});
});
});

View file

@ -16,12 +16,9 @@ describe('actions/groups', () => {
disabled,
};
expect(actions.addGroup(
value,
id,
active,
disabled,
)).to.eql(expectedAction);
expect(actions.addGroup(value, id, active, disabled)).to.eql(
expectedAction,
);
});
});
});

View file

@ -25,16 +25,18 @@ describe('actions/items', () => {
keyCode,
};
expect(actions.addItem(
value,
label,
id,
choiceId,
groupId,
customProperties,
placeholder,
keyCode,
)).to.eql(expectedAction);
expect(
actions.addItem(
value,
label,
id,
choiceId,
groupId,
customProperties,
placeholder,
keyCode,
),
).to.eql(expectedAction);
});
});

View file

@ -2,10 +2,28 @@ import Fuse from 'fuse.js';
import './lib/polyfills';
import Store from './store/store';
import { Dropdown, Container, Input, List, WrappedInput, WrappedSelect } from './components';
import { DEFAULT_CONFIG, DEFAULT_CLASSNAMES, EVENTS, KEY_CODES, SCROLLING_SPEED } from './constants';
import {
Dropdown,
Container,
Input,
List,
WrappedInput,
WrappedSelect,
} from './components';
import {
DEFAULT_CONFIG,
DEFAULT_CLASSNAMES,
EVENTS,
KEY_CODES,
SCROLLING_SPEED,
} from './constants';
import { TEMPLATES } from './templates';
import { addChoice, filterChoices, activateChoices, clearChoices } from './actions/choices';
import {
addChoice,
filterChoices,
activateChoices,
clearChoices,
} from './actions/choices';
import { addItem, removeItem, highlightItem } from './actions/items';
import { addGroup } from './actions/groups';
import { clearAll } from './actions/misc';
@ -48,12 +66,15 @@ class Choices {
}
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
const passedElement = isType('String', element) ? document.querySelector(element) : element;
const passedElement = isType('String', element)
? document.querySelector(element)
: element;
this._isTextElement = passedElement.type === 'text';
this._isSelectOneElement = passedElement.type === 'select-one';
this._isSelectMultipleElement = passedElement.type === 'select-multiple';
this._isSelectElement = this._isSelectOneElement || this._isSelectMultipleElement;
this._isSelectElement =
this._isSelectOneElement || this._isSelectMultipleElement;
if (this._isTextElement) {
this.passedElement = new WrappedInput({
@ -72,8 +93,14 @@ class Choices {
throw new Error('Could not wrap passed element');
}
if (this.config.shouldSortItems === true && this._isSelectOneElement && !this.config.silent) {
console.warn('shouldSortElements: Type of passed element is \'select-one\', falling back to false.');
if (
this.config.shouldSortItems === true &&
this._isSelectOneElement &&
!this.config.silent
) {
console.warn(
"shouldSortElements: Type of passed element is 'select-one', falling back to false.",
);
}
this._store = new Store(this.render);
@ -204,13 +231,13 @@ class Choices {
render() {
this._currentState = this._store.state;
const stateChanged = (
const stateChanged =
this._currentState.choices !== this._prevState.choices ||
this._currentState.groups !== this._prevState.groups ||
this._currentState.items !== this._prevState.items
);
this._currentState.items !== this._prevState.items;
const shouldRenderChoices = this._isSelectElement;
const shouldRenderItems = this._currentState.items !== this._prevState.items;
const shouldRenderItems =
this._currentState.items !== this._prevState.items;
if (!stateChanged) {
return;
@ -295,15 +322,14 @@ class Choices {
}
removeHighlightedItems(runEvent = false) {
this._store.highlightedActiveItems
.forEach((item) => {
this._removeItem(item);
// If this action was performed by the user
// trigger the event
if (runEvent) {
this._triggerChange(item.value);
}
});
this._store.highlightedActiveItems.forEach(item => {
this._removeItem(item);
// If this action was performed by the user
// trigger the event
if (runEvent) {
this._triggerChange(item.value);
}
});
return this;
}
@ -358,12 +384,11 @@ class Choices {
}
getValue(valueOnly = false) {
const values = this._store.activeItems
.reduce((selectedItems, item) => {
const itemValue = valueOnly ? item.value : item;
selectedItems.push(itemValue);
return selectedItems;
}, []);
const values = this._store.activeItems.reduce((selectedItems, item) => {
const itemValue = valueOnly ? item.value : item;
selectedItems.push(itemValue);
return selectedItems;
}, []);
return this._isSelectOneElement ? values[0] : values;
}
@ -373,10 +398,7 @@ class Choices {
return this;
}
// Convert args to an iterable array
const values = [...args];
values.forEach(value => this._setChoiceOrItem(value));
[...args].forEach(value => this._setChoiceOrItem(value));
return this;
}
@ -395,11 +417,7 @@ class Choices {
}
setChoices(choices = [], value = '', label = '', replaceChoices = false) {
if (
!this._isSelectElement ||
!choices.length ||
!value
) {
if (!this._isSelectElement || !choices.length || !value) {
return this;
}
@ -409,14 +427,9 @@ class Choices {
}
this.containerOuter.removeLoadingState();
const addGroupsAndChoices = (groupOrChoice) => {
const addGroupsAndChoices = groupOrChoice => {
if (groupOrChoice.choices) {
this._addGroup(
groupOrChoice,
(groupOrChoice.id || null),
value,
label,
);
this._addGroup(groupOrChoice, groupOrChoice.id || null, value, label);
} else {
this._addChoice(
groupOrChoice[value],
@ -471,20 +484,23 @@ class Choices {
_createGroupsFragment(groups, choices, fragment) {
const groupFragment = fragment || document.createDocumentFragment();
const getGroupChoices = group => choices.filter((choice) => {
if (this._isSelectOneElement) {
return choice.groupId === group.id;
}
return choice.groupId === group.id && (this.config.renderSelectedChoices === 'always' || !choice.selected);
});
const getGroupChoices = group =>
choices.filter(choice => {
if (this._isSelectOneElement) {
return choice.groupId === group.id;
}
return (
choice.groupId === group.id &&
(this.config.renderSelectedChoices === 'always' || !choice.selected)
);
});
// If sorting is enabled, filter groups
if (this.config.shouldSort) {
groups.sort(this.config.sortFn);
}
groups.forEach((group) => {
groups.forEach(group => {
const groupChoices = getGroupChoices(group);
if (groupChoices.length >= 1) {
const dropdownGroup = this._getTemplate('choiceGroup', group);
@ -499,14 +515,23 @@ class Choices {
_createChoicesFragment(choices, fragment, withinGroup = false) {
// Create a fragment to store our list items (so we don't have to update the DOM for each item)
const choicesFragment = fragment || document.createDocumentFragment();
const { renderSelectedChoices, searchResultLimit, renderChoiceLimit } = this.config;
const {
renderSelectedChoices,
searchResultLimit,
renderChoiceLimit,
} = this.config;
const filter = this._isSearching ? sortByScore : this.config.sortFn;
const appendChoice = (choice) => {
const shouldRender = renderSelectedChoices === 'auto' ?
(this._isSelectOneElement || !choice.selected) :
true;
const appendChoice = choice => {
const shouldRender =
renderSelectedChoices === 'auto'
? this._isSelectOneElement || !choice.selected
: true;
if (shouldRender) {
const dropdownItem = this._getTemplate('choice', choice, this.config.itemSelectText);
const dropdownItem = this._getTemplate(
'choice',
choice,
this.config.itemSelectText,
);
choicesFragment.appendChild(dropdownItem);
}
};
@ -518,14 +543,17 @@ class Choices {
}
// Split array into placeholders and "normal" choices
const { placeholderChoices, normalChoices } = rendererableChoices.reduce((acc, choice) => {
if (choice.placeholder) {
acc.placeholderChoices.push(choice);
} else {
acc.normalChoices.push(choice);
}
return acc;
}, { placeholderChoices: [], normalChoices: [] });
const { placeholderChoices, normalChoices } = rendererableChoices.reduce(
(acc, choice) => {
if (choice.placeholder) {
acc.placeholderChoices.push(choice);
} else {
acc.normalChoices.push(choice);
}
return acc;
},
{ placeholderChoices: [], normalChoices: [] },
);
// If sorting is enabled or the user is searching, filter choices
if (this.config.shouldSort || this._isSearching) {
@ -571,7 +599,7 @@ class Choices {
this.passedElement.options = items;
}
const addItemToFragment = (item) => {
const addItemToFragment = item => {
// Create new list element
const listItem = this._getTemplate('item', item, removeItemButton);
// Append it to list
@ -621,7 +649,9 @@ class Choices {
}
const itemId = element.parentNode.getAttribute('data-id');
const itemToRemove = activeItems.find(item => item.id === parseInt(itemId, 10));
const itemToRemove = activeItems.find(
item => item.id === parseInt(itemId, 10),
);
// Remove item associated with button
this._removeItem(itemToRemove);
@ -647,7 +677,7 @@ class Choices {
// We only want to select one item with a click
// so we deselect any items that aren't the target
// unless shift is being pressed
activeItems.forEach((item) => {
activeItems.forEach(item => {
if (item.id === parseInt(passedId, 10) && !item.highlighted) {
this.highlightItem(item);
} else if (!hasShiftKey && item.highlighted) {
@ -668,7 +698,8 @@ class Choices {
// If we are clicking on an option
const id = element.getAttribute('data-id');
const choice = this._store.getChoiceById(id);
const passedKeyCode = activeItems[0] && activeItems[0].keyCode ? activeItems[0].keyCode : null;
const passedKeyCode =
activeItems[0] && activeItems[0].keyCode ? activeItems[0].keyCode : null;
const hasActiveDropdown = this.dropdown.isActive;
// Update choice keyCode
@ -729,12 +760,17 @@ class Choices {
}
_handleLoadingState(isLoading = true) {
let placeholderItem = this.itemList.getChild(`.${this.config.classNames.placeholder}`);
let placeholderItem = this.itemList.getChild(
`.${this.config.classNames.placeholder}`,
);
if (isLoading) {
this.containerOuter.addLoadingState();
if (this._isSelectOneElement) {
if (!placeholderItem) {
placeholderItem = this._getTemplate('placeholder', this.config.loadingText);
placeholderItem = this._getTemplate(
'placeholder',
this.config.loadingText,
);
this.itemList.append(placeholderItem);
} else {
placeholderItem.innerHTML = this.config.loadingText;
@ -746,47 +782,51 @@ class Choices {
this.containerOuter.removeLoadingState();
if (this._isSelectOneElement) {
placeholderItem.innerHTML = (this._placeholderValue || '');
placeholderItem.innerHTML = this._placeholderValue || '';
} else {
this.input.placeholder = (this._placeholderValue || '');
this.input.placeholder = this._placeholderValue || '';
}
}
}
_canAddItem(activeItems, value) {
let canAddItem = true;
let notice = isType('Function', this.config.addItemText) ?
this.config.addItemText(value) :
this.config.addItemText;
let notice = isType('Function', this.config.addItemText)
? this.config.addItemText(value)
: this.config.addItemText;
if (!this._isSelectOneElement) {
const valueAlreadyExists = !existsInArray(activeItems, value);
if (this.config.maxItemCount > 0 && this.config.maxItemCount <= activeItems.length) {
if (
this.config.maxItemCount > 0 &&
this.config.maxItemCount <= activeItems.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;
notice = isType('Function', this.config.maxItemText)
? this.config.maxItemText(this.config.maxItemCount)
: this.config.maxItemText;
}
if (this.config.regexFilter && this._isTextElement && this.config.addItems && canAddItem) {
if (
this.config.regexFilter &&
this._isTextElement &&
this.config.addItems &&
canAddItem
) {
// If a user has supplied a regular expression filter
// determine whether we can update based on whether
// our regular expression passes
canAddItem = regexFilter(value, this.config.regexFilter);
}
if (
!this.config.duplicateItems &&
!valueAlreadyExists &&
canAddItem
) {
if (!this.config.duplicateItems && !valueAlreadyExists && canAddItem) {
canAddItem = false;
notice = isType('Function', this.config.uniqueItemText) ?
this.config.uniqueItemText(value) :
this.config.uniqueItemText;
notice = isType('Function', this.config.uniqueItemText)
? this.config.uniqueItemText(value)
: this.config.uniqueItemText;
}
}
@ -804,19 +844,18 @@ class Choices {
const parsedResults = isType('Object', results) ? [results] : results;
if (parsedResults && isType('Array', parsedResults) && parsedResults.length) {
if (
parsedResults &&
isType('Array', parsedResults) &&
parsedResults.length
) {
// Remove loading states/text
this._handleLoadingState(false);
// Add each result as a choice
parsedResults.forEach((result) => {
parsedResults.forEach(result => {
if (result.choices) {
const groupId = (result.id || null);
this._addGroup(
result,
groupId,
value,
label,
);
const groupId = result.id || null;
this._addGroup(result, groupId, value, label);
} else {
this._addChoice(
result[value],
@ -842,9 +881,9 @@ class Choices {
_searchChoices(value) {
const newValue = isType('String', value) ? value.trim() : value;
const currentValue = isType('String', this._currentValue) ?
this._currentValue.trim() :
this._currentValue;
const currentValue = isType('String', this._currentValue)
? this._currentValue.trim()
: this._currentValue;
if (newValue.length < 1 && newValue === `${currentValue} `) {
return 0;
@ -853,9 +892,9 @@ class Choices {
// If new value matches the desired length and is not the same as the current value with a space
const haystack = this._store.searchableChoices;
const needle = newValue;
const keys = isType('Array', this.config.searchFields) ?
this.config.searchFields :
[this.config.searchFields];
const keys = isType('Array', this.config.searchFields)
? this.config.searchFields
: [this.config.searchFields];
const options = Object.assign(this.config.fuseOptions, { keys });
const fuse = new Fuse(haystack, options);
const results = fuse.search(needle);
@ -934,7 +973,10 @@ class Choices {
_onKeyDown(event) {
const { target, keyCode, ctrlKey, metaKey } = event;
if (target !== this.input.element && !this.containerOuter.element.contains(target)) {
if (
target !== this.input.element &&
!this.containerOuter.element.contains(target)
) {
return;
}
@ -952,7 +994,7 @@ class Choices {
const downKey = KEY_CODES.DOWN_KEY;
const pageUpKey = KEY_CODES.PAGE_UP_KEY;
const pageDownKey = KEY_CODES.PAGE_DOWN_KEY;
const ctrlDownKey = (ctrlKey || metaKey);
const ctrlDownKey = ctrlKey || metaKey;
// If a user is typing and the dropdown is not active
if (!this._isTextElement && /[a-zA-Z0-9-_ ]/.test(keyString)) {
@ -998,7 +1040,9 @@ class Choices {
if (hasActiveDropdown) {
event.preventDefault();
const highlighted = this.dropdown.getChild(`.${this.config.classNames.highlightedState}`);
const highlighted = this.dropdown.getChild(
`.${this.config.classNames.highlightedState}`,
);
// If we have a highlighted choice
if (highlighted) {
@ -1030,34 +1074,48 @@ class Choices {
this.config.searchEnabled = false;
const directionInt = keyCode === downKey || keyCode === pageDownKey ? 1 : -1;
const skipKey = metaKey || keyCode === pageDownKey || keyCode === pageUpKey;
const directionInt =
keyCode === downKey || keyCode === pageDownKey ? 1 : -1;
const skipKey =
metaKey || keyCode === pageDownKey || keyCode === pageUpKey;
const selectableChoiceIdentifier = '[data-choice-selectable]';
let nextEl;
if (skipKey) {
if (directionInt > 0) {
nextEl = Array.from(
this.dropdown.element.querySelectorAll(selectableChoiceIdentifier),
this.dropdown.element.querySelectorAll(
selectableChoiceIdentifier,
),
).pop();
} else {
nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier);
nextEl = this.dropdown.element.querySelector(
selectableChoiceIdentifier,
);
}
} else {
const currentEl = this.dropdown.element.querySelector(
`.${this.config.classNames.highlightedState}`,
);
if (currentEl) {
nextEl = getAdjacentEl(currentEl, selectableChoiceIdentifier, directionInt);
nextEl = getAdjacentEl(
currentEl,
selectableChoiceIdentifier,
directionInt,
);
} else {
nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier);
nextEl = this.dropdown.element.querySelector(
selectableChoiceIdentifier,
);
}
}
if (nextEl) {
// We prevent default to stop the cursor moving
// when pressing the arrow
if (!isScrolledIntoView(nextEl, this.choiceList.element, directionInt)) {
if (
!isScrolledIntoView(nextEl, this.choiceList.element, directionInt)
) {
this._scrollToChoice(nextEl, directionInt);
}
this._highlightChoice(nextEl);
@ -1148,20 +1206,21 @@ class Choices {
}
_onTouchEnd(event) {
const target = (event.target || event.touches[0].target);
const target = event.target || event.touches[0].target;
// If a user tapped within our container...
if (this._wasTap === true && this.containerOuter.element.contains(target)) {
// ...and we aren't dealing with a single select box, show dropdown/focus input
if (
(target === this.containerOuter.element || target === this.containerInner.element) &&
(target === this.containerOuter.element ||
target === this.containerInner.element) &&
!this._isSelectOneElement
) {
if (this._isTextElement) {
// If text element, we only want to focus the input
this.input.focus();
} else {
// If a select box, we want to show the dropdown
// If a select box, we want to show the dropdown
this.showDropdown(true);
}
}
@ -1179,7 +1238,10 @@ class Choices {
this._isScrollingOnIe = true;
}
if (this.containerOuter.element.contains(target) && target !== this.input.element) {
if (
this.containerOuter.element.contains(target) &&
target !== this.input.element
) {
const activeItems = this._store.activeItems;
const hasShiftKey = shiftKey;
@ -1200,10 +1262,10 @@ class Choices {
}
_onMouseOver({ target }) {
const targetWithinDropdown = (
target === this.dropdown || this.dropdown.element.contains(target)
);
const shouldHighlightChoice = targetWithinDropdown && target.hasAttribute('data-choice');
const targetWithinDropdown =
target === this.dropdown || this.dropdown.element.contains(target);
const shouldHighlightChoice =
targetWithinDropdown && target.hasAttribute('data-choice');
if (shouldHighlightChoice) {
this._highlightChoice(target);
@ -1279,7 +1341,10 @@ class Choices {
_onBlur({ target }) {
// If target is something that concerns us
if (this.containerOuter.element.contains(target) && !this._isScrollingOnIe) {
if (
this.containerOuter.element.contains(target) &&
!this._isScrollingOnIe
) {
const activeItems = this._store.activeItems;
const hasHighlightedItems = activeItems.some(item => item.highlighted);
const blurActions = {
@ -1296,8 +1361,11 @@ class Choices {
},
'select-one': () => {
this.containerOuter.removeFocusState();
if (target === this.input.element ||
(target === this.containerOuter.element && !this.config.searchEnabled)) {
if (
target === this.input.element ||
(target === this.containerOuter.element &&
!this.config.searchEnabled)
) {
this.hideDropdown();
}
},
@ -1334,11 +1402,13 @@ class Choices {
// Distance from bottom of element to top of parent
const choicePos = choice.offsetTop + choiceHeight;
// Scroll position of dropdown
const containerScrollPos = this.choiceList.element.scrollTop + dropdownHeight;
const containerScrollPos =
this.choiceList.element.scrollTop + dropdownHeight;
// Difference between the choice and scroll position
const endPoint = direction > 0 ? (
(this.choiceList.element.scrollTop + choicePos) - containerScrollPos
) : choice.offsetTop;
const endPoint =
direction > 0
? this.choiceList.element.scrollTop + choicePos - containerScrollPos
: choice.offsetTop;
const scrollDown = (scrollPos, strength) => {
const easing = (endPoint - scrollPos) / strength;
@ -1374,19 +1444,21 @@ class Choices {
}
if (continueAnimation) {
requestAnimationFrame((time) => {
requestAnimationFrame(time => {
animateScroll(time, endPoint, direction);
});
}
};
requestAnimationFrame((time) => {
requestAnimationFrame(time => {
animateScroll(time, endPoint, direction);
});
}
_highlightChoice(el = null) {
const choices = Array.from(this.dropdown.element.querySelectorAll('[data-choice-selectable]'));
const choices = Array.from(
this.dropdown.element.querySelectorAll('[data-choice-selectable]'),
);
if (!choices.length) {
return;
@ -1394,12 +1466,14 @@ class Choices {
let passedEl = el;
const highlightedChoices = Array.from(
this.dropdown.element.querySelectorAll(`.${this.config.classNames.highlightedState}`),
this.dropdown.element.querySelectorAll(
`.${this.config.classNames.highlightedState}`,
),
);
const hasActiveDropdown = this.dropdown.isActive;
// Remove any highlighted choices
highlightedChoices.forEach((choice) => {
highlightedChoices.forEach(choice => {
choice.classList.remove(this.config.classNames.highlightedState);
choice.setAttribute('aria-selected', 'false');
});
@ -1547,7 +1621,9 @@ class Choices {
const choices = this._store.choices;
const choiceLabel = label || value;
const choiceId = choices ? choices.length + 1 : 1;
const choiceElementId = `${this._baseId}-${this._idNames.itemChoice}-${choiceId}`;
const choiceElementId = `${this._baseId}-${
this._idNames.itemChoice
}-${choiceId}`;
this._store.dispatch(
addChoice(
@ -1581,27 +1657,21 @@ class Choices {
}
_addGroup(group, id, valueKey = 'value', labelKey = 'label') {
const groupChoices = isType('Object', group) ?
group.choices :
Array.from(group.getElementsByTagName('OPTION'));
const groupChoices = isType('Object', group)
? group.choices
: Array.from(group.getElementsByTagName('OPTION'));
const groupId = id || Math.floor(new Date().valueOf() * Math.random());
const isDisabled = group.disabled ? group.disabled : false;
if (groupChoices) {
this._store.dispatch(
addGroup(
group.label,
groupId,
true,
isDisabled,
),
);
this._store.dispatch(addGroup(group.label, groupId, true, isDisabled));
const addGroupChoices = (choice) => {
const isOptDisabled = choice.disabled || (choice.parentNode && choice.parentNode.disabled);
const addGroupChoices = choice => {
const isOptDisabled =
choice.disabled || (choice.parentNode && choice.parentNode.disabled);
this._addChoice(
choice[valueKey],
(isType('Object', choice)) ? choice[labelKey] : choice.innerHTML,
isType('Object', choice) ? choice[labelKey] : choice.innerHTML,
choice.selected,
isOptDisabled,
groupId,
@ -1613,12 +1683,7 @@ class Choices {
groupChoices.forEach(addGroupChoices);
} else {
this._store.dispatch(
addGroup(
group.label,
group.id,
false,
group.disabled,
),
addGroup(group.label, group.id, false, group.disabled),
);
}
}
@ -1636,7 +1701,10 @@ class Choices {
const { callbackOnCreateTemplates } = this.config;
let userTemplates = {};
if (callbackOnCreateTemplates && isType('Function', callbackOnCreateTemplates)) {
if (
callbackOnCreateTemplates &&
isType('Function', callbackOnCreateTemplates)
) {
userTemplates = callbackOnCreateTemplates.call(this, strToEl);
}
@ -1645,7 +1713,8 @@ class Choices {
_createElements() {
const direction = this.passedElement.element.getAttribute('dir') || 'ltr';
const containerOuter = this._getTemplate('containerOuter',
const containerOuter = this._getTemplate(
'containerOuter',
direction,
this._isSelectElement,
this._isSelectOneElement,
@ -1654,7 +1723,10 @@ class Choices {
);
const containerInner = this._getTemplate('containerInner');
const itemList = this._getTemplate('itemList', this._isSelectOneElement);
const choiceList = this._getTemplate('choiceList', this._isSelectOneElement);
const choiceList = this._getTemplate(
'choiceList',
this._isSelectOneElement,
);
const input = this._getTemplate('input');
const dropdown = this._getTemplate('dropdown');
@ -1702,7 +1774,7 @@ class Choices {
this.containerOuter.wrap(this.containerInner.element);
if (this._isSelectOneElement) {
this.input.placeholder = (this.config.searchPlaceholderValue || '');
this.input.placeholder = this.config.searchPlaceholderValue || '';
} else if (this._placeholderValue) {
this.input.placeholder = this._placeholderValue;
this.input.setWidth(true);
@ -1723,7 +1795,10 @@ class Choices {
if (!this._isSelectOneElement) {
this.containerInner.element.appendChild(this.input.element);
} else if (this.config.searchEnabled) {
this.dropdown.element.insertBefore(this.input.element, this.dropdown.element.firstChild);
this.dropdown.element.insertBefore(
this.input.element,
this.dropdown.element.firstChild,
);
}
if (this._isSelectElement) {
@ -1742,7 +1817,10 @@ class Choices {
if (passedGroups && passedGroups.length) {
// If we have a placeholder option
const placeholderChoice = this.passedElement.placeholderOption;
if (placeholderChoice && placeholderChoice.parentNode.tagName === 'SELECT') {
if (
placeholderChoice &&
placeholderChoice.parentNode.tagName === 'SELECT'
) {
this._addChoice(
placeholderChoice.value,
placeholderChoice.innerHTML,
@ -1750,12 +1828,12 @@ class Choices {
placeholderChoice.disabled,
undefined,
undefined,
/* placeholder */ true,
/* placeholder */ true,
);
}
passedGroups.forEach((group) => {
this._addGroup(group, (group.id || null));
passedGroups.forEach(group => {
this._addGroup(group, group.id || null);
});
} else {
const passedOptions = this.passedElement.options;
@ -1763,7 +1841,7 @@ class Choices {
const allChoices = this._presetChoices;
// Create array of options from option elements
passedOptions.forEach((o) => {
passedOptions.forEach(o => {
allChoices.push({
value: o.value,
label: o.innerHTML,
@ -1789,7 +1867,8 @@ class Choices {
// If there is a selected choice already or the choice is not
// the first in the array, add each choice normally
// Otherwise pre-select the first choice in the array if it's a single select
const shouldPreselect = this._isSelectOneElement && !hasSelectedChoice && index === 0;
const shouldPreselect =
this._isSelectOneElement && !hasSelectedChoice && index === 0;
const isSelected = shouldPreselect ? true : choice.selected;
const isDisabled = shouldPreselect ? false : choice.disabled;
@ -1822,7 +1901,7 @@ class Choices {
}
_addPredefinedItems() {
const handlePresetItem = (item) => {
const handlePresetItem = item => {
const itemType = getType(item);
if (itemType === 'Object') {
if (!item.value) {
@ -1859,7 +1938,8 @@ class Choices {
item.value,
item.label,
true,
false, -1,
false,
-1,
item.customProperties,
item.placeholder,
);
@ -1876,13 +1956,7 @@ class Choices {
},
string: () => {
if (!this._isTextElement) {
this._addChoice(
item,
item,
true,
false, -1,
null,
);
this._addChoice(item, item, true, false, -1, null);
} else {
this._addItem(item);
}
@ -1895,7 +1969,9 @@ class Choices {
_findAndSelectChoiceByValue(val) {
const choices = this._store.choices;
// Check 'value' property exists and the choice isn't already selected
const foundChoice = choices.find(choice => this.config.itemComparer(choice.value, val));
const foundChoice = choices.find(choice =>
this.config.itemComparer(choice.value, val),
);
if (foundChoice && !foundChoice.selected) {
this._addItem(
@ -1911,10 +1987,13 @@ class Choices {
}
_generateInstances(elements, config) {
return elements.reduce((instances, element) => {
instances.push(new Choices(element, config));
return instances;
}, [this]);
return elements.reduce(
(instances, element) => {
instances.push(new Choices(element, config));
return instances;
},
[this],
);
}
static _generateConfig(userConfig) {
@ -1934,9 +2013,10 @@ class Choices {
return false;
}
return this.config.placeholder ?
(this.config.placeholderValue || this.passedElement.element.getAttribute('placeholder')) :
false;
return this.config.placeholder
? this.config.placeholderValue ||
this.passedElement.element.getAttribute('placeholder')
: false;
}
_renderChoices() {
@ -1955,22 +2035,32 @@ class Choices {
if (activeGroups.length >= 1 && !this._isSearching) {
// If we have a placeholder choice along with groups
const activePlaceholders = activeChoices.filter(
activeChoice => activeChoice.placeholder === true && activeChoice.groupId === -1,
);
activeChoice =>
activeChoice.placeholder === true && activeChoice.groupId === -1,
);
if (activePlaceholders.length >= 1) {
choiceListFragment = this._createChoicesFragment(activePlaceholders, choiceListFragment);
choiceListFragment = this._createChoicesFragment(
activePlaceholders,
choiceListFragment,
);
}
choiceListFragment = this._createGroupsFragment(
activeGroups,
activeChoices,
choiceListFragment,
);
activeGroups,
activeChoices,
choiceListFragment,
);
} else if (activeChoices.length >= 1) {
choiceListFragment = this._createChoicesFragment(activeChoices, choiceListFragment);
choiceListFragment = this._createChoicesFragment(
activeChoices,
choiceListFragment,
);
}
// If we have choices to show
if (choiceListFragment.childNodes && choiceListFragment.childNodes.length > 0) {
if (
choiceListFragment.childNodes &&
choiceListFragment.childNodes.length > 0
) {
const activeItems = this._store.activeItems;
const canAddItem = this._canAddItem(activeItems, this.input.value);
@ -1989,15 +2079,15 @@ class Choices {
let notice;
if (this._isSearching) {
notice = isType('Function', this.config.noResultsText) ?
this.config.noResultsText() :
this.config.noResultsText;
notice = isType('Function', this.config.noResultsText)
? this.config.noResultsText()
: this.config.noResultsText;
dropdownItem = this._getTemplate('notice', notice, 'no-results');
} else {
notice = isType('Function', this.config.noChoicesText) ?
this.config.noChoicesText() :
this.config.noChoicesText;
notice = isType('Function', this.config.noChoicesText)
? this.config.noChoicesText()
: this.config.noChoicesText;
dropdownItem = this._getTemplate('notice', notice, 'no-choices');
}

View file

@ -45,7 +45,7 @@ describe('choices', () => {
instance.init();
});
it('doesn\'t set initialise flag', () => {
it("doesn't set initialise flag", () => {
expect(instance.initialised).to.not.equal(false);
});
});
@ -123,7 +123,7 @@ describe('choices', () => {
instance.destroy();
});
it('doesn\'t set initialise flag', () => {
it("doesn't set initialise flag", () => {
expect(instance.initialised).to.not.equal(true);
});
});
@ -161,7 +161,9 @@ describe('choices', () => {
it('reverts outer container', () => {
expect(containerOuterUnwrapSpy.called).to.equal(true);
expect(containerOuterUnwrapSpy.lastCall.args[0]).to.equal(instance.passedElement.element);
expect(containerOuterUnwrapSpy.lastCall.args[0]).to.equal(
instance.passedElement.element,
);
});
it('clears store', () => {
@ -263,7 +265,6 @@ describe('choices', () => {
inputDisableSpy = spy(instance.input, 'disable');
});
afterEach(() => {
removeEventListenersSpy.restore();
passedElementDisableSpy.restore();
@ -374,24 +375,26 @@ describe('choices', () => {
expect(output).to.eql(instance);
});
it('opens containerOuter', (done) => {
it('opens containerOuter', done => {
requestAnimationFrame(() => {
expect(containerOuterOpenSpy.called).to.equal(true);
done();
});
});
it('shows dropdown with blurInput flag', (done) => {
it('shows dropdown with blurInput flag', done => {
requestAnimationFrame(() => {
expect(dropdownShowSpy.called).to.equal(true);
done();
});
});
it('triggers event on passedElement', (done) => {
it('triggers event on passedElement', done => {
requestAnimationFrame(() => {
expect(passedElementTriggerEventStub.called).to.equal(true);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.eql(EVENTS.showDropdown);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.eql(
EVENTS.showDropdown,
);
expect(passedElementTriggerEventStub.lastCall.args[1]).to.eql({});
done();
});
@ -404,7 +407,7 @@ describe('choices', () => {
output = instance.showDropdown(true);
});
it('focuses input', (done) => {
it('focuses input', done => {
requestAnimationFrame(() => {
expect(inputFocusSpy.called).to.equal(true);
done();
@ -425,7 +428,10 @@ describe('choices', () => {
containerOuterCloseSpy = spy(instance.containerOuter, 'close');
dropdownHideSpy = spy(instance.dropdown, 'hide');
inputBlurSpy = spy(instance.input, 'blur');
inputRemoveActiveDescendantSpy = spy(instance.input, 'removeActiveDescendant');
inputRemoveActiveDescendantSpy = spy(
instance.input,
'removeActiveDescendant',
);
passedElementTriggerEventStub = stub();
instance.passedElement.triggerEvent = passedElementTriggerEventStub;
@ -465,24 +471,26 @@ describe('choices', () => {
expect(output).to.eql(instance);
});
it('closes containerOuter', (done) => {
it('closes containerOuter', done => {
requestAnimationFrame(() => {
expect(containerOuterCloseSpy.called).to.equal(true);
done();
});
});
it('hides dropdown with blurInput flag', (done) => {
it('hides dropdown with blurInput flag', done => {
requestAnimationFrame(() => {
expect(dropdownHideSpy.called).to.equal(true);
done();
});
});
it('triggers event on passedElement', (done) => {
it('triggers event on passedElement', done => {
requestAnimationFrame(() => {
expect(passedElementTriggerEventStub.called).to.equal(true);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.eql(EVENTS.hideDropdown);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.eql(
EVENTS.hideDropdown,
);
expect(passedElementTriggerEventStub.lastCall.args[1]).to.eql({});
done();
});
@ -495,14 +503,14 @@ describe('choices', () => {
output = instance.hideDropdown(true);
});
it('removes active descendants', (done) => {
it('removes active descendants', done => {
requestAnimationFrame(() => {
expect(inputRemoveActiveDescendantSpy.called).to.equal(true);
done();
});
});
it('blurs input', (done) => {
it('blurs input', done => {
requestAnimationFrame(() => {
expect(inputBlurSpy.called).to.equal(true);
done();
@ -624,7 +632,9 @@ describe('choices', () => {
it('triggers event with null groupValue', () => {
expect(passedElementTriggerEventStub.called).to.equal(true);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(EVENTS.highlightItem);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(
EVENTS.highlightItem,
);
expect(passedElementTriggerEventStub.lastCall.args[1]).to.eql({
id: item.id,
value: item.value,
@ -642,7 +652,9 @@ describe('choices', () => {
it('triggers event with groupValue', () => {
expect(passedElementTriggerEventStub.called).to.equal(true);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(EVENTS.highlightItem);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(
EVENTS.highlightItem,
);
expect(passedElementTriggerEventStub.lastCall.args[1]).to.eql({
id: item.id,
value: item.value,
@ -658,7 +670,7 @@ describe('choices', () => {
output = instance.highlightItem(item, false);
});
it('doesn\'t trigger event', () => {
it("doesn't trigger event", () => {
expect(passedElementTriggerEventStub.called).to.equal(false);
});
@ -735,7 +747,9 @@ describe('choices', () => {
it('triggers event with null groupValue', () => {
expect(passedElementTriggerEventStub.called).to.equal(true);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(EVENTS.highlightItem);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(
EVENTS.highlightItem,
);
expect(passedElementTriggerEventStub.lastCall.args[1]).to.eql({
id: item.id,
value: item.value,
@ -753,7 +767,9 @@ describe('choices', () => {
it('triggers event with groupValue', () => {
expect(passedElementTriggerEventStub.called).to.equal(true);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(EVENTS.highlightItem);
expect(passedElementTriggerEventStub.lastCall.args[0]).to.equal(
EVENTS.highlightItem,
);
expect(passedElementTriggerEventStub.lastCall.args[1]).to.eql({
id: item.id,
value: item.value,
@ -769,7 +785,7 @@ describe('choices', () => {
output = instance.highlightItem(item, false);
});
it('doesn\'t trigger event', () => {
it("doesn't trigger event", () => {
expect(passedElementTriggerEventStub.called).to.equal(false);
});
@ -1005,7 +1021,7 @@ describe('choices', () => {
returnsInstance(output);
it('sets loading state', (done) => {
it('sets loading state', done => {
requestAnimationFrame(() => {
expect(handleLoadingStateStub.called).to.equal(true);
done();
@ -1108,15 +1124,14 @@ describe('choices', () => {
it('sets each choice with same value', () => {
expect(findAndSelectChoiceByValueStub.called).to.equal(true);
expect(findAndSelectChoiceByValueStub.firstCall.args[0]).to.equal(value);
expect(findAndSelectChoiceByValueStub.firstCall.args[0]).to.equal(
value,
);
});
});
describe('passing an array of values', () => {
const values = [
'Value 1',
'Value 2',
];
const values = ['Value 1', 'Value 2'];
beforeEach(() => {
output = instance.setChoiceByValue(values);
@ -1126,8 +1141,12 @@ describe('choices', () => {
it('sets each choice with same value', () => {
expect(findAndSelectChoiceByValueStub.callCount).to.equal(2);
expect(findAndSelectChoiceByValueStub.firstCall.args[0]).to.equal(values[0]);
expect(findAndSelectChoiceByValueStub.secondCall.args[0]).to.equal(values[1]);
expect(findAndSelectChoiceByValueStub.firstCall.args[0]).to.equal(
values[0],
);
expect(findAndSelectChoiceByValueStub.secondCall.args[0]).to.equal(
values[1],
);
});
});
});
@ -1173,7 +1192,7 @@ describe('choices', () => {
});
it('returns all active item values', () => {
expect(output).to.eql(items.map((item => item.value)));
expect(output).to.eql(items.map(item => item.value));
});
});
});
@ -1315,9 +1334,11 @@ describe('choices', () => {
},
];
beforeEach(() => {
highlightedActiveItemsStub = stub(instance._store, 'highlightedActiveItems').get(() => items);
highlightedActiveItemsStub = stub(
instance._store,
'highlightedActiveItems',
).get(() => items);
removeItemStub = stub();
triggerChangeStub = stub();
@ -1557,7 +1578,9 @@ describe('choices', () => {
expect(output).to.be.instanceOf(DocumentFragment);
expect(elementToWrapFragment.children[0]).to.eql(childElement);
expect(elementToWrapFragment.querySelectorAll('[data-group]').length).to.equal(2);
expect(
elementToWrapFragment.querySelectorAll('[data-group]').length,
).to.equal(2);
});
});
@ -1568,7 +1591,9 @@ describe('choices', () => {
elementToWrapFragment.appendChild(output);
expect(output).to.be.instanceOf(DocumentFragment);
expect(elementToWrapFragment.querySelectorAll('[data-group]').length).to.equal(2);
expect(
elementToWrapFragment.querySelectorAll('[data-group]').length,
).to.equal(2);
});
});

View file

@ -16,7 +16,7 @@ export default class Container {
/**
* Add event listeners
*/
*/
addEventListeners() {
this.element.addEventListener('focus', this._onFocus);
this.element.addEventListener('blur', this._onBlur);
@ -24,7 +24,7 @@ export default class Container {
/**
* Remove event listeners
*/
*/
/** */
removeEventListeners() {
@ -138,10 +138,7 @@ export default class Container {
unwrap(element) {
// Move passed element outside this element
this.element.parentNode.insertBefore(
element,
this.element,
);
this.element.parentNode.insertBefore(element, this.element);
// Remove this element
this.element.parentNode.removeChild(this.element);
}

View file

@ -139,21 +139,32 @@ describe('components/container', () => {
});
describe('setActiveDescendant', () => {
it('sets element\'s aria-activedescendant attribute with passed descendant ID', () => {
it("sets element's aria-activedescendant attribute with passed descendant ID", () => {
const activeDescendantID = '1234';
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(null);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
null,
);
instance.setActiveDescendant(activeDescendantID);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(activeDescendantID);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
activeDescendantID,
);
});
});
describe('removeActiveDescendant', () => {
it('remove elememnt\'s aria-activedescendant attribute', () => {
it("remove elememnt's aria-activedescendant attribute", () => {
const activeDescendantID = '1234';
instance.element.setAttribute('aria-activedescendant', activeDescendantID);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(activeDescendantID);
instance.element.setAttribute(
'aria-activedescendant',
activeDescendantID,
);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
activeDescendantID,
);
instance.removeActiveDescendant();
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(null);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
null,
);
});
});
@ -163,7 +174,9 @@ describe('components/container', () => {
});
it('adds open state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.openState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.openState),
).to.equal(true);
});
it('sets aria-expanded attribute to true', () => {
@ -188,7 +201,9 @@ describe('components/container', () => {
});
it('adds adds flipped state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.flippedState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.flippedState),
).to.equal(true);
});
it('sets isFlipped flag to true', () => {
@ -203,7 +218,9 @@ describe('components/container', () => {
});
it('adds open state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.openState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.openState),
).to.equal(false);
});
it('sets aria-expanded attribute to true', () => {
@ -221,7 +238,9 @@ describe('components/container', () => {
});
it('removes adds flipped state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.flippedState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.flippedState),
).to.equal(false);
});
it('sets isFlipped flag to false', () => {
@ -264,9 +283,13 @@ describe('components/container', () => {
});
it('adds focus state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState),
).to.equal(false);
instance.addFocusState();
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState),
).to.equal(true);
});
});
@ -276,9 +299,13 @@ describe('components/container', () => {
});
it('removes focus state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState),
).to.equal(true);
instance.removeFocusState();
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.focusState),
).to.equal(false);
});
});
@ -288,9 +315,13 @@ describe('components/container', () => {
});
it('removes disabled state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState),
).to.equal(true);
instance.enable();
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState),
).to.equal(false);
});
it('removes aria-disabled attribute', () => {
@ -322,9 +353,13 @@ describe('components/container', () => {
});
it('removes disabled state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState),
).to.equal(false);
instance.disable();
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.disabledState),
).to.equal(true);
});
it('removes aria-disabled attribute', () => {
@ -366,7 +401,9 @@ describe('components/container', () => {
it('wraps passed element inside element', () => {
expect(instance.element.querySelector('div#wrap-test')).to.equal(null);
instance.wrap(document.querySelector('div#wrap-test'));
expect(instance.element.querySelector('div#wrap-test')).to.equal(elementToWrap);
expect(instance.element.querySelector('div#wrap-test')).to.equal(
elementToWrap,
);
});
});
@ -385,10 +422,14 @@ describe('components/container', () => {
});
it('moves wrapped element outside of element', () => {
expect(instance.element.querySelector('div#unwrap-test')).to.be.instanceof(HTMLElement);
expect(
instance.element.querySelector('div#unwrap-test'),
).to.be.instanceof(HTMLElement);
instance.unwrap(elementToUnwrap);
expect(instance.element.querySelector('div#unwrap-test')).to.equal(null);
expect(document.querySelector('div#unwrap-test')).to.be.instanceof(HTMLElement);
expect(document.querySelector('div#unwrap-test')).to.be.instanceof(
HTMLElement,
);
});
it('removes element from DOM', () => {
@ -404,9 +445,13 @@ describe('components/container', () => {
});
it('adds loading state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState),
).to.equal(false);
instance.addLoadingState();
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState),
).to.equal(true);
});
it('sets aria-busy attribute to true', () => {
@ -428,9 +473,13 @@ describe('components/container', () => {
});
it('removes loading state class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState),
).to.equal(true);
instance.removeLoadingState();
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.loadingState),
).to.equal(false);
});
it('removes aria-busy attribute', () => {

View file

@ -12,7 +12,9 @@ export default class Dropdown {
*/
distanceFromTopWindow() {
this.dimensions = this.element.getBoundingClientRect();
this.position = Math.ceil(this.dimensions.top + window.pageYOffset + this.element.offsetHeight);
this.position = Math.ceil(
this.dimensions.top + window.pageYOffset + this.element.offsetHeight,
);
return this.position;
}

View file

@ -50,7 +50,9 @@ describe('components/dropdown', () => {
width: 0,
};
getBoundingClientRectStub = sinon.stub(instance.element, 'getBoundingClientRect').returns(dimensions);
getBoundingClientRectStub = sinon
.stub(instance.element, 'getBoundingClientRect')
.returns(dimensions);
window.pageYOffset = 50;
});
@ -107,7 +109,9 @@ describe('components/dropdown', () => {
});
it('adds active class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.activeState)).to.equal(true);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.activeState),
).to.equal(true);
});
it('sets expanded attribute', () => {
@ -135,7 +139,9 @@ describe('components/dropdown', () => {
});
it('adds active class', () => {
expect(instance.element.classList.contains(DEFAULT_CLASSNAMES.activeState)).to.equal(false);
expect(
instance.element.classList.contains(DEFAULT_CLASSNAMES.activeState),
).to.equal(false);
});
it('sets expanded attribute', () => {

View file

@ -5,11 +5,4 @@ import List from './list';
import WrappedInput from './wrapped-input';
import WrappedSelect from './wrapped-select';
export {
Dropdown,
Container,
Input,
List,
WrappedInput,
WrappedSelect,
};
export { Dropdown, Container, Input, List, WrappedInput, WrappedSelect };

View file

@ -92,7 +92,7 @@ export default class Input {
// length than 75% of the placeholder. This stops the input jumping around.
if (
(this.element.value &&
this.element.value.length >= (this._placeholderValue.length / 1.25)) ||
this.element.value.length >= this._placeholderValue.length / 1.25) ||
enforceWidth
) {
this.element.style.width = this.calcWidth();

View file

@ -86,7 +86,6 @@ describe('components/input', () => {
setWidthStub.restore();
});
describe('when element is select one', () => {
it('does not set input width', () => {
instance.type = 'select-one';
@ -207,7 +206,6 @@ describe('components/input', () => {
});
});
describe('blur', () => {
let blurStub;
@ -220,7 +218,7 @@ describe('components/input', () => {
});
describe('when element is not focussed', () => {
it('doesn\'t blur element', () => {
it("doesn't blur element", () => {
instance.isFocussed = false;
instance.blur();
expect(blurStub.callCount).to.equal(0);
@ -247,14 +245,14 @@ describe('components/input', () => {
setWidthStub.restore();
});
it('removes the element\'s value if it has one', () => {
it("removes the element's value if it has one", () => {
instance.element.value = 'test';
expect(instance.element.value).to.equal('test');
instance.clear();
expect(instance.element.value).to.equal('');
});
it('sets the element\'s width if flag passed', () => {
it("sets the element's width if flag passed", () => {
expect(setWidthStub.callCount).to.equal(0);
instance.clear(true);
expect(setWidthStub.callCount).to.equal(1);
@ -350,21 +348,32 @@ describe('components/input', () => {
});
describe('setActiveDescendant', () => {
it('sets element\'s aria-activedescendant attribute with passed descendant ID', () => {
it("sets element's aria-activedescendant attribute with passed descendant ID", () => {
const activeDescendantID = '1234';
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(null);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
null,
);
instance.setActiveDescendant(activeDescendantID);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(activeDescendantID);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
activeDescendantID,
);
});
});
describe('removeActiveDescendant', () => {
it('remove elememnt\'s aria-activedescendant attribute', () => {
it("remove elememnt's aria-activedescendant attribute", () => {
const activeDescendantID = '1234';
instance.element.setAttribute('aria-activedescendant', activeDescendantID);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(activeDescendantID);
instance.element.setAttribute(
'aria-activedescendant',
activeDescendantID,
);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
activeDescendantID,
);
instance.removeActiveDescendant();
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(null);
expect(instance.element.getAttribute('aria-activedescendant')).to.equal(
null,
);
});
});
});

View file

@ -30,7 +30,7 @@ export default class List {
/**
* Find element that matches passed selector
* @return {HTMLElement}
*/
*/
getChild(selector) {
return this.element.querySelector(selector);
}

View file

@ -24,7 +24,7 @@ describe('components/list', () => {
});
describe('clear', () => {
it('clears element\'s inner HTML', () => {
it("clears element's inner HTML", () => {
const innerHTML = 'test';
instance.element.innerHTML = innerHTML;
expect(instance.element.innerHTML).to.equal(innerHTML);
@ -59,11 +59,12 @@ describe('components/list', () => {
elementToAppend.classList.add(childClass);
expect(instance.element.querySelector(`.${childClass}`)).to.equal(null);
instance.append(elementToAppend);
expect(instance.element.querySelector(`.${childClass}`)).to.equal(elementToAppend);
expect(instance.element.querySelector(`.${childClass}`)).to.equal(
elementToAppend,
);
});
});
describe('getChild', () => {
let childElement;
const childClass = 'test-element';

View file

@ -10,7 +10,7 @@ describe('components/wrappedElement', () => {
element = document.createElement('select');
instance = new WrappedElement({
element,
classNames: DEFAULT_CLASSNAMES,
classNames: DEFAULT_CLASSNAMES
});
});
@ -50,11 +50,17 @@ describe('components/wrappedElement', () => {
it('hides element', () => {
instance.conceal();
expect(instance.element.tabIndex).to.equal(-1);
expect(instance.element.classList.contains(instance.classNames.input)).to.equal(true);
expect(instance.element.classList.contains(instance.classNames.hiddenState)).to.equal(true);
expect(
instance.element.classList.contains(instance.classNames.input)
).to.equal(true);
expect(
instance.element.classList.contains(instance.classNames.hiddenState)
).to.equal(true);
expect(instance.element.getAttribute('aria-hidden')).to.equal('true');
expect(instance.element.getAttribute('data-choice')).to.equal('active');
expect(instance.element.getAttribute('data-choice-orig-style')).to.equal(originalStyling);
expect(instance.element.getAttribute('data-choice-orig-style')).to.equal(
originalStyling
);
});
});
@ -69,12 +75,18 @@ describe('components/wrappedElement', () => {
it('shows element', () => {
instance.reveal();
expect(instance.element.tabIndex).to.equal(0);
expect(instance.element.classList.contains(instance.classNames.input)).to.equal(false);
expect(instance.element.classList.contains(instance.classNames.hiddenState)).to.equal(false);
expect(
instance.element.classList.contains(instance.classNames.input)
).to.equal(false);
expect(
instance.element.classList.contains(instance.classNames.hiddenState)
).to.equal(false);
expect(instance.element.getAttribute('style')).to.equal(originalStyling);
expect(instance.element.getAttribute('aria-hidden')).to.equal(null);
expect(instance.element.getAttribute('data-choice')).to.equal(null);
expect(instance.element.getAttribute('data-choice-orig-style')).to.equal(null);
expect(instance.element.getAttribute('data-choice-orig-style')).to.equal(
null
);
});
});
@ -127,9 +139,9 @@ describe('components/wrappedElement', () => {
});
describe('triggerEvent', () => {
it('fires event on element using passed eventType and data', (done) => {
it('fires event on element using passed eventType and data', done => {
const data = {
test: true,
test: true
};
instance.element.addEventListener('testEvent', ({ detail }) => {

View file

@ -34,7 +34,7 @@ describe('components/wrappedInput', () => {
});
describe('inherited methods', () => {
['conceal', 'reveal', 'enable', 'disable'].forEach((method) => {
['conceal', 'reveal', 'enable', 'disable'].forEach(method => {
describe(method, () => {
beforeEach(() => {
stub(WrappedElement.prototype, method);
@ -72,7 +72,9 @@ describe('components/wrappedInput', () => {
it('sets delimited value of element based on passed data', () => {
expect(instance.element.value).to.equal('');
instance.value = data;
expect(instance.value).to.equal(`Value 1${delimiter}Value 2${delimiter}Value 3`);
expect(instance.value).to.equal(
`Value 1${delimiter}Value 2${delimiter}Value 3`,
);
});
});
});

View file

@ -20,7 +20,7 @@ export default class WrappedSelect extends WrappedElement {
set options(options) {
const fragment = document.createDocumentFragment();
const addOptionToFragment = (data) => {
const addOptionToFragment = data => {
// Create a standard select option
const template = templates.option(data);
// Append it to fragment

View file

@ -47,7 +47,7 @@ describe('components/wrappedSelect', () => {
});
describe('inherited methods', () => {
['conceal', 'reveal', 'enable', 'disable'].forEach((method) => {
['conceal', 'reveal', 'enable', 'disable'].forEach(method => {
beforeEach(() => {
stub(WrappedElement.prototype, method);
});
@ -76,7 +76,7 @@ describe('components/wrappedSelect', () => {
it('returns all option elements', () => {
const { options } = instance;
expect(options).to.be.an('array');
options.forEach((option) => {
options.forEach(option => {
expect(option).to.be.instanceOf(HTMLOptionElement);
});
});
@ -91,7 +91,7 @@ describe('components/wrappedSelect', () => {
const { optionGroups } = instance;
expect(optionGroups.length).to.equal(3);
optionGroups.forEach((option) => {
optionGroups.forEach(option => {
expect(option).to.be.instanceOf(HTMLOptGroupElement);
});
});
@ -141,9 +141,13 @@ describe('components/wrappedSelect', () => {
describe('appendDocFragment', () => {
it('empties contents of element', () => {
expect(instance.element.getElementsByTagName('option').length).to.equal(4);
expect(instance.element.getElementsByTagName('option').length).to.equal(
4,
);
instance.appendDocFragment(document.createDocumentFragment());
expect(instance.element.getElementsByTagName('option').length).to.equal(0);
expect(instance.element.getElementsByTagName('option').length).to.equal(
0,
);
});
it('appends passed fragment to element', () => {
@ -153,7 +157,9 @@ describe('components/wrappedSelect', () => {
fragment.appendChild(elementToAppend);
expect(instance.element.querySelector('#fragment-target')).to.equal(null);
instance.appendDocFragment(fragment);
expect(instance.element.querySelector('#fragment-target')).to.eql(elementToAppend);
expect(instance.element.querySelector('#fragment-target')).to.eql(
elementToAppend,
);
});
});
});

View file

@ -65,7 +65,7 @@ export const DEFAULT_CONFIG = {
uniqueItemText: 'Only unique values can be added.',
addItemText: value => `Press Enter to add <b>"${stripHTML(value)}"</b>`,
maxItemText: maxItemCount => `Only ${maxItemCount} values can be added.`,
itemComparer: (choice, item) => (choice === item),
itemComparer: (choice, item) => choice === item,
fuseOptions: {
includeScore: true,
},

View file

@ -140,7 +140,7 @@ describe('constants', () => {
});
it('exports each value as a number', () => {
Object.keys(KEY_CODES).forEach((key) => {
Object.keys(KEY_CODES).forEach(key => {
expect(KEY_CODES[key]).to.be.a('number');
});
});

View file

@ -43,11 +43,7 @@ describe('utils', () => {
];
it('returns an array of item values', () => {
const expectedResponse = [
items[0].value,
items[1].value,
items[2].value,
];
const expectedResponse = [items[0].value, items[1].value, items[2].value];
const actualResponse = reduceToValues(items);
expect(actualResponse).to.eql(expectedResponse);

View file

@ -8,26 +8,29 @@ export default function choices(state = defaultState, action) {
A selected choice has been added to the passed input's value (added as an item)
An active choice appears within the choice dropdown
*/
return [...state, {
id: action.id,
elementId: action.elementId,
groupId: action.groupId,
value: action.value,
label: (action.label || action.value),
disabled: (action.disabled || false),
selected: false,
active: true,
score: 9999,
customProperties: action.customProperties,
placeholder: (action.placeholder || false),
keyCode: null,
}];
return [
...state,
{
id: action.id,
elementId: action.elementId,
groupId: action.groupId,
value: action.value,
label: action.label || action.value,
disabled: action.disabled || false,
selected: false,
active: true,
score: 9999,
customProperties: action.customProperties,
placeholder: action.placeholder || false,
keyCode: null,
},
];
}
case 'ADD_ITEM': {
// If all choices need to be activated
if (action.activateOptions) {
return state.map((obj) => {
return state.map(obj => {
const choice = obj;
choice.active = action.active;
return choice;
@ -37,7 +40,7 @@ export default function choices(state = defaultState, action) {
// When an item is added and it has an associated choice,
// we want to disable it so it can't be chosen again
if (action.choiceId > -1) {
return state.map((obj) => {
return state.map(obj => {
const choice = obj;
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = true;
@ -53,7 +56,7 @@ export default function choices(state = defaultState, action) {
// When an item is removed and it has an associated choice,
// we want to re-enable it so it can be chosen again
if (action.choiceId > -1) {
return state.map((obj) => {
return state.map(obj => {
const choice = obj;
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = false;
@ -66,7 +69,7 @@ export default function choices(state = defaultState, action) {
}
case 'FILTER_CHOICES': {
return state.map((obj) => {
return state.map(obj => {
const choice = obj;
// Set active state based on whether choice is
// within filtered results
@ -83,7 +86,7 @@ export default function choices(state = defaultState, action) {
}
case 'ACTIVATE_CHOICES': {
return state.map((obj) => {
return state.map(obj => {
const choice = obj;
choice.active = action.active;
return choice;

View file

@ -174,15 +174,16 @@ describe('reducers/choices', () => {
score,
};
const actualResponse = choices(state, {
type: 'FILTER_CHOICES',
results: [{
item: {
id,
results: [
{
item: {
id,
},
score,
},
score,
}],
],
}).find(choice => choice.id === id);
expect(actualResponse).to.eql(expectedResponse);

View file

@ -3,12 +3,15 @@ export const defaultState = [];
export default function groups(state = defaultState, action) {
switch (action.type) {
case 'ADD_GROUP': {
return [...state, {
id: action.id,
value: action.value,
active: action.active,
disabled: action.disabled,
}];
return [
...state,
{
id: action.id,
value: action.value,
active: action.active,
disabled: action.disabled,
},
];
}
case 'CLEAR_CHOICES': {

View file

@ -4,20 +4,23 @@ export default function items(state = defaultState, action) {
switch (action.type) {
case 'ADD_ITEM': {
// Add object to items array
const newState = [...state, {
id: action.id,
choiceId: action.choiceId,
groupId: action.groupId,
value: action.value,
label: action.label,
active: true,
highlighted: false,
customProperties: action.customProperties,
placeholder: (action.placeholder || false),
keyCode: null,
}];
const newState = [
...state,
{
id: action.id,
choiceId: action.choiceId,
groupId: action.groupId,
value: action.value,
label: action.label,
active: true,
highlighted: false,
customProperties: action.customProperties,
placeholder: action.placeholder || false,
keyCode: null,
},
];
return newState.map((obj) => {
return newState.map(obj => {
const item = obj;
item.highlighted = false;
return item;
@ -26,7 +29,7 @@ export default function items(state = defaultState, action) {
case 'REMOVE_ITEM': {
// Set item to inactive
return state.map((obj) => {
return state.map(obj => {
const item = obj;
if (item.id === action.id) {
item.active = false;
@ -36,7 +39,7 @@ export default function items(state = defaultState, action) {
}
case 'HIGHLIGHT_ITEM': {
return state.map((obj) => {
return state.map(obj => {
const item = obj;
if (item.id === action.id) {
item.highlighted = action.highlighted;

View file

@ -56,7 +56,7 @@ describe('reducers/items', () => {
});
it('unhighlights all highlighted items', () => {
actualResponse.forEach((item) => {
actualResponse.forEach(item => {
expect(item.highlighted).to.equal(false);
});
});

View file

@ -5,9 +5,7 @@ export default class Store {
constructor() {
this._store = createStore(
rootReducer,
window.devToolsExtension ?
window.devToolsExtension() :
undefined,
window.devToolsExtension ? window.devToolsExtension() : undefined,
);
}
@ -54,9 +52,9 @@ export default class Store {
}
/**
* Get highlighted items from store
* @return {Array} Item objects
*/
* Get highlighted items from store
* @return {Array} Item objects
*/
get highlightedActiveItems() {
return this.items.filter(item => item.active && item.highlighted);
}
@ -122,10 +120,10 @@ export default class Store {
const groups = this.groups;
const choices = this.choices;
return groups.filter((group) => {
return groups.filter(group => {
const isActive = group.active === true && group.disabled === false;
const hasActiveOptions = choices.some(choice =>
choice.active === true && choice.disabled === false,
const hasActiveOptions = choices.some(
choice => choice.active === true && choice.disabled === false,
);
return isActive && hasActiveOptions;
}, []);
@ -138,7 +136,9 @@ export default class Store {
getChoiceById(id) {
if (id) {
const choices = this.activeChoices;
const foundChoice = choices.find(choice => choice.id === parseInt(id, 10));
const foundChoice = choices.find(
choice => choice.id === parseInt(id, 10),
);
return foundChoice;
}
return false;

View file

@ -21,7 +21,6 @@ describe('reducers/store', () => {
getStateStub.restore();
});
describe('constructor', () => {
it('creates redux store', () => {
expect(instance._store).to.contain.keys([
@ -32,7 +31,6 @@ describe('reducers/store', () => {
});
});
describe('subscribe', () => {
it('wraps redux subscribe method', () => {
const onChange = () => {};
@ -163,14 +161,16 @@ describe('reducers/store', () => {
describe('activeItems getter', () => {
it('returns items that are active', () => {
const expectedResponse = state.items.filter((item => item.active));
const expectedResponse = state.items.filter(item => item.active);
expect(instance.activeItems).to.eql(expectedResponse);
});
});
describe('highlightedActiveItems getter', () => {
it('returns items that are active and highlighted', () => {
const expectedResponse = state.items.filter((item => item.highlighted && item.active));
const expectedResponse = state.items.filter(
item => item.highlighted && item.active,
);
expect(instance.highlightedActiveItems).to.eql(expectedResponse);
});
});
@ -184,21 +184,25 @@ describe('reducers/store', () => {
describe('activeChoices getter', () => {
it('returns choices that are active', () => {
const expectedResponse = state.choices.filter((choice => choice.active));
const expectedResponse = state.choices.filter(choice => choice.active);
expect(instance.activeChoices).to.eql(expectedResponse);
});
});
describe('selectableChoices getter', () => {
it('returns choices that are not disabled', () => {
const expectedResponse = state.choices.filter((choice => !choice.disabled));
const expectedResponse = state.choices.filter(
choice => !choice.disabled,
);
expect(instance.selectableChoices).to.eql(expectedResponse);
});
});
describe('searchableChoices getter', () => {
it('returns choices that are not placeholders and are selectable', () => {
const expectedResponse = state.choices.filter((choice => !choice.disabled && !choice.placeholder));
const expectedResponse = state.choices.filter(
choice => !choice.disabled && !choice.placeholder,
);
expect(instance.searchableChoices).to.eql(expectedResponse);
});
});
@ -207,7 +211,9 @@ describe('reducers/store', () => {
describe('passing id', () => {
it('returns active choice by passed id', () => {
const id = '1';
const expectedResponse = state.choices.find((choice => choice.id === parseInt(id, 10)));
const expectedResponse = state.choices.find(
choice => choice.id === parseInt(id, 10),
);
const actualResponse = instance.getChoiceById(id);
expect(actualResponse).to.eql(expectedResponse);
});
@ -223,7 +229,9 @@ describe('reducers/store', () => {
describe('placeholderChoice getter', () => {
it('returns placeholder choice', () => {
const expectedResponse = state.choices.reverse().find(choice => choice.placeholder);
const expectedResponse = state.choices
.reverse()
.find(choice => choice.placeholder);
expect(instance.getPlaceholderChoice).to.eql(expectedResponse);
});
});
@ -245,7 +253,9 @@ describe('reducers/store', () => {
describe('getGroupById', () => {
it('returns group by id', () => {
const id = '1';
const expectedResponse = state.groups.find((group => group.id === parseInt(id, 10)));
const expectedResponse = state.groups.find(
group => group.id === parseInt(id, 10),
);
const actualResponse = instance.getGroupById(id);
expect(actualResponse).to.eql(expectedResponse);
});

View file

@ -39,13 +39,10 @@ export const TEMPLATES = {
`);
},
itemList(globalClasses, isSelectOneElement) {
const localClasses = classNames(
globalClasses.list,
{
[globalClasses.listSingle]: (isSelectOneElement),
[globalClasses.listItems]: (!isSelectOneElement),
},
);
const localClasses = classNames(globalClasses.list, {
[globalClasses.listSingle]: isSelectOneElement,
[globalClasses.listItems]: !isSelectOneElement,
});
return strToEl(`
<div class="${localClasses}"></div>
@ -62,22 +59,18 @@ export const TEMPLATES = {
const ariaSelected = data.active ? 'aria-selected="true"' : '';
const ariaDisabled = data.disabled ? 'aria-disabled="true"' : '';
let localClasses = classNames(
globalClasses.item, {
[globalClasses.highlightedState]: data.highlighted,
[globalClasses.itemSelectable]: !data.highlighted,
[globalClasses.placeholder]: data.placeholder,
},
);
let localClasses = classNames(globalClasses.item, {
[globalClasses.highlightedState]: data.highlighted,
[globalClasses.itemSelectable]: !data.highlighted,
[globalClasses.placeholder]: data.placeholder,
});
if (removeItemButton) {
localClasses = classNames(
globalClasses.item, {
[globalClasses.highlightedState]: data.highlighted,
[globalClasses.itemSelectable]: !data.disabled,
[globalClasses.placeholder]: data.placeholder,
},
);
localClasses = classNames(globalClasses.item, {
[globalClasses.highlightedState]: data.highlighted,
[globalClasses.itemSelectable]: !data.disabled,
[globalClasses.placeholder]: data.placeholder,
});
return strToEl(`
<div
@ -116,9 +109,9 @@ export const TEMPLATES = {
`);
},
choiceList(globalClasses, isSelectOneElement) {
const ariaMultiSelectable = !isSelectOneElement ?
'aria-multiselectable="true"' :
'';
const ariaMultiSelectable = !isSelectOneElement
? 'aria-multiselectable="true"'
: '';
return strToEl(`
<div
@ -132,11 +125,9 @@ export const TEMPLATES = {
},
choiceGroup(globalClasses, data) {
const ariaDisabled = data.disabled ? 'aria-disabled="true"' : '';
const localClasses = classNames(
globalClasses.group, {
[globalClasses.itemDisabled]: data.disabled,
},
);
const localClasses = classNames(globalClasses.group, {
[globalClasses.itemDisabled]: data.disabled,
});
return strToEl(`
<div
@ -155,7 +146,8 @@ export const TEMPLATES = {
const role = data.groupId > 0 ? 'role="treeitem"' : 'role="option"';
const localClasses = classNames(
globalClasses.item,
globalClasses.itemChoice, {
globalClasses.itemChoice,
{
[globalClasses.itemDisabled]: data.disabled,
[globalClasses.itemSelectable]: !data.disabled,
[globalClasses.placeholder]: data.placeholder,
@ -169,9 +161,10 @@ export const TEMPLATES = {
data-choice
data-id="${data.id}"
data-value="${data.value}"
${data.disabled ?
'data-choice-disabled aria-disabled="true"' :
'data-choice-selectable'
${
data.disabled
? 'data-choice-disabled aria-disabled="true"'
: 'data-choice-selectable'
}
id="${data.elementId}"
${role}
@ -217,8 +210,8 @@ export const TEMPLATES = {
globalClasses.item,
globalClasses.itemChoice,
{
[globalClasses.noResults]: (type === 'no-results'),
[globalClasses.noChoices]: (type === 'no-choices'),
[globalClasses.noResults]: type === 'no-results',
[globalClasses.noChoices]: type === 'no-choices',
},
);
@ -230,7 +223,9 @@ export const TEMPLATES = {
},
option(data) {
return strToEl(`
<option value="${data.value}" ${data.selected ? 'selected' : ''} ${data.disabled ? 'disabled' : ''}>${data.label}</option>
<option value="${data.value}" ${data.selected ? 'selected' : ''} ${
data.disabled ? 'disabled' : ''
}>${data.label}</option>
`);
},
};

View file

@ -2,7 +2,8 @@ import { expect } from 'chai';
import templates from './templates';
import { getType, strToEl } from './lib/utils';
const stripElement = element => element.outerHTML.replace(/(^|>)\s+|\s+(?=<|$)/g, '$1');
const stripElement = element =>
element.outerHTML.replace(/(^|>)\s+|\s+(?=<|$)/g, '$1');
describe('templates', () => {
describe('containerOuter', () => {
@ -41,7 +42,9 @@ describe('templates', () => {
);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
@ -73,7 +76,9 @@ describe('templates', () => {
);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
@ -106,7 +111,9 @@ describe('templates', () => {
);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
});
@ -138,7 +145,9 @@ describe('templates', () => {
);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
});
@ -148,7 +157,9 @@ describe('templates', () => {
const classes = {
containerInner: 'test',
};
const expectedOutput = strToEl(`<div class="${classes.containerInner}"></div>`);
const expectedOutput = strToEl(
`<div class="${classes.containerInner}"></div>`,
);
const actualOutput = templates.containerInner(classes);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
@ -165,21 +176,29 @@ describe('templates', () => {
describe('select one element', () => {
it('returns expected html', () => {
const expectedOutput = strToEl(`<div class="${classes.list} ${classes.listSingle}"></div>`);
const expectedOutput = strToEl(
`<div class="${classes.list} ${classes.listSingle}"></div>`,
);
const actualOutput = templates.itemList(classes, true);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
describe('non select one element', () => {
it('returns expected html', () => {
const expectedOutput = strToEl(`<div class="${classes.list} ${classes.listItems}"></div>`);
const expectedOutput = strToEl(
`<div class="${classes.list} ${classes.listItems}"></div>`,
);
const actualOutput = templates.itemList(classes, false);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
});
@ -191,8 +210,7 @@ describe('templates', () => {
};
const value = 'test';
const expectedOutput = strToEl(`
<div class="${classes.placeholder}">${value}</div>`,
);
<div class="${classes.placeholder}">${value}</div>`);
const actualOutput = templates.placeholder(classes, value);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
@ -222,7 +240,9 @@ describe('templates', () => {
const actualOutput = templates.choiceList(classes, true);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
@ -240,7 +260,9 @@ describe('templates', () => {
const actualOutput = templates.choiceList(classes, false);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
});
@ -278,7 +300,9 @@ describe('templates', () => {
const actualOutput = templates.choiceGroup(classes, data);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
@ -306,7 +330,9 @@ describe('templates', () => {
const actualOutput = templates.choiceGroup(classes, data);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
});
@ -339,7 +365,9 @@ describe('templates', () => {
it('returns expected html', () => {
const expectedOutput = strToEl(`
<div
class="${classes.item} ${classes.itemChoice} ${classes.itemSelectable}"
class="${classes.item} ${classes.itemChoice} ${
classes.itemSelectable
}"
data-select-text="${itemSelectText}"
data-choice
data-id="${data.id}"
@ -354,7 +382,9 @@ describe('templates', () => {
const actualOutput = templates.choice(classes, data, itemSelectText);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
@ -369,7 +399,9 @@ describe('templates', () => {
it('returns expected html', () => {
const expectedOutput = strToEl(`
<div
class="${classes.item} ${classes.itemChoice} ${classes.itemDisabled}"
class="${classes.item} ${classes.itemChoice} ${
classes.itemDisabled
}"
data-select-text="${itemSelectText}"
data-choice
data-id="${data.id}"
@ -385,7 +417,9 @@ describe('templates', () => {
const actualOutput = templates.choice(classes, data, itemSelectText);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
@ -400,7 +434,9 @@ describe('templates', () => {
it('returns expected html', () => {
const expectedOutput = strToEl(`
<div
class="${classes.item} ${classes.itemChoice} ${classes.itemSelectable} ${classes.placeholder}"
class="${classes.item} ${classes.itemChoice} ${
classes.itemSelectable
} ${classes.placeholder}"
data-select-text="${itemSelectText}"
data-choice
data-id="${data.id}"
@ -415,7 +451,9 @@ describe('templates', () => {
const actualOutput = templates.choice(classes, data, itemSelectText);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
@ -423,14 +461,16 @@ describe('templates', () => {
beforeEach(() => {
data = {
...data,
groupId: 1
groupId: 1,
};
});
it('returns expected html', () => {
const expectedOutput = strToEl(`
<div
class="${classes.item} ${classes.itemChoice} ${classes.itemSelectable}"
class="${classes.item} ${classes.itemChoice} ${
classes.itemSelectable
}"
data-select-text="${itemSelectText}"
data-choice
data-id="${data.id}"
@ -445,7 +485,9 @@ describe('templates', () => {
const actualOutput = templates.choice(classes, data, itemSelectText);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
});
@ -479,11 +521,14 @@ describe('templates', () => {
const classes = {
list: 'test 1',
listDropdown: 'test 2',
}
;
};
it('returns expected html', () => {
const value = 'test';
const expectedOutput = strToEl(`<div class="${classes.list} ${classes.listDropdown}" aria-expanded="false"></div>`);
const expectedOutput = strToEl(
`<div class="${classes.list} ${
classes.listDropdown
}" aria-expanded="false"></div>`,
);
const actualOutput = templates.dropdown(classes, value);
expect(getType(actualOutput)).to.equal('HTMLDivElement');
@ -517,26 +562,34 @@ describe('templates', () => {
describe('no results', () => {
it('adds no results classname', () => {
const expectedOutput = strToEl(`
<div class="${classes.item} ${classes.itemChoice} ${classes.noResults}">
<div class="${classes.item} ${classes.itemChoice} ${
classes.noResults
}">
${label}
</div>
`);
const actualOutput = templates.notice(classes, label, 'no-results');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
describe('no choices', () => {
it('adds no choices classname', () => {
const expectedOutput = strToEl(`
<div class="${classes.item} ${classes.itemChoice} ${classes.noChoices}">
<div class="${classes.item} ${classes.itemChoice} ${
classes.noChoices
}">
${label}
</div>
`);
const actualOutput = templates.notice(classes, label, 'no-choices');
expect(stripElement(actualOutput)).to.equal(stripElement(expectedOutput));
expect(stripElement(actualOutput)).to.equal(
stripElement(expectedOutput),
);
});
});
});
@ -555,7 +608,11 @@ describe('templates', () => {
});
it('returns expected html', () => {
const expectedOutput = strToEl(`<option value="${data.value}" ${data.selected ? 'selected' : ''} ${data.disabled ? 'disabled' : ''}>${data.label}</option>`);
const expectedOutput = strToEl(
`<option value="${data.value}" ${data.selected ? 'selected' : ''} ${
data.disabled ? 'disabled' : ''
}>${data.label}</option>`,
);
const actualOutput = templates.option(data);
expect(getType(actualOutput)).to.equal('HTMLOptionElement');