Reinstate method to remove item by value + general refactoring

This commit is contained in:
Josh Johnson 2016-04-17 12:02:28 +01:00
parent ed66199c35
commit e1d138ba42
6 changed files with 82 additions and 89 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,51 +1,51 @@
export const addItem = (value, label, id, optionId) => { export const addItem = (value, label, id, optionId) => {
return { return {
type: 'ADD_ITEM', type: 'ADD_ITEM',
value: value, value,
label: label, label,
id: parseInt(id), id,
optionId: parseInt(optionId) optionId,
} }
}; };
export const removeItem = (id, optionId) => { export const removeItem = (id, optionId) => {
return { return {
type: 'REMOVE_ITEM', type: 'REMOVE_ITEM',
id: parseInt(id), id,
optionId: parseInt(optionId) optionId,
} }
}; };
export const selectItem = (id, selected) => { export const selectItem = (id, selected) => {
return { return {
type: 'SELECT_ITEM', type: 'SELECT_ITEM',
id: parseInt(id), id,
selected: selected, selected,
} }
}; };
export const addOption = (value, label, id, groupId) => { export const addOption = (value, label, id, groupId) => {
return { return {
type: 'ADD_OPTION', type: 'ADD_OPTION',
value: value, value,
label: label, label,
id: parseInt(id), id,
groupId: parseInt(groupId) groupId,
} }
}; };
export const selectOption = (id, selected) => { export const selectOption = (id, selected) => {
return { return {
type: 'SELECT_OPTION', type: 'SELECT_OPTION',
id: parseInt(id), id,
selected: selected, selected,
} }
}; };
export const addGroup = (value, id) => { export const addGroup = (value, id) => {
return { return {
type: 'ADD_GROUP', type: 'ADD_GROUP',
value: value, value,
id: parseInt(id) id,
} }
}; };

View file

