Configurable class names

This commit is contained in:
Josh Johnson 2016-04-11 14:13:50 +01:00
parent f05b49578a
commit 7dc30abff7
2 changed files with 68 additions and 55 deletions

File diff suppressed because one or more lines are too long

View file

@ -37,9 +37,19 @@ export class Choices {
appendValue: false, appendValue: false,
selectAll: true, selectAll: true,
classNames: { classNames: {
input: '', containerOuter: 'choices',
container: '', containerInner: 'choices__inner',
input: 'choices__input',
inputCloned: 'choices__input--cloned',
list: 'choices__list',
listItems: 'choices__list--items',
listDropdown: 'choices__list--dropdown',
item: 'choices__item',
itemSelectable: 'choices__item--selectable',
activeState: 'is-active',
disabledState: 'is-disabled',
hiddenState: 'is-hidden',
selectedState: 'is-selected'
}, },
callbackOnInit: function() {}, callbackOnInit: function() {},
callbackOnRender: function() {}, callbackOnRender: function() {},
@ -77,7 +87,6 @@ export class Choices {
this.onKeyDown = this.onKeyDown.bind(this); this.onKeyDown = this.onKeyDown.bind(this);
this.onClick = this.onClick.bind(this); this.onClick = this.onClick.bind(this);
this.onFocus = this.onFocus.bind(this); this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
// Let's have it large // Let's have it large
this.init(); this.init();
@ -181,7 +190,7 @@ export class Choices {
let handleBackspaceKey = () => { let handleBackspaceKey = () => {
if(this.options.removeItems) { if(this.options.removeItems) {
let currentListItems = this.list.querySelectorAll('[data-choice-item]'); let currentListItems = this.list.querySelectorAll('[data-choice-item]');
let selectedItems = this.list.querySelectorAll('.is-selected'); let selectedItems = this.list.querySelectorAll(this.options.classNames.selectedState);
let lastItem = currentListItems[currentListItems.length - 1]; let lastItem = currentListItems[currentListItems.length - 1];
let inputIsFocussed = this.input === document.activeElement; let inputIsFocussed = this.input === document.activeElement;
@ -214,38 +223,44 @@ export class Choices {
* @return * @return
*/ */
onClick(e) { onClick(e) {
// I don't like the look of this // If click is affecting a child node of our element
if(e.target.hasAttribute('data-choice-item')) { if(this.containerOuter.contains(e.target)) {
let item = e.target; if(e.target.hasAttribute('data-choice-item')) {
let item = e.target;
let handleClick = (item) => { let handleClick = (item) => {
if(this.options.removeItems) { if(this.options.removeItems) {
let passedId = item.getAttribute('data-choice-id'); let passedId = item.getAttribute('data-choice-id');
let items = this.list.children; let items = this.list.children;
// We only want to select one item with a click // We only want to select one item with a click
// so we deselect any items that aren't the target // so we deselect any items that aren't the target
for (var i = 0; i < items.length; i++) { for (var i = 0; i < items.length; i++) {
let singleItem = items[i]; let singleItem = items[i];
let id = singleItem.getAttribute('data-choice-id');; let id = singleItem.getAttribute('data-choice-id');;
if(id === passedId && !singleItem.classList.contains('is-selected')) { if(id === passedId && !singleItem.classList.contains(this.options.classNames.selectedState)) {
this.selectItem(singleItem); this.selectItem(singleItem);
} else { } else {
this.deselectItem(singleItem); this.deselectItem(singleItem);
} }
} }
}
} }
handleClick(item);
} }
handleClick(item);
}
if(e.target.hasAttribute('data-choice-selectable')) {
let item = e.target; if(e.target.hasAttribute('data-choice-selectable')) {
let value = e.target.getAttribute('data-choice-value'); let item = e.target;
this.addItem(value); let value = e.target.getAttribute('data-choice-value');
this.addItem(value);
}
} else if(this.dropdown && this.dropdown.classList.contains(this.options.classNames.activeState)) {
this.toggleDropdown();
} }
} }
onFocus(e) { onFocus(e) {
@ -254,12 +269,6 @@ export class Choices {
} }
} }
onBlur(e) {
if(this.dropdown) {
this.toggleDropdown();
}
}
/* Methods */ /* Methods */
/** /**
@ -353,6 +362,11 @@ export class Choices {
// Generate unique id // Generate unique id
let id = this.store.getState().length + 1; let id = this.store.getState().length + 1;
// Close dropdown
if(this.dropdown && this.dropdown.classList.contains('is-active')) {
this.toggleDropdown();
}
// Run callback if it is a function // Run callback if it is a function
if(this.options.callbackOnAddItem){ if(this.options.callbackOnAddItem){
if(isType('Function', this.options.callbackOnAddItem)) { if(isType('Function', this.options.callbackOnAddItem)) {
@ -377,6 +391,7 @@ export class Choices {
// We are re-assigning a variable here. Probably shouldn't be doing that... // We are re-assigning a variable here. Probably shouldn't be doing that...
let item; let item;
if(itemOrValue.nodeType) { if(itemOrValue.nodeType) {
item = itemOrValue; item = itemOrValue;
} else { } else {
@ -436,7 +451,7 @@ export class Choices {
} }
addItemToDropdown(value) { addItemToDropdown(value) {
const dropdownItem = strToEl(`<li class="choices__item choices__item--selectable" data-choice-selectable data-choice-value="${value}">${value}</li>`); const dropdownItem = strToEl(`<li class="${ this.options.classNames.item } ${ this.options.classNames.itemSelectable }" data-choice-selectable data-choice-value="${value}">${value}</li>`);
this.dropdown.appendChild(dropdownItem); this.dropdown.appendChild(dropdownItem);
} }
@ -459,11 +474,11 @@ export class Choices {
</div> </div>
*/ */
let containerOuter = strToEl(`<div class="choices choices--active"></div>`); let containerOuter = strToEl(`<div class="${ this.options.classNames.containerOuter }"></div>`);
let containerInner = strToEl(`<div class="choices__inner"></div>`); let containerInner = strToEl(`<div class="${ this.options.classNames.containerInner }"></div>`);
// Hide passed input // Hide passed input
this.passedElement.classList.add('choices__input', 'choices__input--hidden'); this.passedElement.classList.add(this.options.classNames.input, this.options.classNames.hiddenState);
this.passedElement.tabIndex = '-1'; this.passedElement.tabIndex = '-1';
this.passedElement.setAttribute('style', 'display:none;'); this.passedElement.setAttribute('style', 'display:none;');
this.passedElement.setAttribute('aria-hidden', 'true'); this.passedElement.setAttribute('aria-hidden', 'true');
@ -474,8 +489,8 @@ export class Choices {
// Wrapper inner container with outer container // Wrapper inner container with outer container
wrap(containerInner, containerOuter); wrap(containerInner, containerOuter);
let list = strToEl(`<div class="choices__list choices__list--items"></div>`); let list = strToEl(`<ul class="${ this.options.classNames.list } ${ this.options.classNames.listItems }"></ul>`);
let input = strToEl(`<input type="text" class="choices__input choices__input--cloned">`); let input = strToEl(`<input type="text" class="${ this.options.classNames.input } ${ this.options.classNames.inputCloned }">`);
if (this.passedElement.placeholder) { if (this.passedElement.placeholder) {
input.placeholder = this.passedElement.placeholder; input.placeholder = this.passedElement.placeholder;
@ -483,7 +498,7 @@ export class Choices {
if(!this.options.addItems) { if(!this.options.addItems) {
input.disabled = true; input.disabled = true;
containerOuter.classList.add('is-disabled'); containerOuter.classList.add(this.options.classNames.disabledState);
} }
containerOuter.appendChild(containerInner); containerOuter.appendChild(containerInner);
@ -527,11 +542,11 @@ export class Choices {
</div> </div>
*/ */
let containerOuter = strToEl('<div class="choices choices--active"></div>'); let containerOuter = strToEl(`<div class="${ this.options.classNames.containerOuter }"></div>`);
let containerInner = strToEl('<div class="choices__inner"></div>'); let containerInner = strToEl(`<div class="${ this.options.classNames.containerInner }"></div>`);
// Hide passed input // Hide passed input
this.passedElement.classList.add('choices__input', 'choices__input--hidden'); this.passedElement.classList.add(this.options.classNames.input, this.options.classNames.hiddenState);
this.passedElement.tabIndex = '-1'; this.passedElement.tabIndex = '-1';
this.passedElement.setAttribute('style', 'display:none;'); this.passedElement.setAttribute('style', 'display:none;');
this.passedElement.setAttribute('aria-hidden', 'true'); this.passedElement.setAttribute('aria-hidden', 'true');
@ -542,9 +557,9 @@ export class Choices {
// Wrapper inner container with outer container // Wrapper inner container with outer container
wrap(containerInner, containerOuter); wrap(containerInner, containerOuter);
let list = strToEl('<div class="choices__list choices__list--items"></div>'); let list = strToEl(`<ul class="${ this.options.classNames.list } ${ this.options.classNames.listItems }"></ul>`);
let input = strToEl('<input type="text" class="choices__input choices__input--cloned">'); let input = strToEl(`<input type="text" class="${ this.options.classNames.input } ${ this.options.classNames.inputCloned }">`);
let dropdown = strToEl('<div class="choices__list choices__list--dropdown"></div>'); let dropdown = strToEl(`<div class="${ this.options.classNames.list } ${ this.options.classNames.listDropdown }"></div>`);
if (input.placeholder) { if (input.placeholder) {
input.placeholder = this.passedElement.placeholder; input.placeholder = this.passedElement.placeholder;
@ -588,16 +603,14 @@ export class Choices {
addEventListeners() { addEventListeners() {
document.addEventListener('keydown', this.onKeyDown); document.addEventListener('keydown', this.onKeyDown);
this.containerOuter.addEventListener('click', this.onClick); document.addEventListener('click', this.onClick);
this.input.addEventListener('focus', this.onFocus); this.input.addEventListener('focus', this.onFocus);
this.input.addEventListener('blur', this.onBlur);
} }
removeEventListeners() { removeEventListeners() {
document.removeEventListener('keydown', this.onKeyDown); document.removeEventListener('keydown', this.onKeyDown);
this.containerOuter.removeEventListener('click', this.onClick); document.removeEventListener('click', this.onClick);
this.input.removeEventListener('focus', this.onFocus); this.input.removeEventListener('focus', this.onFocus);
this.input.removeEventListener('blur', this.onBlur);
} }
/** /**
@ -623,7 +636,7 @@ export class Choices {
state.forEach((item) => { state.forEach((item) => {
if(item.active) { if(item.active) {
// Create new list element // Create new list element
let listItem = strToEl(`<div class="choices__item ${ this.options.removeItems ? 'choices__item--selectable' : '' } ${ item.selected ? 'is-selected' : '' }" data-choice-item data-choice-id="${ item.id }" data-choice-selected="${ item.selected }">${ item.value }</div>`); let listItem = strToEl(`<li class="choices__item ${ this.options.removeItems ? 'choices__item--selectable' : '' } ${ item.selected ? 'is-selected' : '' }" data-choice-item data-choice-id="${ item.id }" data-choice-selected="${ item.selected }">${ item.value }</li>`);
// Append it to list // Append it to list
this.list.appendChild(listItem); this.list.appendChild(listItem);