mirror of
https://github.com/Choices-js/Choices.git
synced 2024-05-23 16:02:21 +02:00
Abstract store getters into own class
This commit is contained in:
parent
345fe885c5
commit
b34db1920a
4
assets/scripts/dist/bundle.js
vendored
4
assets/scripts/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,9 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { createStore } from 'redux';
|
|
||||||
import rootReducer from './reducers/index.js';
|
|
||||||
import { addItem, removeItem, selectItem, addOption, filterOptions, activateOptions, addGroup } from './actions/index';
|
import { addItem, removeItem, selectItem, addOption, filterOptions, activateOptions, addGroup } from './actions/index';
|
||||||
import { isScrolledIntoView, getAdjacentEl, findAncestor, wrap, isType, strToEl, extend, getWidthOfInput, debounce } from './lib/utils.js';
|
import { isScrolledIntoView, getAdjacentEl, findAncestor, wrap, isType, strToEl, extend, getWidthOfInput, debounce } from './lib/utils.js';
|
||||||
import Fuse from 'fuse.js';
|
import Fuse from 'fuse.js';
|
||||||
|
import Store from './store.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Choices
|
* Choices
|
||||||
|
@ -85,7 +84,7 @@ export class Choices {
|
||||||
this.options = extend(defaultOptions, userOptions);
|
this.options = extend(defaultOptions, userOptions);
|
||||||
|
|
||||||
// Create data store
|
// Create data store
|
||||||
this.store = createStore(rootReducer);
|
this.store = new Store();
|
||||||
|
|
||||||
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
|
// Retrieve triggering element (i.e. element with 'data-choice' trigger)
|
||||||
this.passedElement = isType('String', element) ? document.querySelector(element) : element;
|
this.passedElement = isType('String', element) ? document.querySelector(element) : element;
|
||||||
|
@ -227,8 +226,8 @@ export class Choices {
|
||||||
const upKey = 38;
|
const upKey = 38;
|
||||||
const downKey = 40;
|
const downKey = 40;
|
||||||
|
|
||||||
const activeItems = this.getItemsFilteredByActive();
|
const activeItems = this.store.getItemsFilteredByActive();
|
||||||
const activeOptions = this.getOptionsFilteredByActive();
|
const activeOptions = this.store.getOptionsFilteredByActive();
|
||||||
|
|
||||||
const hasFocussedInput = this.input === document.activeElement;
|
const hasFocussedInput = this.input === document.activeElement;
|
||||||
const hasActiveDropdown = this.dropdown && this.dropdown.classList.contains(this.options.classNames.activeState);
|
const hasActiveDropdown = this.dropdown && this.dropdown.classList.contains(this.options.classNames.activeState);
|
||||||
|
@ -326,7 +325,7 @@ export class Choices {
|
||||||
|
|
||||||
if(this.passedElement.type === 'select-multiple' && this.options.allowSearch) {
|
if(this.passedElement.type === 'select-multiple' && this.options.allowSearch) {
|
||||||
if(this.input === document.activeElement) {
|
if(this.input === document.activeElement) {
|
||||||
const options = this.getOptions();
|
const options = this.store.getOptions();
|
||||||
const hasUnactiveOptions = options.some((option) => {
|
const hasUnactiveOptions = options.some((option) => {
|
||||||
return option.active !== true;
|
return option.active !== true;
|
||||||
});
|
});
|
||||||
|
@ -336,7 +335,7 @@ export class Choices {
|
||||||
const handleFilter = debounce(() => {
|
const handleFilter = debounce(() => {
|
||||||
// Ensure value *still* has a value after 500 delay
|
// Ensure value *still* has a value after 500 delay
|
||||||
if(this.input.value && this.input.value.length >= 1) {
|
if(this.input.value && this.input.value.length >= 1) {
|
||||||
const options = this.getOptionsFiltedBySelectable();
|
const options = this.store.getOptionsFiltedBySelectable();
|
||||||
const fuse = new Fuse(options, {
|
const fuse = new Fuse(options, {
|
||||||
keys: ['label', 'value'],
|
keys: ['label', 'value'],
|
||||||
shouldSort: true,
|
shouldSort: true,
|
||||||
|
@ -355,7 +354,7 @@ export class Choices {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} q
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -364,7 +363,7 @@ export class Choices {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
onClick(e) {
|
onClick(e) {
|
||||||
const activeItems = this.getItemsFilteredByActive();
|
const activeItems = this.store.getItemsFilteredByActive();
|
||||||
const hasShiftKey = e.shiftKey ? true : false;
|
const hasShiftKey = e.shiftKey ? true : false;
|
||||||
|
|
||||||
if(this.passedElement.type === 'select-multiple' && !this.dropdown.classList.contains(this.options.classNames.activeState)) {
|
if(this.passedElement.type === 'select-multiple' && !this.dropdown.classList.contains(this.options.classNames.activeState)) {
|
||||||
|
@ -383,7 +382,7 @@ export class Choices {
|
||||||
this.handleClick(activeItems, e.target, hasShiftKey);
|
this.handleClick(activeItems, e.target, hasShiftKey);
|
||||||
} else if(e.target.hasAttribute('data-option')) {
|
} else if(e.target.hasAttribute('data-option')) {
|
||||||
// If we are clicking on an option
|
// If we are clicking on an option
|
||||||
const options = this.getOptionsFilteredByActive();
|
const options = this.store.getOptionsFilteredByActive();
|
||||||
const id = e.target.getAttribute('data-id');
|
const id = e.target.getAttribute('data-id');
|
||||||
const option = options.find((option) => {
|
const option = options.find((option) => {
|
||||||
return option.id === parseInt(id);
|
return option.id === parseInt(id);
|
||||||
|
@ -572,7 +571,7 @@ export class Choices {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
selectAll() {
|
selectAll() {
|
||||||
const items = this.getItems();
|
const items = this.store.getItems();
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
this.selectItem(item);
|
this.selectItem(item);
|
||||||
});
|
});
|
||||||
|
@ -583,7 +582,7 @@ export class Choices {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
deselectAll() {
|
deselectAll() {
|
||||||
const items = this.getItems();
|
const items = this.store.getItems();
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
this.deselectItem(item);
|
this.deselectItem(item);
|
||||||
});
|
});
|
||||||
|
@ -659,7 +658,7 @@ export class Choices {
|
||||||
console.error('removeItemsByValue: No value was passed to be removed');
|
console.error('removeItemsByValue: No value was passed to be removed');
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = this.getItemsFilteredByActive();
|
const items = this.store.getItemsFilteredByActive();
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
if(item.value === value) {
|
if(item.value === value) {
|
||||||
|
@ -675,7 +674,7 @@ export class Choices {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
removeAllItems() {
|
removeAllItems() {
|
||||||
const items = this.getItemsFilteredByActive();
|
const items = this.store.getItemsFilteredByActive();
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
if(item.active) {
|
if(item.active) {
|
||||||
|
@ -690,7 +689,7 @@ export class Choices {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
removeAllSelectedItems() {
|
removeAllSelectedItems() {
|
||||||
const items = this.getItemsFilteredByActive();
|
const items = this.store.getItemsFilteredByActive();
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
if(item.selected && item.active) {
|
if(item.selected && item.active) {
|
||||||
|
@ -789,106 +788,6 @@ export class Choices {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get items from store
|
|
||||||
* @return {Array} Item objects
|
|
||||||
*/
|
|
||||||
getItems() {
|
|
||||||
const state = this.store.getState();
|
|
||||||
return state.items;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get active items from store
|
|
||||||
* @return {Array} Item objects
|
|
||||||
*/
|
|
||||||
getItemsFilteredByActive() {
|
|
||||||
const items = this.getItems();
|
|
||||||
|
|
||||||
const valueArray = items.filter((item) => {
|
|
||||||
return item.active === true;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return valueArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get items from store reduced to just their values
|
|
||||||
* @return {Array} Item objects
|
|
||||||
*/
|
|
||||||
getItemsReducedToValues() {
|
|
||||||
const items = this.getItems();
|
|
||||||
|
|
||||||
const valueArray = items.reduce((prev, current) => {
|
|
||||||
prev.push(current.value);
|
|
||||||
return prev;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return valueArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get options from store
|
|
||||||
* @return {Array} Option objects
|
|
||||||
*/
|
|
||||||
getOptions() {
|
|
||||||
const state = this.store.getState();
|
|
||||||
return state.options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get active options from store
|
|
||||||
* @return {Array} Option objects
|
|
||||||
*/
|
|
||||||
getOptionsFilteredByActive() {
|
|
||||||
const options = this.getOptions();
|
|
||||||
const valueArray = options.filter((option) => {
|
|
||||||
return option.active === true && option.selected !== true;
|
|
||||||
},[]);
|
|
||||||
|
|
||||||
return valueArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get selectable options from store
|
|
||||||
* @return {Array} Option objects
|
|
||||||
*/
|
|
||||||
getOptionsFiltedBySelectable() {
|
|
||||||
const options = this.getOptions();
|
|
||||||
const valueArray = options.filter((option) => {
|
|
||||||
return option.selected === false && option.disabled !== true;
|
|
||||||
},[]);
|
|
||||||
|
|
||||||
return valueArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get groups from store
|
|
||||||
* @return {Array} Group objects
|
|
||||||
*/
|
|
||||||
getGroups() {
|
|
||||||
const state = this.store.getState();
|
|
||||||
return state.groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get active groups from store
|
|
||||||
* @return {Array} Group objects
|
|
||||||
*/
|
|
||||||
getGroupsFilteredByActive() {
|
|
||||||
const groups = this.getGroups();
|
|
||||||
const options = this.getOptions();
|
|
||||||
|
|
||||||
const valueArray = groups.filter((group) => {
|
|
||||||
const isActive = group.active === true && group.disabled === false;
|
|
||||||
const hasActiveOptions = options.some((option) => {
|
|
||||||
return option.active === true && option.disabled === false;
|
|
||||||
});
|
|
||||||
return isActive && hasActiveOptions ? true : false;
|
|
||||||
},[]);
|
|
||||||
|
|
||||||
return valueArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create DOM structure around passed select element
|
* Create DOM structure around passed select element
|
||||||
|
@ -967,12 +866,12 @@ export class Choices {
|
||||||
*/
|
*/
|
||||||
render(callback = this.options.callbackOnRender) {
|
render(callback = this.options.callbackOnRender) {
|
||||||
const classNames = this.options.classNames;
|
const classNames = this.options.classNames;
|
||||||
const activeItems = this.getItemsFilteredByActive();
|
const activeItems = this.store.getItemsFilteredByActive();
|
||||||
|
|
||||||
// OPTIONS
|
// OPTIONS
|
||||||
if(this.passedElement.type === 'select-multiple') {
|
if(this.passedElement.type === 'select-multiple') {
|
||||||
const activeOptions = this.getOptionsFilteredByActive();
|
const activeOptions = this.store.getOptionsFilteredByActive();
|
||||||
const activeGroups = this.getGroupsFilteredByActive();
|
const activeGroups = this.store.getGroupsFilteredByActive();
|
||||||
|
|
||||||
// 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 optionListFragment = document.createDocumentFragment();
|
const optionListFragment = document.createDocumentFragment();
|
||||||
|
@ -1019,7 +918,7 @@ export class Choices {
|
||||||
// ITEMS
|
// ITEMS
|
||||||
if(activeItems) {
|
if(activeItems) {
|
||||||
// Simplify store data to just values
|
// Simplify store data to just values
|
||||||
const itemsFiltered = this.getItemsReducedToValues();
|
const itemsFiltered = this.store.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);
|
||||||
|
|
125
assets/scripts/src/store.js
Normal file
125
assets/scripts/src/store.js
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { createStore } from 'redux';
|
||||||
|
import rootReducer from './reducers/index.js';
|
||||||
|
|
||||||
|
export class Store {
|
||||||
|
constructor() {
|
||||||
|
this.store = createStore(rootReducer);
|
||||||
|
}
|
||||||
|
|
||||||
|
getState() {
|
||||||
|
return this.store.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(callback) {
|
||||||
|
this.store.dispatch(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(callback) {
|
||||||
|
this.store.subscribe(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get items from store
|
||||||
|
* @return {Array} Item objects
|
||||||
|
*/
|
||||||
|
getItems() {
|
||||||
|
const state = this.store.getState();
|
||||||
|
return state.items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active items from store
|
||||||
|
* @return {Array} Item objects
|
||||||
|
*/
|
||||||
|
getItemsFilteredByActive() {
|
||||||
|
const items = this.getItems();
|
||||||
|
|
||||||
|
const values = items.filter((item) => {
|
||||||
|
return item.active === true;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get items from store reduced to just their values
|
||||||
|
* @return {Array} Item objects
|
||||||
|
*/
|
||||||
|
getItemsReducedToValues() {
|
||||||
|
const items = this.getItems();
|
||||||
|
|
||||||
|
const values = items.reduce((prev, current) => {
|
||||||
|
prev.push(current.value);
|
||||||
|
return prev;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get options from store
|
||||||
|
* @return {Array} Option objects
|
||||||
|
*/
|
||||||
|
getOptions() {
|
||||||
|
const state = this.store.getState();
|
||||||
|
return state.options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active options from store
|
||||||
|
* @return {Array} Option objects
|
||||||
|
*/
|
||||||
|
getOptionsFilteredByActive() {
|
||||||
|
const options = this.getOptions();
|
||||||
|
const values = options.filter((option) => {
|
||||||
|
return option.active === true && option.selected !== true;
|
||||||
|
},[]);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get selectable options from store
|
||||||
|
* @return {Array} Option objects
|
||||||
|
*/
|
||||||
|
getOptionsFiltedBySelectable() {
|
||||||
|
const options = this.getOptions();
|
||||||
|
const values = options.filter((option) => {
|
||||||
|
return option.selected === false && option.disabled !== true;
|
||||||
|
},[]);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get groups from store
|
||||||
|
* @return {Array} Group objects
|
||||||
|
*/
|
||||||
|
getGroups() {
|
||||||
|
const state = this.store.getState();
|
||||||
|
return state.groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active groups from store
|
||||||
|
* @return {Array} Group objects
|
||||||
|
*/
|
||||||
|
getGroupsFilteredByActive() {
|
||||||
|
const groups = this.getGroups();
|
||||||
|
const options = this.getOptions();
|
||||||
|
|
||||||
|
const values = groups.filter((group) => {
|
||||||
|
const isActive = group.active === true && group.disabled === false;
|
||||||
|
const hasActiveOptions = options.some((option) => {
|
||||||
|
return option.active === true && option.disabled === false;
|
||||||
|
});
|
||||||
|
return isActive && hasActiveOptions ? true : false;
|
||||||
|
},[]);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Store = module.exports = Store;
|
Loading…
Reference in a new issue