More private variables

This commit is contained in:
Josh Johnson 2018-05-24 09:22:07 +01:00
parent 109a232171
commit 62389ff744
6 changed files with 238 additions and 244 deletions

View file

@ -50,31 +50,31 @@ class Choices {
} }
// Create data store // Create data store
this.store = new Store(this.render); this._store = new Store(this.render);
// State tracking // State tracking
this.initialised = false; this.initialised = false;
this.currentState = {}; this._currentState = {};
this.prevState = {}; this._prevState = {};
this.currentValue = ''; this._currentValue = '';
this.isScrollingOnIe = false; this._isScrollingOnIe = false;
this.wasTap = true; this._wasTap = true;
// Retrieve triggering element (i.e. element with 'data-choice' trigger) // 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._isTextElement = passedElement.type === 'text';
this.isSelectOneElement = passedElement.type === 'select-one'; this._isSelectOneElement = passedElement.type === 'select-one';
this.isSelectMultipleElement = passedElement.type === 'select-multiple'; this._isSelectMultipleElement = passedElement.type === 'select-multiple';
this.isSelectElement = this.isSelectOneElement || this.isSelectMultipleElement; this._isSelectElement = this._isSelectOneElement || this._isSelectMultipleElement;
if (this.isTextElement) { if (this._isTextElement) {
this.passedElement = new WrappedInput({ this.passedElement = new WrappedInput({
element: passedElement, element: passedElement,
classNames: this.config.classNames, classNames: this.config.classNames,
delimiter: this.config.delimiter, delimiter: this.config.delimiter,
}); });
} else if (this.isSelectElement) { } else if (this._isSelectElement) {
this.passedElement = new WrappedSelect({ this.passedElement = new WrappedSelect({
element: passedElement, element: passedElement,
classNames: this.config.classNames, classNames: this.config.classNames,
@ -85,27 +85,27 @@ class Choices {
throw new Error('Could not wrap passed element'); throw new Error('Could not wrap passed element');
} }
if (this.config.shouldSortItems === true && this.isSelectOneElement && !this.config.silent) { if (this.config.shouldSortItems === true && this._isSelectOneElement && !this.config.silent) {
console.warn('shouldSortElements: Type of passed element is \'select-one\', falling back to false.'); console.warn('shouldSortElements: Type of passed element is \'select-one\', falling back to false.');
} }
this.highlightPosition = 0; this._highlightPosition = 0;
this.placeholderValue = this._generatePlaceholderValue(); this._placeholderValue = this._generatePlaceholderValue();
// Assign preset choices from passed object // Assign preset choices from passed object
this.presetChoices = this.config.choices; this._presetChoices = this.config.choices;
// Assign preset items from passed object first // Assign preset items from passed object first
this.presetItems = this.config.items; this._presetItems = this.config.items;
// Then add any values passed from attribute // Then add any values passed from attribute
if (this.passedElement.value) { if (this.passedElement.value) {
this.presetItems = this.presetItems.concat( this._presetItems = this._presetItems.concat(
this.passedElement.value.split(this.config.delimiter), this.passedElement.value.split(this.config.delimiter),
); );
} }
// Set unique base Id // Set unique base Id
this.baseId = generateId(this.passedElement.element, 'choices-'); this._baseId = generateId(this.passedElement.element, 'choices-');
this.idNames = { this.idNames = {
itemChoice: 'item-choice', itemChoice: 'item-choice',
@ -154,16 +154,16 @@ class Choices {
// Generate input markup // Generate input markup
this._createStructure(); this._createStructure();
// Subscribe store to render method // Subscribe store to render method
this.store.subscribe(this.render); this._store.subscribe(this.render);
// Render any items // Render any items
this.render(); this.render();
// Trigger event listeners // Trigger event listeners
this._addEventListeners(); this._addEventListeners();
const callback = this.config.callbackOnInit; const { callbackOnInit } = this.config;
// Run callback if it is a function // Run callback if it is a function
if (callback && isType('Function', callback)) { if (callbackOnInit && isType('Function', callbackOnInit)) {
callback.call(this); callbackOnInit.call(this);
} }
} }
@ -182,8 +182,8 @@ class Choices {
this.passedElement.reveal(); this.passedElement.reveal();
this.containerOuter.unwrap(this.passedElement.element); this.containerOuter.unwrap(this.passedElement.element);
if (this.isSelectElement) { if (this._isSelectElement) {
this.passedElement.options = this.presetChoices; this.passedElement.options = this._presetChoices;
} }
// Clear data store // Clear data store
@ -243,14 +243,15 @@ class Choices {
* @private * @private
*/ */
render() { render() {
this.currentState = this.store.state; this._currentState = this._store.state;
const stateChanged = ( const stateChanged = (
this.currentState.choices !== this.prevState.choices || this._currentState.choices !== this._prevState.choices ||
this.currentState.groups !== this.prevState.groups || this._currentState.groups !== this._prevState.groups ||
this.currentState.items !== this.prevState.items this._currentState.items !== this._prevState.items
); );
const shouldRenderChoices = this.isSelectElement; const shouldRenderChoices = this._isSelectElement;
const shouldRenderItems = this.currentState.items !== this.prevState.items; const shouldRenderItems = this._currentState.items !== this._prevState.items;
if (!stateChanged) { if (!stateChanged) {
return; return;
@ -264,7 +265,7 @@ class Choices {
this._renderItems(); this._renderItems();
} }
this.prevState = this.currentState; this._prevState = this._currentState;
} }
/** /**
@ -280,9 +281,9 @@ class Choices {
} }
const { id, groupId = -1, value = '', label = '' } = item; const { id, groupId = -1, value = '', label = '' } = item;
const group = groupId >= 0 ? this.store.getGroupById(groupId) : null; const group = groupId >= 0 ? this._store.getGroupById(groupId) : null;
this.store.dispatch(highlightItem(id, true)); this._store.dispatch(highlightItem(id, true));
if (runEvent) { if (runEvent) {
this.passedElement.triggerEvent(EVENTS.highlightItem, { this.passedElement.triggerEvent(EVENTS.highlightItem, {
@ -308,9 +309,9 @@ class Choices {
} }
const { id, groupId = -1, value = '', label = '' } = item; const { id, groupId = -1, value = '', label = '' } = item;
const group = groupId >= 0 ? this.store.getGroupById(groupId) : null; const group = groupId >= 0 ? this._store.getGroupById(groupId) : null;
this.store.dispatch(highlightItem(id, false)); this._store.dispatch(highlightItem(id, false));
this.passedElement.triggerEvent(EVENTS.highlightItem, { this.passedElement.triggerEvent(EVENTS.highlightItem, {
id, id,
value, value,
@ -327,7 +328,7 @@ class Choices {
* @public * @public
*/ */
highlightAll() { highlightAll() {
this.store.items.forEach(item => this.highlightItem(item)); this._store.items.forEach(item => this.highlightItem(item));
return this; return this;
} }
@ -337,7 +338,7 @@ class Choices {
* @public * @public
*/ */
unhighlightAll() { unhighlightAll() {
this.store.items.forEach(item => this.unhighlightItem(item)); this._store.items.forEach(item => this.unhighlightItem(item));
return this; return this;
} }
@ -353,7 +354,7 @@ class Choices {
return this; return this;
} }
this.store.activeItems this._store.activeItems
.filter(item => item.value === value) .filter(item => item.value === value)
.forEach(item => this._removeItem(item)); .forEach(item => this._removeItem(item));
@ -368,7 +369,7 @@ class Choices {
* @public * @public
*/ */
removeActiveItems(excludedId) { removeActiveItems(excludedId) {
this.store.activeItems this._store.activeItems
.filter(({ id }) => id !== excludedId) .filter(({ id }) => id !== excludedId)
.forEach(item => this._removeItem(item)); .forEach(item => this._removeItem(item));
@ -382,7 +383,7 @@ class Choices {
* @public * @public
*/ */
removeHighlightedItems(runEvent = false) { removeHighlightedItems(runEvent = false) {
this.store.highlightedActiveItems this._store.highlightedActiveItems
.forEach((item) => { .forEach((item) => {
this._removeItem(item); this._removeItem(item);
// If this action was performed by the user // If this action was performed by the user
@ -467,7 +468,7 @@ class Choices {
* @public * @public
*/ */
getValue(valueOnly = false) { getValue(valueOnly = false) {
const items = this.store.activeItems; const items = this._store.activeItems;
const values = items.reduce((selectedItems, item) => { const values = items.reduce((selectedItems, item) => {
const itemValue = valueOnly ? item.value : item; const itemValue = valueOnly ? item.value : item;
@ -475,7 +476,7 @@ class Choices {
return selectedItems; return selectedItems;
}, []); }, []);
return this.isSelectOneElement ? values[0] : values; return this._isSelectOneElement ? values[0] : values;
} }
/** /**
@ -504,7 +505,7 @@ class Choices {
* @public * @public
*/ */
setChoiceByValue(value) { setChoiceByValue(value) {
if (!this.initialised || this.isTextElement) { if (!this.initialised || this._isTextElement) {
return this; return this;
} }
@ -528,7 +529,7 @@ class Choices {
*/ */
setChoices(choices = [], value = '', label = '', replaceChoices = false) { setChoices(choices = [], value = '', label = '', replaceChoices = false) {
if ( if (
!this.isSelectElement || !this._isSelectElement ||
!choices.length || !choices.length ||
!value !value
) { ) {
@ -574,7 +575,7 @@ class Choices {
* @public * @public
*/ */
clearStore() { clearStore() {
this.store.dispatch(clearAll()); this._store.dispatch(clearAll());
return this; return this;
} }
@ -584,12 +585,12 @@ class Choices {
* @public * @public
*/ */
clearInput() { clearInput() {
const shouldSetInputWidth = !this.isSelectOneElement; const shouldSetInputWidth = !this._isSelectOneElement;
this.input.clear(shouldSetInputWidth); this.input.clear(shouldSetInputWidth);
if (!this.isTextElement && this.config.searchEnabled) { if (!this._isTextElement && this.config.searchEnabled) {
this.isSearching = false; this._isSearching = false;
this.store.dispatch(activateChoices(true)); this._store.dispatch(activateChoices(true));
} }
return this; return this;
@ -602,7 +603,7 @@ class Choices {
* @public * @public
*/ */
ajax(fn) { ajax(fn) {
if (!this.initialised || !this.isSelectElement || !fn) { if (!this.initialised || !this._isSelectElement || !fn) {
return this; return this;
} }
@ -629,7 +630,7 @@ class Choices {
_createGroupsFragment(groups, choices, fragment) { _createGroupsFragment(groups, choices, fragment) {
const groupFragment = fragment || document.createDocumentFragment(); const groupFragment = fragment || document.createDocumentFragment();
const getGroupChoices = group => choices.filter((choice) => { const getGroupChoices = group => choices.filter((choice) => {
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
return choice.groupId === group.id; return choice.groupId === group.id;
} }
return choice.groupId === group.id && (this.config.renderSelectedChoices === 'always' || !choice.selected); return choice.groupId === group.id && (this.config.renderSelectedChoices === 'always' || !choice.selected);
@ -664,10 +665,10 @@ class Choices {
// Create a fragment to store our list items (so we don't have to update the DOM for each item) // 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 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 filter = this._isSearching ? sortByScore : this.config.sortFn;
const appendChoice = (choice) => { const appendChoice = (choice) => {
const shouldRender = renderSelectedChoices === 'auto' ? const shouldRender = renderSelectedChoices === 'auto' ?
(this.isSelectOneElement || !choice.selected) : (this._isSelectOneElement || !choice.selected) :
true; true;
if (shouldRender) { if (shouldRender) {
const dropdownItem = this._getTemplate('choice', choice, this.config.itemSelectText); const dropdownItem = this._getTemplate('choice', choice, this.config.itemSelectText);
@ -677,7 +678,7 @@ class Choices {
let rendererableChoices = choices; let rendererableChoices = choices;
if (renderSelectedChoices === 'auto' && !this.isSelectOneElement) { if (renderSelectedChoices === 'auto' && !this._isSelectOneElement) {
rendererableChoices = choices.filter(choice => !choice.selected); rendererableChoices = choices.filter(choice => !choice.selected);
} }
@ -692,7 +693,7 @@ class Choices {
}, { placeholderChoices: [], normalChoices: [] }); }, { placeholderChoices: [], normalChoices: [] });
// If sorting is enabled or the user is searching, filter choices // If sorting is enabled or the user is searching, filter choices
if (this.config.shouldSort || this.isSearching) { if (this.config.shouldSort || this._isSearching) {
normalChoices.sort(filter); normalChoices.sort(filter);
} }
@ -701,7 +702,7 @@ class Choices {
// Prepend placeholeder // Prepend placeholeder
const sortedChoices = [...placeholderChoices, ...normalChoices]; const sortedChoices = [...placeholderChoices, ...normalChoices];
if (this.isSearching) { if (this._isSearching) {
choiceLimit = searchResultLimit; choiceLimit = searchResultLimit;
} else if (renderChoiceLimit > 0 && !withinGroup) { } else if (renderChoiceLimit > 0 && !withinGroup) {
choiceLimit = renderChoiceLimit; choiceLimit = renderChoiceLimit;
@ -726,14 +727,15 @@ class Choices {
*/ */
_createItemsFragment(items, fragment = null) { _createItemsFragment(items, fragment = null) {
// Create fragment to add elements to // Create fragment to add elements to
const { shouldSortItems, sortFn, removeItemButton } = this.config;
const itemListFragment = fragment || document.createDocumentFragment(); const itemListFragment = fragment || document.createDocumentFragment();
// If sorting is enabled, filter items // If sorting is enabled, filter items
if (this.config.shouldSortItems && !this.isSelectOneElement) { if (shouldSortItems && !this._isSelectOneElement) {
items.sort(this.config.sortFn); items.sort(sortFn);
} }
if (this.isTextElement) { if (this._isTextElement) {
// Update the value of the hidden input // Update the value of the hidden input
this.passedElement.value = items; this.passedElement.value = items;
} else { } else {
@ -743,7 +745,7 @@ class Choices {
const addItemToFragment = (item) => { const addItemToFragment = (item) => {
// Create new list element // Create new list element
const listItem = this._getTemplate('item', item, this.config.removeItemButton); const listItem = this._getTemplate('item', item, removeItemButton);
// Append it to list // Append it to list
itemListFragment.appendChild(listItem); itemListFragment.appendChild(listItem);
}; };
@ -774,7 +776,7 @@ class Choices {
* Select placeholder choice * Select placeholder choice
*/ */
_selectPlaceholderChoice() { _selectPlaceholderChoice() {
const placeholderChoice = this.store.placeholderChoice; const placeholderChoice = this._store.placeholderChoice;
if (placeholderChoice) { if (placeholderChoice) {
this._addItem( this._addItem(
@ -810,11 +812,11 @@ class Choices {
const itemId = element.parentNode.getAttribute('data-id'); 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 // Remove item associated with button
this._removeItem(itemToRemove); this._removeItem(itemToRemove);
this._triggerChange(itemToRemove.value); this._triggerChange(itemToRemove.value);
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
this._selectPlaceholderChoice(); this._selectPlaceholderChoice();
} }
} }
@ -832,7 +834,7 @@ class Choices {
!activeItems || !activeItems ||
!element || !element ||
!this.config.removeItems || !this.config.removeItems ||
this.isSelectOneElement this._isSelectOneElement
) { ) {
return; return;
} }
@ -868,7 +870,7 @@ class Choices {
// If we are clicking on an option // If we are clicking on an option
const id = element.getAttribute('data-id'); const id = element.getAttribute('data-id');
const choice = this.store.getChoiceById(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; const hasActiveDropdown = this.dropdown.isActive;
@ -899,7 +901,7 @@ class Choices {
this.clearInput(); this.clearInput();
// We wont to close the dropdown if we are dealing with a single select box // We wont to close the dropdown if we are dealing with a single select box
if (hasActiveDropdown && this.isSelectOneElement) { if (hasActiveDropdown && this._isSelectOneElement) {
this.hideDropdown(); this.hideDropdown();
this.containerOuter.focus(); this.containerOuter.focus();
} }
@ -945,7 +947,7 @@ class Choices {
let placeholderItem = this.itemList.getChild(`.${this.config.classNames.placeholder}`); let placeholderItem = this.itemList.getChild(`.${this.config.classNames.placeholder}`);
if (isLoading) { if (isLoading) {
this.containerOuter.addLoadingState(); this.containerOuter.addLoadingState();
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
if (!placeholderItem) { if (!placeholderItem) {
placeholderItem = this._getTemplate('placeholder', this.config.loadingText); placeholderItem = this._getTemplate('placeholder', this.config.loadingText);
this.itemList.append(placeholderItem); this.itemList.append(placeholderItem);
@ -958,10 +960,10 @@ class Choices {
} else { } else {
this.containerOuter.removeLoadingState(); this.containerOuter.removeLoadingState();
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
placeholderItem.innerHTML = (this.placeholderValue || ''); placeholderItem.innerHTML = (this._placeholderValue || '');
} else { } else {
this.input.placeholder = (this.placeholderValue || ''); this.input.placeholder = (this._placeholderValue || '');
} }
} }
} }
@ -980,7 +982,7 @@ class Choices {
this.config.addItemText(value) : this.config.addItemText(value) :
this.config.addItemText; this.config.addItemText;
if (this.isSelectMultipleElement || this.isTextElement) { if (this._isSelectMultipleElement || this._isTextElement) {
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 // If there is a max entry limit and we have reached that limit
// don't update // don't update
@ -991,7 +993,7 @@ class Choices {
} }
} }
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 // If a user has supplied a regular expression filter
// determine whether we can update based on whether // determine whether we can update based on whether
// our regular expression passes // our regular expression passes
@ -1010,7 +1012,7 @@ class Choices {
if (!isUnique && if (!isUnique &&
!this.config.duplicateItems && !this.config.duplicateItems &&
!this.isSelectOneElement && !this._isSelectOneElement &&
canAddItem canAddItem
) { ) {
canAddItem = false; canAddItem = false;
@ -1064,7 +1066,7 @@ class Choices {
} }
}); });
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
this._selectPlaceholderChoice(); this._selectPlaceholderChoice();
} }
} else { } else {
@ -1082,16 +1084,16 @@ class Choices {
*/ */
_searchChoices(value) { _searchChoices(value) {
const newValue = isType('String', value) ? value.trim() : value; const newValue = isType('String', value) ? value.trim() : value;
const currentValue = isType('String', this.currentValue) ? const currentValue = isType('String', this._currentValue) ?
this.currentValue.trim() : this._currentValue.trim() :
this.currentValue; this._currentValue;
if (newValue.length < 1 && newValue === `${currentValue} `) { if (newValue.length < 1 && newValue === `${currentValue} `) {
return 0; return 0;
} }
// If new value matches the desired length and is not the same as the current value with a space // 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 haystack = this._store.searchableChoices;
const needle = newValue; const needle = newValue;
const keys = isType('Array', this.config.searchFields) ? const keys = isType('Array', this.config.searchFields) ?
this.config.searchFields : this.config.searchFields :
@ -1100,10 +1102,10 @@ class Choices {
const fuse = new Fuse(haystack, options); const fuse = new Fuse(haystack, options);
const results = fuse.search(needle); const results = fuse.search(needle);
this.currentValue = newValue; this._currentValue = newValue;
this.highlightPosition = 0; this._highlightPosition = 0;
this.isSearching = true; this._isSearching = true;
this.store.dispatch(filterChoices(results)); this._store.dispatch(filterChoices(results));
return results.length; return results.length;
} }
@ -1119,12 +1121,13 @@ class Choices {
return; return;
} }
const choices = this.store.choices; const choices = this._store.choices;
const { searchFloor, searchChoices } = this.config;
const hasUnactiveChoices = choices.some(option => !option.active); const hasUnactiveChoices = choices.some(option => !option.active);
// Check that we have a value to search and the input was an alphanumeric character // Check that we have a value to search and the input was an alphanumeric character
if (value && value.length >= this.config.searchFloor) { if (value && value.length >= searchFloor) {
const resultCount = this.config.searchChoices ? this._searchChoices(value) : 0; const resultCount = searchChoices ? this._searchChoices(value) : 0;
// Trigger search event // Trigger search event
this.passedElement.triggerEvent(EVENTS.search, { this.passedElement.triggerEvent(EVENTS.search, {
value, value,
@ -1132,8 +1135,8 @@ class Choices {
}); });
} else if (hasUnactiveChoices) { } else if (hasUnactiveChoices) {
// Otherwise reset choices to active // Otherwise reset choices to active
this.isSearching = false; this._isSearching = false;
this.store.dispatch(activateChoices(true)); this._store.dispatch(activateChoices(true));
} }
} }
@ -1151,7 +1154,7 @@ class Choices {
document.addEventListener('mousedown', this._onMouseDown); document.addEventListener('mousedown', this._onMouseDown);
document.addEventListener('mouseover', this._onMouseOver); document.addEventListener('mouseover', this._onMouseOver);
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
this.containerOuter.element.addEventListener('focus', this._onFocus); this.containerOuter.element.addEventListener('focus', this._onFocus);
this.containerOuter.element.addEventListener('blur', this._onBlur); this.containerOuter.element.addEventListener('blur', this._onBlur);
} }
@ -1176,14 +1179,13 @@ class Choices {
document.removeEventListener('mousedown', this._onMouseDown); document.removeEventListener('mousedown', this._onMouseDown);
document.removeEventListener('mouseover', this._onMouseOver); document.removeEventListener('mouseover', this._onMouseOver);
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
this.containerOuter.element.removeEventListener('focus', this._onFocus); this.containerOuter.element.removeEventListener('focus', this._onFocus);
this.containerOuter.element.removeEventListener('blur', this._onBlur); this.containerOuter.element.removeEventListener('blur', this._onBlur);
} }
this.input.element.removeEventListener('focus', this._onFocus); this.input.element.removeEventListener('focus', this._onFocus);
this.input.element.removeEventListener('blur', this._onBlur); this.input.element.removeEventListener('blur', this._onBlur);
this.input.removeEventListeners(); this.input.removeEventListeners();
} }
@ -1198,7 +1200,7 @@ class Choices {
} }
const target = e.target; const target = e.target;
const activeItems = this.store.activeItems; const activeItems = this._store.activeItems;
const hasFocusedInput = this.input.isFocussed; const hasFocusedInput = this.input.isFocussed;
const hasActiveDropdown = this.dropdown.isActive; const hasActiveDropdown = this.dropdown.isActive;
const hasItems = this.itemList.hasChildren; const hasItems = this.itemList.hasChildren;
@ -1215,7 +1217,7 @@ class Choices {
const ctrlDownKey = (e.ctrlKey || e.metaKey); const ctrlDownKey = (e.ctrlKey || e.metaKey);
// If a user is typing and the dropdown is not active // If a user is typing and the dropdown is not active
if (!this.isTextElement && /[a-zA-Z0-9-_ ]/.test(keyString)) { if (!this._isTextElement && /[a-zA-Z0-9-_ ]/.test(keyString)) {
this.showDropdown(true); this.showDropdown(true);
} }
@ -1238,7 +1240,7 @@ class Choices {
const onEnterKey = () => { const onEnterKey = () => {
// If enter key is pressed and the input has a value // If enter key is pressed and the input has a value
if (this.isTextElement && target.value) { if (this._isTextElement && target.value) {
const value = this.input.value; const value = this.input.value;
const canAddItem = this._canAddItem(activeItems, value); const canAddItem = this._canAddItem(activeItems, value);
@ -1268,7 +1270,7 @@ class Choices {
} }
this._handleChoiceAction(activeItems, highlighted); this._handleChoiceAction(activeItems, highlighted);
} }
} else if (this.isSelectOneElement) { } else if (this._isSelectOneElement) {
// Open single select dropdown if it's not active // Open single select dropdown if it's not active
this.showDropdown(true); this.showDropdown(true);
e.preventDefault(); e.preventDefault();
@ -1284,7 +1286,7 @@ class Choices {
const onDirectionKey = () => { const onDirectionKey = () => {
// If up or down key is pressed, traverse through options // If up or down key is pressed, traverse through options
if (hasActiveDropdown || this.isSelectOneElement) { if (hasActiveDropdown || this._isSelectOneElement) {
// Show dropdown if focus // Show dropdown if focus
this.showDropdown(true); this.showDropdown(true);
@ -1292,24 +1294,25 @@ class Choices {
const directionInt = e.keyCode === downKey || e.keyCode === pageDownKey ? 1 : -1; const directionInt = e.keyCode === downKey || e.keyCode === pageDownKey ? 1 : -1;
const skipKey = e.metaKey || e.keyCode === pageDownKey || e.keyCode === pageUpKey; const skipKey = e.metaKey || e.keyCode === pageDownKey || e.keyCode === pageUpKey;
const selectableChoiceIdentifier = '[data-choice-selectable]';
let nextEl; let nextEl;
if (skipKey) { if (skipKey) {
if (directionInt > 0) { if (directionInt > 0) {
nextEl = Array.from( nextEl = Array.from(
this.dropdown.element.querySelectorAll('[data-choice-selectable]'), this.dropdown.element.querySelectorAll(selectableChoiceIdentifier),
).pop(); ).pop();
} else { } else {
nextEl = this.dropdown.element.querySelector('[data-choice-selectable]'); nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier);
} }
} else { } else {
const currentEl = this.dropdown.element.querySelector( const currentEl = this.dropdown.element.querySelector(
`.${this.config.classNames.highlightedState}`, `.${this.config.classNames.highlightedState}`,
); );
if (currentEl) { if (currentEl) {
nextEl = getAdjacentEl(currentEl, '[data-choice-selectable]', directionInt); nextEl = getAdjacentEl(currentEl, selectableChoiceIdentifier, directionInt);
} else { } else {
nextEl = this.dropdown.element.querySelector('[data-choice-selectable]'); nextEl = this.dropdown.element.querySelector(selectableChoiceIdentifier);
} }
} }
@ -1330,7 +1333,7 @@ class Choices {
const onDeleteKey = () => { const onDeleteKey = () => {
// If backspace or delete key is pressed and the input has no value // If backspace or delete key is pressed and the input has no value
if (hasFocusedInput && !e.target.value && !this.isSelectOneElement) { if (hasFocusedInput && !e.target.value && !this._isSelectOneElement) {
this._handleBackspace(activeItems); this._handleBackspace(activeItems);
e.preventDefault(); e.preventDefault();
} }
@ -1367,12 +1370,12 @@ class Choices {
} }
const value = this.input.value; const value = this.input.value;
const activeItems = this.store.activeItems; const activeItems = this._store.activeItems;
const canAddItem = this._canAddItem(activeItems, value); const canAddItem = this._canAddItem(activeItems, value);
// We are typing into a text input and have a value, we want to show a dropdown // We are typing into a text input and have a value, we want to show a dropdown
// notice. Otherwise hide the dropdown // notice. Otherwise hide the dropdown
if (this.isTextElement) { if (this._isTextElement) {
if (value) { if (value) {
if (canAddItem.notice) { if (canAddItem.notice) {
const dropdownItem = this._getTemplate('notice', canAddItem.notice); const dropdownItem = this._getTemplate('notice', canAddItem.notice);
@ -1394,9 +1397,9 @@ class Choices {
// If user has removed value... // If user has removed value...
if ((e.keyCode === backKey || e.keyCode === deleteKey) && !e.target.value) { if ((e.keyCode === backKey || e.keyCode === deleteKey) && !e.target.value) {
// ...and it is a multiple select input, activate choices (if searching) // ...and it is a multiple select input, activate choices (if searching)
if (!this.isTextElement && this.isSearching) { if (!this._isTextElement && this._isSearching) {
this.isSearching = false; this._isSearching = false;
this.store.dispatch(activateChoices(true)); this._store.dispatch(activateChoices(true));
} }
} else if (this.config.searchEnabled && canAddItem.response) { } else if (this.config.searchEnabled && canAddItem.response) {
this._handleSearch(this.input.value); this._handleSearch(this.input.value);
@ -1412,8 +1415,8 @@ class Choices {
* @private * @private
*/ */
_onTouchMove() { _onTouchMove() {
if (this.wasTap === true) { if (this._wasTap === true) {
this.wasTap = false; this._wasTap = false;
} }
} }
@ -1427,13 +1430,13 @@ class Choices {
const target = (e.target || e.touches[0].target); const target = (e.target || e.touches[0].target);
// If a user tapped within our container... // If a user tapped within our container...
if (this.wasTap === true && this.containerOuter.element.contains(target)) { if (this._wasTap === true && this.containerOuter.element.contains(target)) {
// ...and we aren't dealing with a single select box, show dropdown/focus input // ...and we aren't dealing with a single select box, show dropdown/focus input
if ( if (
(target === this.containerOuter.element || target === this.containerInner.element) && (target === this.containerOuter.element || target === this.containerInner.element) &&
!this.isSelectOneElement !this._isSelectOneElement
) { ) {
if (this.isTextElement) { if (this._isTextElement) {
// If text element, we only want to focus the input // If text element, we only want to focus the input
this.input.focus(); this.input.focus();
} else { } else {
@ -1445,7 +1448,7 @@ class Choices {
e.stopPropagation(); e.stopPropagation();
} }
this.wasTap = true; this._wasTap = true;
} }
/** /**
@ -1459,11 +1462,11 @@ class Choices {
// If we have our mouse down on the scrollbar and are on IE11... // If we have our mouse down on the scrollbar and are on IE11...
if (target === this.choiceList && isIE11()) { if (target === this.choiceList && isIE11()) {
this.isScrollingOnIe = true; 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 activeItems = this._store.activeItems;
const hasShiftKey = e.shiftKey; const hasShiftKey = e.shiftKey;
const buttonTarget = findAncestorByAttrName(target, 'data-button'); const buttonTarget = findAncestorByAttrName(target, 'data-button');
@ -1509,12 +1512,12 @@ class Choices {
_onClick(e) { _onClick(e) {
const target = e.target; const target = e.target;
const hasActiveDropdown = this.dropdown.isActive; const hasActiveDropdown = this.dropdown.isActive;
const activeItems = this.store.activeItems; const activeItems = this._store.activeItems;
// If target is something that concerns us // If target is something that concerns us
if (this.containerOuter.element.contains(target)) { if (this.containerOuter.element.contains(target)) {
if (!hasActiveDropdown) { if (!hasActiveDropdown) {
if (this.isTextElement) { if (this._isTextElement) {
if (document.activeElement !== this.input.element) { if (document.activeElement !== this.input.element) {
this.input.focus(); this.input.focus();
} }
@ -1526,7 +1529,7 @@ class Choices {
this.containerOuter.focus(); this.containerOuter.focus();
} }
} else if ( } else if (
this.isSelectOneElement && this._isSelectOneElement &&
target !== this.input.element && target !== this.input.element &&
!this.dropdown.element.contains(target) !this.dropdown.element.contains(target)
) { ) {
@ -1595,8 +1598,8 @@ class Choices {
_onBlur(e) { _onBlur(e) {
const target = e.target; const target = e.target;
// If target is something that concerns us // 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 activeItems = this._store.activeItems;
const hasHighlightedItems = activeItems.some(item => item.highlighted); const hasHighlightedItems = activeItems.some(item => item.highlighted);
const blurActions = { const blurActions = {
text: () => { text: () => {
@ -1635,7 +1638,7 @@ class Choices {
// On IE11, clicking the scollbar blurs our input and thus // On IE11, clicking the scollbar blurs our input and thus
// closes the dropdown. To stop this, we refocus our input // closes the dropdown. To stop this, we refocus our input
// if we know we are on IE *and* are scrolling. // if we know we are on IE *and* are scrolling.
this.isScrollingOnIe = false; this._isScrollingOnIe = false;
this.input.element.focus(); this.input.element.focus();
} }
} }
@ -1727,12 +1730,12 @@ class Choices {
}); });
if (passedEl) { if (passedEl) {
this.highlightPosition = choices.indexOf(passedEl); this._highlightPosition = choices.indexOf(passedEl);
} else { } else {
// Highlight choice based on last known highlight location // Highlight choice based on last known highlight location
if (choices.length > this.highlightPosition) { if (choices.length > this._highlightPosition) {
// If we have an option to highlight // If we have an option to highlight
passedEl = choices[this.highlightPosition]; passedEl = choices[this._highlightPosition];
} else { } else {
// Otherwise highlight the option before // Otherwise highlight the option before
passedEl = choices[choices.length - 1]; passedEl = choices[choices.length - 1];
@ -1775,16 +1778,13 @@ class Choices {
keyCode = null, keyCode = null,
) { ) {
let passedValue = isType('String', value) ? value.trim() : value; let passedValue = isType('String', value) ? value.trim() : value;
const passedKeyCode = keyCode; const passedKeyCode = keyCode;
const passedCustomProperties = customProperties; const passedCustomProperties = customProperties;
const items = this.store.items; const items = this._store.items;
const passedLabel = label || passedValue; const passedLabel = label || passedValue;
const passedOptionId = parseInt(choiceId, 10) || -1; const passedOptionId = parseInt(choiceId, 10) || -1;
const group = groupId >= 0 ? this._store.getGroupById(groupId) : null;
// Get group if group ID passed
const group = groupId >= 0 ? this.store.getGroupById(groupId) : null;
// Generate unique id
const id = items ? items.length + 1 : 1; const id = items ? items.length + 1 : 1;
// If a prepended value has been passed, prepend it // If a prepended value has been passed, prepend it
@ -1797,7 +1797,7 @@ class Choices {
passedValue += this.config.appendValue.toString(); passedValue += this.config.appendValue.toString();
} }
this.store.dispatch( this._store.dispatch(
addItem( addItem(
passedValue, passedValue,
passedLabel, passedLabel,
@ -1810,7 +1810,7 @@ class Choices {
), ),
); );
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
this.removeActiveItems(id); this.removeActiveItems(id);
} }
@ -1849,9 +1849,9 @@ class Choices {
} }
const { id, value, label, choiceId, groupId } = item; const { id, value, label, choiceId, groupId } = item;
const group = groupId >= 0 ? this.store.getGroupById(groupId) : null; const group = groupId >= 0 ? this._store.getGroupById(groupId) : null;
this.store.dispatch(removeItem(id, choiceId)); this._store.dispatch(removeItem(id, choiceId));
if (group && group.value) { if (group && group.value) {
this.passedElement.triggerEvent(EVENTS.removeItem, { this.passedElement.triggerEvent(EVENTS.removeItem, {
@ -1897,12 +1897,12 @@ class Choices {
} }
// Generate unique id // Generate unique id
const choices = this.store.choices; const choices = this._store.choices;
const choiceLabel = label || value; const choiceLabel = label || value;
const choiceId = choices ? choices.length + 1 : 1; 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( this._store.dispatch(
addChoice( addChoice(
value, value,
choiceLabel, choiceLabel,
@ -1935,7 +1935,7 @@ class Choices {
* @private * @private
*/ */
_clearChoices() { _clearChoices() {
this.store.dispatch(clearChoices()); this._store.dispatch(clearChoices());
} }
/** /**
@ -1955,7 +1955,7 @@ class Choices {
const isDisabled = group.disabled ? group.disabled : false; const isDisabled = group.disabled ? group.disabled : false;
if (groupChoices) { if (groupChoices) {
this.store.dispatch( this._store.dispatch(
addGroup( addGroup(
group.label, group.label,
groupId, groupId,
@ -1979,7 +1979,7 @@ class Choices {
groupChoices.forEach(addGroupChoices); groupChoices.forEach(addGroupChoices);
} else { } else {
this.store.dispatch( this._store.dispatch(
addGroup( addGroup(
group.label, group.label,
group.id, group.id,
@ -2029,14 +2029,14 @@ class Choices {
const direction = this.passedElement.element.getAttribute('dir') || 'ltr'; const direction = this.passedElement.element.getAttribute('dir') || 'ltr';
const containerOuter = this._getTemplate('containerOuter', const containerOuter = this._getTemplate('containerOuter',
direction, direction,
this.isSelectElement, this._isSelectElement,
this.isSelectOneElement, this._isSelectOneElement,
this.config.searchEnabled, this.config.searchEnabled,
this.passedElement.element.type, this.passedElement.element.type,
); );
const containerInner = this._getTemplate('containerInner'); const containerInner = this._getTemplate('containerInner');
const itemList = this._getTemplate('itemList', this.isSelectOneElement); 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 input = this._getTemplate('input');
const dropdown = this._getTemplate('dropdown'); const dropdown = this._getTemplate('dropdown');
@ -2088,10 +2088,10 @@ class Choices {
// Wrapper inner container with outer container // Wrapper inner container with outer container
this.containerOuter.wrap(this.containerInner.element); this.containerOuter.wrap(this.containerInner.element);
if (this.isSelectOneElement) { if (this._isSelectOneElement) {
this.input.placeholder = (this.config.searchPlaceholderValue || ''); this.input.placeholder = (this.config.searchPlaceholderValue || '');
} else if (this.placeholderValue) { } else if (this._placeholderValue) {
this.input.placeholder = this.placeholderValue; this.input.placeholder = this._placeholderValue;
this.input.setWidth(true); this.input.setWidth(true);
} }
@ -2103,19 +2103,19 @@ class Choices {
this.containerOuter.element.appendChild(this.dropdown.element); this.containerOuter.element.appendChild(this.dropdown.element);
this.containerInner.element.appendChild(this.itemList.element); this.containerInner.element.appendChild(this.itemList.element);
if (!this.isTextElement) { if (!this._isTextElement) {
this.dropdown.element.appendChild(this.choiceList.element); this.dropdown.element.appendChild(this.choiceList.element);
} }
if (!this.isSelectOneElement) { if (!this._isSelectOneElement) {
this.containerInner.element.appendChild(this.input.element); this.containerInner.element.appendChild(this.input.element);
} else if (this.config.searchEnabled) { } 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) { if (this._isSelectElement) {
this._addPredefinedChoices(); this._addPredefinedChoices();
} else if (this.isTextElement) { } else if (this._isTextElement) {
this._addPredefinedItems(); this._addPredefinedItems();
} }
} }
@ -2123,8 +2123,8 @@ class Choices {
_addPredefinedChoices() { _addPredefinedChoices() {
const passedGroups = this.passedElement.optionGroups; const passedGroups = this.passedElement.optionGroups;
this.highlightPosition = 0; this._highlightPosition = 0;
this.isSearching = false; this._isSearching = false;
if (passedGroups && passedGroups.length) { if (passedGroups && passedGroups.length) {
// If we have a placeholder option // If we have a placeholder option
@ -2147,7 +2147,7 @@ class Choices {
} else { } else {
const passedOptions = this.passedElement.options; const passedOptions = this.passedElement.options;
const filter = this.config.sortFn; const filter = this.config.sortFn;
const allChoices = this.presetChoices; const allChoices = this._presetChoices;
// Create array of options from option elements // Create array of options from option elements
passedOptions.forEach((o) => { passedOptions.forEach((o) => {
@ -2168,7 +2168,7 @@ class Choices {
// Determine whether there is a selected choice // Determine whether there is a selected choice
const hasSelectedChoice = allChoices.some(choice => choice.selected); const hasSelectedChoice = allChoices.some(choice => choice.selected);
const handleChoice = (choice, index) => { const handleChoice = (choice, index) => {
if (this.isSelectElement) { if (this._isSelectElement) {
// If the choice is actually a group // If the choice is actually a group
if (choice.choices) { if (choice.choices) {
this._addGroup(choice, choice.id || null); this._addGroup(choice, choice.id || null);
@ -2176,7 +2176,7 @@ class Choices {
// If there is a selected choice already or the choice is not // If there is a selected choice already or the choice is not
// the first in the array, add each choice normally // the first in the array, add each choice normally
// Otherwise pre-select the first choice in the array if it's a single select // 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 isSelected = shouldPreselect ? true : choice.selected;
const isDisabled = shouldPreselect ? false : choice.disabled; const isDisabled = shouldPreselect ? false : choice.disabled;
@ -2228,7 +2228,7 @@ class Choices {
} }
}; };
this.presetItems.forEach(item => handlePresetItem(item)); this._presetItems.forEach(item => handlePresetItem(item));
} }
_setChoiceOrItem(item) { _setChoiceOrItem(item) {
@ -2241,7 +2241,7 @@ class Choices {
// If we are dealing with a select input, we need to create an option first // If we are dealing with a select input, we need to create an option first
// that is then selected. For text inputs we can just add items normally. // that is then selected. For text inputs we can just add items normally.
if (!this.isTextElement) { if (!this._isTextElement) {
this._addChoice( this._addChoice(
item.value, item.value,
item.label, item.label,
@ -2262,7 +2262,7 @@ class Choices {
} }
}, },
string: () => { string: () => {
if (!this.isTextElement) { if (!this._isTextElement) {
this._addChoice( this._addChoice(
item, item,
item, item,
@ -2280,7 +2280,7 @@ class Choices {
} }
_findAndSelectChoiceByValue(val) { _findAndSelectChoiceByValue(val) {
const choices = this.store.choices; const choices = this._store.choices;
// Check 'value' property exists and the choice isn't already selected // 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));
@ -2317,7 +2317,7 @@ class Choices {
} }
_generatePlaceholderValue() { _generatePlaceholderValue() {
if (!this.isSelectOneElement) { if (!this._isSelectOneElement) {
return this.config.placeholder ? return this.config.placeholder ?
(this.config.placeholderValue || this.passedElement.element.getAttribute('placeholder')) : (this.config.placeholderValue || this.passedElement.element.getAttribute('placeholder')) :
false; false;
@ -2328,8 +2328,8 @@ class Choices {
_renderChoices() { _renderChoices() {
// Get active groups/choices // Get active groups/choices
const activeGroups = this.store.activeGroups; const activeGroups = this._store.activeGroups;
const activeChoices = this.store.activeChoices; const activeChoices = this._store.activeChoices;
let choiceListFragment = document.createDocumentFragment(); let choiceListFragment = document.createDocumentFragment();
@ -2342,7 +2342,7 @@ class Choices {
} }
// If we have grouped options // If we have grouped options
if (activeGroups.length >= 1 && !this.isSearching) { if (activeGroups.length >= 1 && !this._isSearching) {
// If we have a placeholder choice along with groups // If we have a placeholder choice along with groups
const activePlaceholders = activeChoices.filter( const activePlaceholders = activeChoices.filter(
activeChoice => activeChoice.placeholder === true && activeChoice.groupId === -1, activeChoice => activeChoice.placeholder === true && activeChoice.groupId === -1,
@ -2361,7 +2361,7 @@ class Choices {
// If we have choices to show // 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 activeItems = this._store.activeItems;
const canAddItem = this._canAddItem(activeItems, this.input.value); const canAddItem = this._canAddItem(activeItems, this.input.value);
// ...and we can select them // ...and we can select them
@ -2378,7 +2378,7 @@ class Choices {
let dropdownItem; let dropdownItem;
let notice; let notice;
if (this.isSearching) { if (this._isSearching) {
notice = isType('Function', this.config.noResultsText) ? notice = isType('Function', this.config.noResultsText) ?
this.config.noResultsText() : this.config.noResultsText() :
this.config.noResultsText; this.config.noResultsText;
@ -2398,7 +2398,7 @@ class Choices {
_renderItems() { _renderItems() {
// Get active items (items that can be selected) // Get active items (items that can be selected)
const activeItems = this.store.activeItems || []; const activeItems = this._store.activeItems || [];
// Clear list // Clear list
this.itemList.clear(); this.itemList.clear();

View file

@ -60,7 +60,7 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
createTemplatesSpy = spy(instance, '_createTemplates'); createTemplatesSpy = spy(instance, '_createTemplates');
createInputSpy = spy(instance, '_createStructure'); createInputSpy = spy(instance, '_createStructure');
storeSubscribeSpy = spy(instance.store, 'subscribe'); storeSubscribeSpy = spy(instance._store, 'subscribe');
renderSpy = spy(instance, 'render'); renderSpy = spy(instance, 'render');
addEventListenersSpy = spy(instance, '_addEventListeners'); addEventListenersSpy = spy(instance, '_addEventListeners');
@ -152,33 +152,27 @@ describe('choices', () => {
}); });
it('removes event listeners', () => { it('removes event listeners', () => {
requestAnimationFrame;
expect(removeEventListenersSpy.called).to.equal(true); expect(removeEventListenersSpy.called).to.equal(true);
}); });
it('reveals passed element', () => { it('reveals passed element', () => {
requestAnimationFrame;
expect(passedElementRevealSpy.called).to.equal(true); expect(passedElementRevealSpy.called).to.equal(true);
}); });
it('reverts outer container', () => { it('reverts outer container', () => {
requestAnimationFrame;
expect(containerOuterUnwrapSpy.called).to.equal(true); 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', () => { it('clears store', () => {
requestAnimationFrame;
expect(clearStoreSpy.called).to.equal(true); expect(clearStoreSpy.called).to.equal(true);
}); });
it('nullifys templates config', () => { it('nullifys templates config', () => {
requestAnimationFrame;
expect(instance.config.templates).to.equal(null); expect(instance.config.templates).to.equal(null);
}); });
it('resets initialise flag', () => { it('resets initialise flag', () => {
requestAnimationFrame;
expect(instance.initialised).to.equal(false); expect(instance.initialised).to.equal(false);
}); });
}); });
@ -406,7 +400,7 @@ describe('choices', () => {
describe('passing true focusInput flag with canSearch set to true', () => { describe('passing true focusInput flag with canSearch set to true', () => {
beforeEach(() => { beforeEach(() => {
instance.dropdown.isActive = false; instance.dropdown.isActive = false;
instance.canSearch = true; instance._canSearch = true;
output = instance.showDropdown(true); output = instance.showDropdown(true);
}); });
@ -497,7 +491,7 @@ describe('choices', () => {
describe('passing true blurInput flag with canSearch set to true', () => { describe('passing true blurInput flag with canSearch set to true', () => {
beforeEach(() => { beforeEach(() => {
instance.dropdown.isActive = true; instance.dropdown.isActive = true;
instance.canSearch = true; instance._canSearch = true;
output = instance.hideDropdown(true); output = instance.hideDropdown(true);
}); });
@ -573,15 +567,15 @@ describe('choices', () => {
storeGetGroupByIdStub = stub().returns({ storeGetGroupByIdStub = stub().returns({
value: groupIdValue, value: groupIdValue,
}); });
storeDispatchSpy = spy(instance.store, 'dispatch'); storeDispatchSpy = spy(instance._store, 'dispatch');
instance.store.getGroupById = storeGetGroupByIdStub; instance._store.getGroupById = storeGetGroupByIdStub;
instance.passedElement.triggerEvent = passedElementTriggerEventStub; instance.passedElement.triggerEvent = passedElementTriggerEventStub;
}); });
afterEach(() => { afterEach(() => {
storeDispatchSpy.restore(); storeDispatchSpy.restore();
instance.store.getGroupById.reset(); instance._store.getGroupById.reset();
instance.passedElement.triggerEvent.reset(); instance.passedElement.triggerEvent.reset();
}); });
@ -684,15 +678,15 @@ describe('choices', () => {
storeGetGroupByIdStub = stub().returns({ storeGetGroupByIdStub = stub().returns({
value: groupIdValue, value: groupIdValue,
}); });
storeDispatchSpy = spy(instance.store, 'dispatch'); storeDispatchSpy = spy(instance._store, 'dispatch');
instance.store.getGroupById = storeGetGroupByIdStub; instance._store.getGroupById = storeGetGroupByIdStub;
instance.passedElement.triggerEvent = passedElementTriggerEventStub; instance.passedElement.triggerEvent = passedElementTriggerEventStub;
}); });
afterEach(() => { afterEach(() => {
storeDispatchSpy.restore(); storeDispatchSpy.restore();
instance.store.getGroupById.reset(); instance._store.getGroupById.reset();
instance.passedElement.triggerEvent.reset(); instance.passedElement.triggerEvent.reset();
}); });
@ -800,7 +794,7 @@ describe('choices', () => {
]; ];
beforeEach(() => { beforeEach(() => {
storeGetItemsStub = stub(instance.store, 'items').get(() => items); storeGetItemsStub = stub(instance._store, 'items').get(() => items);
highlightItemStub = stub(); highlightItemStub = stub();
instance.highlightItem = highlightItemStub; instance.highlightItem = highlightItemStub;
@ -838,7 +832,7 @@ describe('choices', () => {
]; ];
beforeEach(() => { beforeEach(() => {
storeGetItemsStub = stub(instance.store, 'items').get(() => items); storeGetItemsStub = stub(instance._store, 'items').get(() => items);
unhighlightItemStub = stub(); unhighlightItemStub = stub();
instance.unhighlightItem = unhighlightItemStub; instance.unhighlightItem = unhighlightItemStub;
@ -865,13 +859,13 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
storeDispatchStub = stub(); storeDispatchStub = stub();
instance.store.dispatch = storeDispatchStub; instance._store.dispatch = storeDispatchStub;
output = instance.clearStore(); output = instance.clearStore();
}); });
afterEach(() => { afterEach(() => {
instance.store.dispatch.reset(); instance._store.dispatch.reset();
}); });
returnsInstance(output); returnsInstance(output);
@ -890,21 +884,21 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
inputClearSpy = spy(instance.input, 'clear'); inputClearSpy = spy(instance.input, 'clear');
storeDispatchStub = stub(); storeDispatchStub = stub();
instance.store.dispatch = storeDispatchStub; instance._store.dispatch = storeDispatchStub;
output = instance.clearInput(); output = instance.clearInput();
}); });
afterEach(() => { afterEach(() => {
inputClearSpy.restore(); inputClearSpy.restore();
instance.store.dispatch.reset(); instance._store.dispatch.reset();
}); });
returnsInstance(output); returnsInstance(output);
describe('text element', () => { describe('text element', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = false; instance._isSelectOneElement = false;
instance.isTextElement = false; instance._isTextElement = false;
output = instance.clearInput(); output = instance.clearInput();
}); });
@ -917,8 +911,8 @@ describe('choices', () => {
describe('select element with search enabled', () => { describe('select element with search enabled', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = true; instance._isSelectOneElement = true;
instance.isTextElement = false; instance._isTextElement = false;
instance.config.searchEnabled = true; instance.config.searchEnabled = true;
output = instance.clearInput(); output = instance.clearInput();
@ -930,7 +924,7 @@ describe('choices', () => {
}); });
it('resets search flag', () => { it('resets search flag', () => {
expect(instance.isSearching).to.equal(false); expect(instance._isSearching).to.equal(false);
}); });
it('dispatches activateChoices action', () => { it('dispatches activateChoices action', () => {
@ -981,7 +975,7 @@ describe('choices', () => {
describe('text element', () => { describe('text element', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectElement = false; instance._isSelectElement = false;
output = instance.ajax(() => {}); output = instance.ajax(() => {});
}); });
@ -1003,7 +997,7 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
instance.initialised = true; instance.initialised = true;
instance.isSelectElement = true; instance._isSelectElement = true;
ajaxCallbackStub = stub(); ajaxCallbackStub = stub();
callback = stub(); callback = stub();
output = instance.ajax(callback); output = instance.ajax(callback);
@ -1100,7 +1094,7 @@ describe('choices', () => {
describe('when already initialised and not text element', () => { describe('when already initialised and not text element', () => {
beforeEach(() => { beforeEach(() => {
instance.initialised = true; instance.initialised = true;
instance.isTextElement = false; instance._isTextElement = false;
}); });
describe('passing a string value', () => { describe('passing a string value', () => {
@ -1153,7 +1147,7 @@ describe('choices', () => {
]; ];
beforeEach(() => { beforeEach(() => {
activeItemsStub = stub(instance.store, 'activeItems').get(() => items); activeItemsStub = stub(instance._store, 'activeItems').get(() => items);
}); });
afterEach(() => { afterEach(() => {
@ -1163,7 +1157,7 @@ describe('choices', () => {
describe('passing true valueOnly flag', () => { describe('passing true valueOnly flag', () => {
describe('select one input', () => { describe('select one input', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = true; instance._isSelectOneElement = true;
output = instance.getValue(true); output = instance.getValue(true);
}); });
@ -1174,7 +1168,7 @@ describe('choices', () => {
describe('non select one input', () => { describe('non select one input', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = false; instance._isSelectOneElement = false;
output = instance.getValue(true); output = instance.getValue(true);
}); });
@ -1187,7 +1181,7 @@ describe('choices', () => {
describe('passing false valueOnly flag', () => { describe('passing false valueOnly flag', () => {
describe('select one input', () => { describe('select one input', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = true; instance._isSelectOneElement = true;
output = instance.getValue(false); output = instance.getValue(false);
}); });
@ -1198,7 +1192,7 @@ describe('choices', () => {
describe('non select one input', () => { describe('non select one input', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = false; instance._isSelectOneElement = false;
output = instance.getValue(false); output = instance.getValue(false);
}); });
@ -1239,7 +1233,7 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
removeItemStub = stub(); removeItemStub = stub();
activeItemsStub = stub(instance.store, 'activeItems').get(() => items); activeItemsStub = stub(instance._store, 'activeItems').get(() => items);
instance._removeItem = removeItemStub; instance._removeItem = removeItemStub;
output = instance.removeActiveItemsByValue(value); output = instance.removeActiveItemsByValue(value);
@ -1278,7 +1272,7 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
removeItemStub = stub(); removeItemStub = stub();
activeItemsStub = stub(instance.store, 'activeItems').get(() => items); activeItemsStub = stub(instance._store, 'activeItems').get(() => items);
instance._removeItem = removeItemStub; instance._removeItem = removeItemStub;
}); });
@ -1333,7 +1327,7 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
highlightedActiveItemsStub = stub(instance.store, 'highlightedActiveItems').get(() => items); highlightedActiveItemsStub = stub(instance._store, 'highlightedActiveItems').get(() => items);
removeItemStub = stub(); removeItemStub = stub();
triggerChangeStub = stub(); triggerChangeStub = stub();
@ -1430,7 +1424,7 @@ describe('choices', () => {
describe('when element is not select element', () => { describe('when element is not select element', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectElement = false; instance._isSelectElement = false;
instance.setChoices(choices, value, label, false); instance.setChoices(choices, value, label, false);
}); });
@ -1440,7 +1434,7 @@ describe('choices', () => {
describe('passing invalid arguments', () => { describe('passing invalid arguments', () => {
describe('passing an empty array', () => { describe('passing an empty array', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectElement = true; instance._isSelectElement = true;
instance.setChoices([], value, label, false); instance.setChoices([], value, label, false);
}); });
@ -1449,7 +1443,7 @@ describe('choices', () => {
describe('passing no value', () => { describe('passing no value', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectElement = true; instance._isSelectElement = true;
instance.setChoices(choices, undefined, 'label', false); instance.setChoices(choices, undefined, 'label', false);
}); });
@ -1459,7 +1453,7 @@ describe('choices', () => {
describe('passing valid arguments', () => { describe('passing valid arguments', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectElement = true; instance._isSelectElement = true;
}); });
it('removes loading state', () => { it('removes loading state', () => {
@ -1629,7 +1623,7 @@ describe('choices', () => {
describe('select-one element', () => { describe('select-one element', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = true; instance._isSelectOneElement = true;
}); });
it('calls _createChoicesFragment with choices that belong to each group', () => { it('calls _createChoicesFragment with choices that belong to each group', () => {
@ -1667,7 +1661,7 @@ describe('choices', () => {
describe('text/select-multiple element', () => { describe('text/select-multiple element', () => {
describe('renderSelectedChoices set to "always"', () => { describe('renderSelectedChoices set to "always"', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = false; instance._isSelectOneElement = false;
instance.config.renderSelectedChoices = 'always'; instance.config.renderSelectedChoices = 'always';
}); });
@ -1705,7 +1699,7 @@ describe('choices', () => {
describe('renderSelectedChoices not set to "always"', () => { describe('renderSelectedChoices not set to "always"', () => {
beforeEach(() => { beforeEach(() => {
instance.isSelectOneElement = false; instance._isSelectOneElement = false;
instance.config.renderSelectedChoices = false; instance.config.renderSelectedChoices = false;
}); });
@ -1737,31 +1731,31 @@ describe('choices', () => {
}); });
}); });
describe('render', () => { // describe('render', () => {
beforeEach(() => {}); // beforeEach(() => {});
describe('no change to state', () => { // describe('no change to state', () => {
it('returns early', () => {}); // it('returns early', () => {});
}); // });
describe('change to state', () => { // describe('change to state', () => {
it('updates previous state to current state', () => {}); // it('updates previous state to current state', () => {});
describe('select element', () => { // describe('select element', () => {
it('clears choice list', () => {}); // it('clears choice list', () => {});
describe('when resetScrollPosition config option is set to true', () => { // describe('when resetScrollPosition config option is set to true', () => {
it('scrolls to top of choice list', () => {}); // it('scrolls to top of choice list', () => {});
}); // });
}); // });
describe('text element', () => { // describe('text element', () => {
describe('active items in store', () => { // describe('active items in store', () => {
it('clears item list', () => {}); // it('clears item list', () => {});
it('renders active items inside item list', () => {}); // it('renders active items inside item list', () => {});
}); // });
}); // });
}); // });
}); // });
}); });
}); });

View file

@ -119,12 +119,12 @@ export default class Input {
* @return * @return
*/ */
setWidth(enforceWidth) { setWidth(enforceWidth) {
if (this.placeholderValue) { if (this._placeholderValue) {
// If there is a placeholder, we only want to set the width of the input when it is a greater // If there is a placeholder, we only want to set the width of the input when it is a greater
// length than 75% of the placeholder. This stops the input jumping around. // length than 75% of the placeholder. This stops the input jumping around.
if ( if (
(this.element.value && (this.element.value &&
this.element.value.length >= (this.placeholderValue.length / 1.25)) || this.element.value.length >= (this._placeholderValue.length / 1.25)) ||
enforceWidth enforceWidth
) { ) {
this.element.style.width = this.calcWidth(); this.element.style.width = this.calcWidth();

View file

@ -281,7 +281,7 @@ describe('components/input', () => {
describe('with a placeholder', () => { describe('with a placeholder', () => {
describe('when value length is greater or equal to 75% of the placeholder length', () => { describe('when value length is greater or equal to 75% of the placeholder length', () => {
it('sets the width of the element based on input value', () => { it('sets the width of the element based on input value', () => {
instance.placeholderValue = 'This is a test'; instance._placeholderValue = 'This is a test';
instance.element.value = 'This is a test'; instance.element.value = 'This is a test';
expect(instance.element.style.width).to.not.equal(inputWidth); expect(instance.element.style.width).to.not.equal(inputWidth);
instance.setWidth(); instance.setWidth();
@ -292,7 +292,7 @@ describe('components/input', () => {
describe('when width is enforced', () => { describe('when width is enforced', () => {
it('sets the width of the element based on input value', () => { it('sets the width of the element based on input value', () => {
instance.placeholderValue = 'This is a test'; instance._placeholderValue = 'This is a test';
instance.element.value = ''; instance.element.value = '';
expect(instance.element.style.width).to.not.equal(inputWidth); expect(instance.element.style.width).to.not.equal(inputWidth);
instance.setWidth(true); instance.setWidth(true);
@ -303,7 +303,7 @@ describe('components/input', () => {
describe('when value length is less than 75% of the placeholder length', () => { describe('when value length is less than 75% of the placeholder length', () => {
it('does not set the width of the element', () => { it('does not set the width of the element', () => {
instance.placeholderValue = 'This is a test'; instance._placeholderValue = 'This is a test';
instance.element.value = 'Test'; instance.element.value = 'Test';
instance.setWidth(); instance.setWidth();
expect(calcWidthStub.callCount).to.equal(0); expect(calcWidthStub.callCount).to.equal(0);

View file

@ -3,7 +3,7 @@ import rootReducer from './../reducers/index';
export default class Store { export default class Store {
constructor() { constructor() {
this.store = createStore( this._store = createStore(
rootReducer, rootReducer,
window.devToolsExtension ? window.devToolsExtension ?
window.devToolsExtension() : window.devToolsExtension() :
@ -17,7 +17,7 @@ export default class Store {
* @return * @return
*/ */
subscribe(onChange) { subscribe(onChange) {
this.store.subscribe(onChange); this._store.subscribe(onChange);
} }
/** /**
@ -26,7 +26,7 @@ export default class Store {
* @return * @return
*/ */
dispatch(action) { dispatch(action) {
this.store.dispatch(action); this._store.dispatch(action);
} }
/** /**
@ -34,7 +34,7 @@ export default class Store {
* @return {Object} State * @return {Object} State
*/ */
get state() { get state() {
return this.store.getState(); return this._store.getState();
} }
/** /**

View file

@ -10,9 +10,9 @@ describe('reducers/store', () => {
beforeEach(() => { beforeEach(() => {
instance = new Store(); instance = new Store();
subscribeStub = sinon.stub(instance.store, 'subscribe'); subscribeStub = sinon.stub(instance._store, 'subscribe');
dispatchStub = sinon.stub(instance.store, 'dispatch'); dispatchStub = sinon.stub(instance._store, 'dispatch');
getStateStub = sinon.stub(instance.store, 'getState'); getStateStub = sinon.stub(instance._store, 'getState');
}); });
afterEach(() => { afterEach(() => {
@ -24,7 +24,7 @@ describe('reducers/store', () => {
describe('constructor', () => { describe('constructor', () => {
it('creates redux store', () => { it('creates redux store', () => {
expect(instance.store).to.contain.keys([ expect(instance._store).to.contain.keys([
'subscribe', 'subscribe',
'dispatch', 'dispatch',
'getState', 'getState',