Eliminate excessive searches

This commit is contained in:
Josh Johnson 2016-06-07 14:20:37 +01:00
parent d9cb983262
commit 1a9622aaff
3 changed files with 40 additions and 12 deletions

File diff suppressed because one or more lines are too long

View file

@ -86,11 +86,13 @@ export class Choices {
this.initialised = false; this.initialised = false;
this.currentState = {}; this.currentState = {};
this.prevState = {}; this.prevState = {};
this.currentValue = '';
// 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;
this.highlightPosition = 0; this.highlightPosition = 0;
this.canSearch = this.options.allowSearch;
// Assign preset items from passed object first // Assign preset items from passed object first
this.presetItems = this.options.items; this.presetItems = this.options.items;
@ -224,10 +226,13 @@ export class Choices {
this.showDropdown(); this.showDropdown();
} }
this.canSearch = this.options.allowSearch;
switch (e.keyCode) { switch (e.keyCode) {
case aKey: case aKey:
// If CTRL + A or CMD + A have been pressed and there are items to select // If CTRL + A or CMD + A have been pressed and there are items to select
if(ctrlDownKey && hasItems) { if(ctrlDownKey && hasItems) {
this.canSearch = false;
if(this.options.removeItems && !this.input.value && this.options.selectAll && this.input === document.activeElement) { if(this.options.removeItems && !this.input.value && this.options.selectAll && this.input === document.activeElement) {
this.selectAll(this.itemList.children); this.selectAll(this.itemList.children);
} }
@ -235,7 +240,6 @@ export class Choices {
break; break;
case enterKey: case enterKey:
// If enter key is pressed and the input has a value // If enter key is pressed and the input has a value
if(e.target.value && this.passedElement.type === 'text') { if(e.target.value && this.passedElement.type === 'text') {
const value = this.input.value; const value = this.input.value;
@ -275,6 +279,8 @@ export class Choices {
const directionInt = e.keyCode === downKey ? 1 : -1; const directionInt = e.keyCode === downKey ? 1 : -1;
let nextEl; let nextEl;
this.canSearch = false;
if(currentEl) { if(currentEl) {
nextEl = getAdjacentEl(currentEl, '[data-option-selectable]', directionInt); nextEl = getAdjacentEl(currentEl, '[data-option-selectable]', directionInt);
} else { } else {
@ -289,6 +295,10 @@ export class Choices {
} }
this.highlightOption(nextEl); this.highlightOption(nextEl);
} }
// Prevent default to maintain cursor position whilst
// traversing dropdown options
e.preventDefault();
} }
break break
@ -313,6 +323,7 @@ export class Choices {
*/ */
onKeyUp(e) { onKeyUp(e) {
if(e.target !== this.input) return; if(e.target !== this.input) return;
const keyString = String.fromCharCode(event.keyCode);
// 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
@ -320,7 +331,6 @@ export class Choices {
const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState); const hasActiveDropdown = this.dropdown.classList.contains(this.options.classNames.activeState);
let dropdownItem; let dropdownItem;
if(this.input.value) { if(this.input.value) {
const activeItems = this.store.getItemsFilteredByActive(); const activeItems = this.store.getItemsFilteredByActive();
const isUnique = !activeItems.some((item) => item.value === this.input.value); const isUnique = !activeItems.some((item) => item.value === this.input.value);
@ -344,26 +354,29 @@ export class Choices {
} }
} }
if(this.options.allowSearch) { // If we have enabled text search
if(this.canSearch) {
if(this.input === document.activeElement) { if(this.input === document.activeElement) {
const options = this.store.getOptions(); const options = this.store.getOptions();
const hasUnactiveOptions = options.some((option) => option.active !== true); const hasUnactiveOptions = options.some((option) => option.active !== true);
// Check that have a value to search // Check that we have a value to search and the input was an alphanumeric character
if(this.input.value && options.length) { if(this.input.value && options.length && /[a-zA-Z0-9-_ ]/.test(keyString)) {
const handleFilter = () => { const handleFilter = () => {
if(this.input.value.length >= 1) { const newValue = this.input.value.trim();
const haystack = this.store.getOptionsFiltedBySelectable(); const currentValue = this.currentValue.trim();
const needle = this.input.value;
if(newValue.length >= 1 && newValue !== currentValue + ' ') {
const haystack = this.store.getOptionsFiltedBySelectable();
const needle = newValue;
const fuse = new Fuse(haystack, { const fuse = new Fuse(haystack, {
keys: ['label', 'value'], keys: ['label', 'value'],
shouldSort: true, shouldSort: true,
include: 'score', include: 'score',
}); });
const results = fuse.search(needle); const results = fuse.search(needle);
this.currentValue = newValue;
this.highlightPosition = 0; this.highlightPosition = 0;
this.isSearching = true; this.isSearching = true;
this.store.dispatch(filterOptions(results)); this.store.dispatch(filterOptions(results));
@ -380,6 +393,11 @@ export class Choices {
} }
} }
/**
* Input event
* @param {Object} e Event
* @return
*/
onInput(e) { onInput(e) {
if(this.passedElement.type !== 'select-one') { if(this.passedElement.type !== 'select-one') {
this.input.style.width = getWidthOfInput(this.input); this.input.style.width = getWidthOfInput(this.input);
@ -890,6 +908,16 @@ export class Choices {
isActive ? this.hideDropdown() : this.showDropdown(); isActive ? this.hideDropdown() : this.showDropdown();
} }
/**
* Set value of input
* @return
*/
setValue(values) {
if(isType('Array', values)) {
console.log(values);
}
}
/** /**
* Disable * Disable
* @return {[type]} [description] * @return {[type]} [description]

View file

@ -166,7 +166,7 @@
items: ['josh@joshuajohnson.co.uk', { value: 'joe@bloggs.co.uk', label: 'Joe Bloggs' } ], items: ['josh@joshuajohnson.co.uk', { value: 'joe@bloggs.co.uk', label: 'Joe Bloggs' } ],
}); });
const choices7 = new Choices('#choices-7', { allowSearch: false }); const choices7 = new Choices('#choices-7', { allowSearch: false }).setValue(['Set value 1', 'Set value 2']);
const choicesAjax = new Choices('#choices-12').ajax((callback) => { const choicesAjax = new Choices('#choices-12').ajax((callback) => {
fetch('https://api.discogs.com/artists/391170/releases?token=QBRmstCkwXEvCjTclCpumbtNwvVkEzGAdELXyRyW') fetch('https://api.discogs.com/artists/391170/releases?token=QBRmstCkwXEvCjTclCpumbtNwvVkEzGAdELXyRyW')