@ -408,6 +408,7 @@ export class Choices {
let passedValue = value.trim(); let passedValue = value.trim();
let passedLabel = label || passedValue; let passedLabel = label || passedValue;
let passedOptionId = optionId || -1;
// If a prepended value has been passed, prepend it // If a prepended value has been passed, prepend it
if(this.options.prependValue) { if(this.options.prependValue) {
@ -420,7 +421,7 @@ export class Choices {
} }
// Generate unique id // Generate unique id
let id = this.store.getState().items.length + 1; const id = this.store.getState().items.length + 1;
// Close dropdown // Close dropdown
if(this.dropdown && this.dropdown.classList.contains('is-active')) { if(this.dropdown && this.dropdown.classList.contains('is-active')) {
@ -436,7 +437,7 @@ export class Choices {
} }
} }
this.store.dispatch(addItem(passedValue, passedLabel, id, optionId)); this.store.dispatch(addItem(passedValue, passedLabel, id, passedOptionId));
} }
/** /**
@ -444,14 +445,14 @@ export class Choices {
* @param * @param
*/ */
removeItem(item, callback = this.options.callbackOnRemoveItem) { removeItem(item, callback = this.options.callbackOnRemoveItem) {
if(!item) { if(!item || !isType('Object', item)) {
console.error('removeItem: No item or value was passed to be removed'); console.error('removeItem: No item object was passed to be removed');
return; return;
} }
let id = item.id; const id = item.id;
let value = item.value; const value = item.value;
let optionId = item.optionId; const optionId = item.optionId;
// Run callback // Run callback
if(callback){ if(callback){
@ -465,13 +466,27 @@ export class Choices {
this.store.dispatch(removeItem(id, optionId)); this.store.dispatch(removeItem(id, optionId));
} }
removeItemsByValue(value) {
if(!value || !isType('String', value)) {
console.error('removeItemsByValue: No value was passed to be removed');
}
const items = this.getItemsFilteredByActive();
items.forEach((item) => {
if(item.value === value) {
this.removeItem(item);
}
});
}
/** /**
* Remove all items from array * Remove all items from array
* @param {Boolean} selectedOnly Optionally remove only selected items * @param {Boolean} selectedOnly Optionally remove only selected items
* @return * @return
*/ */
removeAllItems() { removeAllItems() {
const items = this.getItems(); const items = this.getItemsFilteredByActive();
items.forEach((item) => { items.forEach((item) => {
if(item.active) { if(item.active) {
@ -481,7 +496,7 @@ export class Choices {
} }
removeAllSelectedItems() { removeAllSelectedItems() {
const items = this.getItems(); const items = this.getItemsFilteredByActive();
items.forEach((item) => { items.forEach((item) => {
if(item.selected && item.active) { if(item.selected && item.active) {
@ -628,15 +643,6 @@ export class Choices {
this.presetItems.forEach((value) => { this.presetItems.forEach((value) => {
this.addItem(value); this.addItem(value);
}); });
// Subscribe to store
this.store.subscribe(this.render);
// Render any items
this.render();
// Trigger event listeners
this.addEventListeners();
} }
/** /**
@ -684,7 +690,6 @@ export class Choices {
this.list = list; this.list = list;
this.dropdown = dropdown; this.dropdown = dropdown;
// const passedGroups;
const passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP')); const passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP'));
if(passedGroups.length) { if(passedGroups.length) {
@ -706,16 +711,6 @@ export class Choices {
this.addOption(option); this.addOption(option);
}); });
} }
// Subscribe to store
this.store.subscribe(this.render);
// Render any items
this.render();
// Trigger event listeners
this.addEventListeners();
} }
/** /**
@ -736,29 +731,13 @@ export class Choices {
document.removeEventListener('paste', this.onPaste); document.removeEventListener('paste', this.onPaste);
} }
observeStore(store, select, onChange) {
let currentState;
function handleChange() {
let nextState = select(store.getState());
if (nextState !== currentState) {
currentState = nextState;
onChange(currentState);
}
}
let unsubscribe = store.subscribe(handleChange);
handleChange();
return unsubscribe;
}
/** /**
* Render DOM with values * Render DOM with values
* @return * @return
*/ */
render(callback = this.options.callbackOnRender) { render(callback = this.options.callbackOnRender) {
const classNames = this.options.classNames; const classNames = this.options.classNames;
const items = this.getItems(); const activeItems = this.getItemsFilteredByActive();
const options = this.getOptions(); const options = this.getOptions();
const groups = this.getGroups(); const groups = this.getGroups();
@ -823,21 +802,21 @@ export class Choices {
} }
// ITEMS // ITEMS
// Simplify store data to just values if(activeItems) {
const itemsFiltered = this.getItemsReducedToValues(); // Simplify store data to just values
const itemsFiltered = this.getItemsReducedToValues();
// Assign hidden input array of values // Assign hidden input array of values
this.passedElement.value = itemsFiltered.join(this.options.delimiter); this.passedElement.value = itemsFiltered.join(this.options.delimiter);
// Clear list // Clear list
this.list.innerHTML = ''; this.list.innerHTML = '';
// 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 itemListFragment = document.createDocumentFragment(); const itemListFragment = document.createDocumentFragment();
// Add each list item to list // Add each list item to list
items.forEach((item) => { activeItems.forEach((item) => {
if(item.active) {
// Create new list element // Create new list element
const listItem = strToEl(` const listItem = strToEl(`
<li class="${ classNames.item } ${ this.options.removeItems ? classNames.itemSelectable : '' } ${ item.selected ? classNames.selectedState : '' }" data-choice-item data-choice-id="${ item.id }" data-choice-selected="${ item.selected }"> <li class="${ classNames.item } ${ this.options.removeItems ? classNames.itemSelectable : '' } ${ item.selected ? classNames.selectedState : '' }" data-choice-item data-choice-id="${ item.id }" data-choice-selected="${ item.selected }">
@ -847,15 +826,15 @@ export class Choices {
// Append it to list // Append it to list
itemListFragment.appendChild(listItem); itemListFragment.appendChild(listItem);
} });
});
this.list.appendChild(itemListFragment); this.list.appendChild(itemListFragment);
}
// Run callback if it is a function // Run callback if it is a function
if(callback){ if(callback){
if(isType('Function', callback)) { if(isType('Function', callback)) {
callback(items, options, groups); callback(activeItems, options, groups);
} else { } else {
console.error('callbackOnRender: Callback is not a function'); console.error('callbackOnRender: Callback is not a function');
} }
@ -880,7 +859,7 @@ export class Choices {
this.generateMultipleSelectInput(); this.generateMultipleSelectInput();
break; break;
default: default:
this.generateMultipleSelectInput(); console.error('renderInput: Input type is not supported');
break; break;
} }
} }
@ -892,7 +871,18 @@ export class Choices {
init(callback = this.options.callbackOnInit) { init(callback = this.options.callbackOnInit) {
if (!this.supports) console.error('init: Your browser doesn\'nt support shit'); if (!this.supports) console.error('init: Your browser doesn\'nt support shit');
this.initialised = true; this.initialised = true;
// Render input
this.renderInput(this.passedElement); this.renderInput(this.passedElement);
// Subscribe to store
this.store.subscribe(this.render);
// Render any items
this.render();
// Trigger event listeners
this.addEventListeners();
// Run callback if it is a function // Run callback if it is a function
if(callback){ if(callback){
if(isType('Function', callback)) { if(isType('Function', callback)) {
@ -951,15 +941,18 @@ document.addEventListener('DOMContentLoaded', () => {
const choices5 = new Choices('#choices-5', { const choices5 = new Choices('#choices-5', {
prependValue: 'item-', prependValue: 'item-',
appendValue: `-${Date.now()}`, appendValue: `-${Date.now()}`,
// callbackOnRender: function(items, options) {
// console.log(items);
// },
}); });
choices5.removeAllItems(); choices5.removeAllItems();
const choices6 = new Choices('#choices-6', { const choices6 = new Choices('#choices-6', {
items: ['josh@joshuajohnson.co.uk', 'joe@bloggs.co.uk'], items: ['josh@joshuajohnson.co.uk', 'joe@bloggs.co.uk'],
// callbackOnRender: function(items, options, groups) { callbackOnRender: function(items, options, groups) {
// console.log(items); console.log(items);
// }, },
}); });
const choices7 = new Choices('#choices-7', { const choices7 = new Choices('#choices-7', {
@ -975,7 +968,7 @@ document.addEventListener('DOMContentLoaded', () => {
// }, // },
}); });
// choices6.addItem('josh2@joshuajohnson.co.uk', () => { console.log('Custom add item callback')}); choices6.addItem('josh2@joshuajohnson.co.uk', null, null, () => { console.log('Custom add item callback')});
// choices6.removeItem('josh@joshuajohnson.co.uk'); choices6.removeItemsByValue('josh@joshuajohnson.co.uk');
// console.log(choices6.getItemById(1)); console.log(choices6.getItemById(3));
}); });

View file

@ -389,7 +389,7 @@ export const getWidthOfInput = (input, initialWidth = 20) => {
document.body.appendChild(testEl); document.body.appendChild(testEl);
if(testEl.offsetWidth > initialWidth && testEl.offsetWidth != input.offsetWidth) { if(testEl.offsetWidth > initialWidth && testEl.offsetWidth != input.offsetWidth) {
width = testEl.offsetWidth + initialWidth; width = testEl.offsetWidth + initialWidth/4;
} }
document.body.removeChild(testEl); document.body.removeChild(testEl);

View file

@ -2,7 +2,7 @@ const groups = (state = [], action) => {
switch (action.type) { switch (action.type) {
case 'ADD_GROUP': case 'ADD_GROUP':
return [...state, { return [...state, {
id: parseInt(action.id), id: action.id,
value: action.value, value: action.value,
disabled: false, disabled: false,
}]; }];

View file

@ -2,7 +2,7 @@ const options = (state = [], action) => {
switch (action.type) { switch (action.type) {
case 'ADD_OPTION': case 'ADD_OPTION':
return [...state, { return [...state, {
id: parseInt(action.id), id: action.id,
groupId: action.groupId, groupId: action.groupId,
value: action.value, value: action.value,
label: action.label, label: action.label,