mirror of
https://github.com/Choices-js/Choices.git
synced 2024-06-16 12:45:10 +02:00
Seperate key methods into class methods
This commit is contained in:
parent
60d52a2d3b
commit
3319529b98
|
@ -143,6 +143,11 @@ class Choices {
|
||||||
this._onMouseDown = this._onMouseDown.bind(this);
|
this._onMouseDown = this._onMouseDown.bind(this);
|
||||||
this._onMouseOver = this._onMouseOver.bind(this);
|
this._onMouseOver = this._onMouseOver.bind(this);
|
||||||
this._onFormReset = this._onFormReset.bind(this);
|
this._onFormReset = this._onFormReset.bind(this);
|
||||||
|
this._onAKey = this._onAKey.bind(this);
|
||||||
|
this._onEnterKey = this._onEnterKey.bind(this);
|
||||||
|
this._onEscapeKey = this._onEscapeKey.bind(this);
|
||||||
|
this._onDirectionKey = this._onDirectionKey.bind(this);
|
||||||
|
this._onDeleteKey = this._onDeleteKey.bind(this);
|
||||||
|
|
||||||
// If element has already been initialised with Choices, fail silently
|
// If element has already been initialised with Choices, fail silently
|
||||||
if (this.passedElement.element.getAttribute('data-choice') === 'active') {
|
if (this.passedElement.element.getAttribute('data-choice') === 'active') {
|
||||||
|
@ -1096,168 +1101,50 @@ class Choices {
|
||||||
const hasActiveDropdown = this.dropdown.isActive;
|
const hasActiveDropdown = this.dropdown.isActive;
|
||||||
const hasItems = this.itemList.hasChildren;
|
const hasItems = this.itemList.hasChildren;
|
||||||
const keyString = String.fromCharCode(keyCode);
|
const keyString = String.fromCharCode(keyCode);
|
||||||
const backKey = KEY_CODES.BACK_KEY;
|
|
||||||
const deleteKey = KEY_CODES.DELETE_KEY;
|
const {
|
||||||
const enterKey = KEY_CODES.ENTER_KEY;
|
BACK_KEY,
|
||||||
const aKey = KEY_CODES.A_KEY;
|
DELETE_KEY,
|
||||||
const escapeKey = KEY_CODES.ESC_KEY;
|
ENTER_KEY,
|
||||||
const upKey = KEY_CODES.UP_KEY;
|
A_KEY,
|
||||||
const downKey = KEY_CODES.DOWN_KEY;
|
ESC_KEY,
|
||||||
const pageUpKey = KEY_CODES.PAGE_UP_KEY;
|
UP_KEY,
|
||||||
const pageDownKey = KEY_CODES.PAGE_DOWN_KEY;
|
DOWN_KEY,
|
||||||
const ctrlDownKey = ctrlKey || metaKey;
|
PAGE_UP_KEY,
|
||||||
|
PAGE_DOWN_KEY,
|
||||||
|
} = KEY_CODES;
|
||||||
|
const hasCtrlDownKeyPressed = ctrlKey || 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();
|
this.showDropdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
const onAKey = () => {
|
|
||||||
// If CTRL + A or CMD + A have been pressed and there are items to select
|
|
||||||
if (ctrlDownKey && hasItems) {
|
|
||||||
this._canSearch = false;
|
|
||||||
if (
|
|
||||||
this.config.removeItems &&
|
|
||||||
!this.input.value &&
|
|
||||||
this.input.element === document.activeElement
|
|
||||||
) {
|
|
||||||
// Highlight items
|
|
||||||
this.highlightAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEnterKey = () => {
|
|
||||||
// If enter key is pressed and the input has a value
|
|
||||||
if (this._isTextElement && target.value) {
|
|
||||||
const value = this.input.value;
|
|
||||||
const canAddItem = this._canAddItem(activeItems, value);
|
|
||||||
|
|
||||||
// All is good, add
|
|
||||||
if (canAddItem.response) {
|
|
||||||
this.hideDropdown(true);
|
|
||||||
this._addItem({ value });
|
|
||||||
this._triggerChange(value);
|
|
||||||
this.clearInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.hasAttribute('data-button')) {
|
|
||||||
this._handleButtonAction(activeItems, target);
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasActiveDropdown) {
|
|
||||||
event.preventDefault();
|
|
||||||
const highlighted = this.dropdown.getChild(
|
|
||||||
`.${this.config.classNames.highlightedState}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// If we have a highlighted choice
|
|
||||||
if (highlighted) {
|
|
||||||
// add enter keyCode value
|
|
||||||
if (activeItems[0]) {
|
|
||||||
activeItems[0].keyCode = enterKey;
|
|
||||||
}
|
|
||||||
this._handleChoiceAction(activeItems, highlighted);
|
|
||||||
}
|
|
||||||
} else if (this._isSelectOneElement) {
|
|
||||||
// Open single select dropdown if it's not active
|
|
||||||
this.showDropdown();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEscapeKey = () => {
|
|
||||||
if (hasActiveDropdown) {
|
|
||||||
this.hideDropdown(true);
|
|
||||||
this.containerOuter.focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDirectionKey = () => {
|
|
||||||
// If up or down key is pressed, traverse through options
|
|
||||||
if (hasActiveDropdown || this._isSelectOneElement) {
|
|
||||||
this.showDropdown();
|
|
||||||
this._canSearch = false;
|
|
||||||
|
|
||||||
const directionInt =
|
|
||||||
keyCode === downKey || keyCode === pageDownKey ? 1 : -1;
|
|
||||||
const skipKey =
|
|
||||||
metaKey || keyCode === pageDownKey || keyCode === pageUpKey;
|
|
||||||
const selectableChoiceIdentifier = '[data-choice-selectable]';
|
|
||||||
|
|
||||||
let nextEl;
|
|
||||||
if (skipKey) {
|
|
||||||
if (directionInt > 0) {
|
|
||||||
nextEl = Array.from(
|
|
||||||
this.dropdown.element.querySelectorAll(
|
|
||||||
selectableChoiceIdentifier,
|
|
||||||
),
|
|
||||||
).pop();
|
|
||||||
} else {
|
|
||||||
nextEl = this.dropdown.element.querySelector(
|
|
||||||
selectableChoiceIdentifier,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const currentEl = this.dropdown.element.querySelector(
|
|
||||||
`.${this.config.classNames.highlightedState}`,
|
|
||||||
);
|
|
||||||
if (currentEl) {
|
|
||||||
nextEl = getAdjacentEl(
|
|
||||||
currentEl,
|
|
||||||
selectableChoiceIdentifier,
|
|
||||||
directionInt,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
nextEl = this.dropdown.element.querySelector(
|
|
||||||
selectableChoiceIdentifier,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextEl) {
|
|
||||||
// We prevent default to stop the cursor moving
|
|
||||||
// when pressing the arrow
|
|
||||||
if (
|
|
||||||
!isScrolledIntoView(nextEl, this.choiceList.element, directionInt)
|
|
||||||
) {
|
|
||||||
this.choiceList.scrollToChoice(nextEl, directionInt);
|
|
||||||
}
|
|
||||||
this._highlightChoice(nextEl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent default to maintain cursor position whilst
|
|
||||||
// traversing dropdown options
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteKey = () => {
|
|
||||||
// If backspace or delete key is pressed and the input has no value
|
|
||||||
if (hasFocusedInput && !target.value && !this._isSelectOneElement) {
|
|
||||||
this._handleBackspace(activeItems);
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Map keys to key actions
|
// Map keys to key actions
|
||||||
const keyDownActions = {
|
const keyDownActions = {
|
||||||
[aKey]: onAKey,
|
[A_KEY]: this._onAKey,
|
||||||
[enterKey]: onEnterKey,
|
[ENTER_KEY]: this._onEnterKey,
|
||||||
[escapeKey]: onEscapeKey,
|
[ESC_KEY]: this._onEscapeKey,
|
||||||
[upKey]: onDirectionKey,
|
[UP_KEY]: this._onDirectionKey,
|
||||||
[pageUpKey]: onDirectionKey,
|
[PAGE_UP_KEY]: this._onDirectionKey,
|
||||||
[downKey]: onDirectionKey,
|
[DOWN_KEY]: this._onDirectionKey,
|
||||||
[pageDownKey]: onDirectionKey,
|
[PAGE_DOWN_KEY]: this._onDirectionKey,
|
||||||
[deleteKey]: onDeleteKey,
|
[DELETE_KEY]: this._onDeleteKey,
|
||||||
[backKey]: onDeleteKey,
|
[BACK_KEY]: this._onDeleteKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
// If keycode has a function, run it
|
// If keycode has a function, run it
|
||||||
if (keyDownActions[keyCode]) {
|
if (keyDownActions[keyCode]) {
|
||||||
keyDownActions[keyCode]();
|
keyDownActions[keyCode]({
|
||||||
|
target,
|
||||||
|
keyCode,
|
||||||
|
metaKey,
|
||||||
|
activeItems,
|
||||||
|
hasFocusedInput,
|
||||||
|
hasActiveDropdown,
|
||||||
|
hasItems,
|
||||||
|
hasCtrlDownKeyPressed,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1305,6 +1192,141 @@ class Choices {
|
||||||
this._canSearch = this.config.searchEnabled;
|
this._canSearch = this.config.searchEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onAKey({ hasItems, hasCtrlDownKeyPressed }) {
|
||||||
|
// If CTRL + A or CMD + A have been pressed and there are items to select
|
||||||
|
if (hasCtrlDownKeyPressed && hasItems) {
|
||||||
|
this._canSearch = false;
|
||||||
|
if (
|
||||||
|
this.config.removeItems &&
|
||||||
|
!this.input.value &&
|
||||||
|
this.input.element === document.activeElement
|
||||||
|
) {
|
||||||
|
// Highlight items
|
||||||
|
this.highlightAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onEnterKey({ target, activeItems, hasActiveDropdown }) {
|
||||||
|
const { ENTER_KEY: enterKey } = KEY_CODES;
|
||||||
|
// If enter key is pressed and the input has a value
|
||||||
|
if (this._isTextElement && target.value) {
|
||||||
|
const value = this.input.value;
|
||||||
|
const canAddItem = this._canAddItem(activeItems, value);
|
||||||
|
|
||||||
|
// All is good, add
|
||||||
|
if (canAddItem.response) {
|
||||||
|
this.hideDropdown(true);
|
||||||
|
this._addItem({ value });
|
||||||
|
this._triggerChange(value);
|
||||||
|
this.clearInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.hasAttribute('data-button')) {
|
||||||
|
this._handleButtonAction(activeItems, target);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasActiveDropdown) {
|
||||||
|
event.preventDefault();
|
||||||
|
const highlighted = this.dropdown.getChild(
|
||||||
|
`.${this.config.classNames.highlightedState}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// If we have a highlighted choice
|
||||||
|
if (highlighted) {
|
||||||
|
// add enter keyCode value
|
||||||
|
if (activeItems[0]) {
|
||||||
|
activeItems[0].keyCode = enterKey; // eslint-disable-line no-param-reassign
|
||||||
|
}
|
||||||
|
this._handleChoiceAction(activeItems, highlighted);
|
||||||
|
}
|
||||||
|
} else if (this._isSelectOneElement) {
|
||||||
|
// Open single select dropdown if it's not active
|
||||||
|
this.showDropdown();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onEscapeKey({ hasActiveDropdown }) {
|
||||||
|
if (hasActiveDropdown) {
|
||||||
|
this.hideDropdown(true);
|
||||||
|
this.containerOuter.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onDirectionKey({ hasActiveDropdown, keyCode, metaKey }) {
|
||||||
|
const {
|
||||||
|
DOWN_KEY: downKey,
|
||||||
|
PAGE_UP_KEY: pageUpKey,
|
||||||
|
PAGE_DOWN_KEY: pageDownKey,
|
||||||
|
} = KEY_CODES;
|
||||||
|
|
||||||
|
// If up or down key is pressed, traverse through options
|
||||||
|
if (hasActiveDropdown || this._isSelectOneElement) {
|
||||||
|
this.showDropdown();
|
||||||
|
this._canSearch = false;
|
||||||
|
|
||||||
|
const directionInt =
|
||||||
|
keyCode === downKey || keyCode === pageDownKey ? 1 : -1;
|
||||||
|
const skipKey =
|
||||||
|
metaKey || keyCode === pageDownKey || keyCode === pageUpKey;
|
||||||
|
const selectableChoiceIdentifier = '[data-choice-selectable]';
|
||||||
|
|
||||||
|
let nextEl;
|
||||||
|
if (skipKey) {
|
||||||
|
if (directionInt > 0) {
|
||||||
|
nextEl = Array.from(
|
||||||
|
this.dropdown.element.querySelectorAll(selectableChoiceIdentifier),
|
||||||
|
).pop();
|
||||||
|
} else {
|
||||||
|
nextEl = this.dropdown.element.querySelector(
|
||||||
|
selectableChoiceIdentifier,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const currentEl = this.dropdown.element.querySelector(
|
||||||
|
`.${this.config.classNames.highlightedState}`,
|
||||||
|
);
|
||||||
|
if (currentEl) {
|
||||||
|
nextEl = getAdjacentEl(
|
||||||
|
currentEl,
|
||||||
|
selectableChoiceIdentifier,
|
||||||
|
directionInt,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
nextEl = this.dropdown.element.querySelector(
|
||||||
|
selectableChoiceIdentifier,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextEl) {
|
||||||
|
// We prevent default to stop the cursor moving
|
||||||
|
// when pressing the arrow
|
||||||
|
if (
|
||||||
|
!isScrolledIntoView(nextEl, this.choiceList.element, directionInt)
|
||||||
|
) {
|
||||||
|
this.choiceList.scrollToChoice(nextEl, directionInt);
|
||||||
|
}
|
||||||
|
this._highlightChoice(nextEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent default to maintain cursor position whilst
|
||||||
|
// traversing dropdown options
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onDeleteKey({ target, hasFocusedInput, activeItems }) {
|
||||||
|
// If backspace or delete key is pressed and the input has no value
|
||||||
|
if (hasFocusedInput && !target.value && !this._isSelectOneElement) {
|
||||||
|
this._handleBackspace(activeItems);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_onTouchMove() {
|
_onTouchMove() {
|
||||||
if (this._wasTap === true) {
|
if (this._wasTap === true) {
|
||||||
this._wasTap = false;
|
this._wasTap = false;
|
||||||
|
|
Loading…
Reference in a new issue