Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIO-8548: Update choices.js to 11 version #5976

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"homepage": "https://github.com/formio/formio.js#readme",
"dependencies": {
"@formio/bootstrap": "v3.0.0-dev.121.085d187",
"@formio/choices.js": "^10.2.1",
"@formio/choices.js": "11.0.3-rc.1",
"@formio/core": "v2.4.0-dev.2",
"@formio/text-mask-addons": "3.8.0-formio.4",
"@formio/vanilla-text-mask": "^5.1.1-formio.1",
Expand Down
27 changes: 2 additions & 25 deletions src/components/select/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -905,8 +905,8 @@ export default class SelectComponent extends ListComponent {
removeItemButton: this.component.disabled ? false : _.get(this.component, 'removeItemButton', true),
itemSelectText: '',
classNames: {
containerOuter: 'choices form-group formio-choices',
containerInner: this.transform('class', 'form-control ui fluid selection dropdown')
containerOuter: ['choices', 'form-group', 'formio-choices'],
containerInner: this.transform('class', 'form-control ui fluid selection dropdown').split(' '),
},
addItemText: false,
allowHTML: true,
Expand Down Expand Up @@ -1097,14 +1097,6 @@ export default class SelectComponent extends ListComponent {
});
}

if (this.choices && choicesOptions.placeholderValue && this.choices._isSelectOneElement) {
this.addPlaceholderItem(choicesOptions.placeholderValue);

this.addEventListener(input, 'removeItem', () => {
this.addPlaceholderItem(choicesOptions.placeholderValue);
});
}

// Add value options.
this.addValueOptions();
this.setChoicesValue(this.dataValue);
Expand Down Expand Up @@ -1208,21 +1200,6 @@ export default class SelectComponent extends ListComponent {
}
}

addPlaceholderItem(placeholderValue) {
const items = this.choices._store.activeItems;
if (!items.length) {
this.choices._addItem({
value: '',
label: placeholderValue,
choiceId: 0,
groupId: -1,
customProperties: null,
placeholder: true,
keyCode: null
});
}
}

/* eslint-enable max-statements */
update() {
if (this.component.dataSrc === 'custom') {
Expand Down
2 changes: 1 addition & 1 deletion src/components/tags/Tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export default class TagsComponent extends Input {
const changed = super.setValue(value, flags);
if (this.choices) {
let dataValue = this.dataValue;
this.choices.removeActiveItems();
this.choices.clearStore();
if (dataValue) {
if (typeof dataValue === 'string') {
dataValue = dataValue.split(this.delimiter).filter(result => result);
Expand Down
178 changes: 26 additions & 152 deletions src/utils/ChoicesWrapper.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,8 @@
import Choices from '@formio/choices.js';

/**
* TODO: REMOVE THIS ONCE THE PULL REQUEST HAS BEEN RESOLVED.
*
* https://github.com/jshjohnson/Choices/pull/788
*
* This is intentionally not part of the extended class, since other components use Choices and need this fix as well.
* @type {Choices._generatePlaceholderValue}
* @private
*/
Choices.prototype._generatePlaceholderValue = function() {
if (this._isSelectElement && this.passedElement.placeholderOption) {
const { placeholderOption } = this.passedElement;
return placeholderOption ? placeholderOption.text : false;
}
const { placeholder, placeholderValue } = this.config;
const {
element: { dataset },
} = this.passedElement;

if (placeholder) {
if (placeholderValue) {
return placeholderValue;
}

if (dataset.placeholder) {
return dataset.placeholder;
}
}
import Choices, { KeyCodeMap } from '@formio/choices.js';

return false;
};

export const KEY_CODES = {
BACK_KEY: 46,
DELETE_KEY: 8,
const ExtendedKeyCodeMap = {
...KeyCodeMap,
TAB_KEY: 9,
ENTER_KEY: 13,
A_KEY: 65,
ESC_KEY: 27,
UP_KEY: 38,
DOWN_KEY: 40,
PAGE_UP_KEY: 33,
PAGE_DOWN_KEY: 34,
};

class ChoicesWrapper extends Choices {
Expand Down Expand Up @@ -74,29 +34,13 @@ class ChoicesWrapper extends Choices {
this._wasTap = true;
}

_handleButtonAction(activeItems, element) {
if (!this._isSelectOneElement) {
return super._handleButtonAction(activeItems, element);
}

if (
!activeItems ||
!element ||
!this.config.removeItems ||
!this.config.removeItemButton
) {
return;
}

super._handleButtonAction(activeItems, element);
}

_onEnterKey(args) {
_onEnterKey(...args) {
const [event] = args;
// Prevent dropdown form opening when removeItemButton was pressed using 'Enter' on keyboard
if (args.event.target.className === 'choices__button') {
if (event.target.className === 'choices__button') {
this.shouldOpenDropDown = false;
}
super._onEnterKey(args);
super._onEnterKey(...args);
}

_onDirectionKey(...args) {
Expand All @@ -116,21 +60,22 @@ class ChoicesWrapper extends Choices {
}, 250);
}

_onTabKey({ activeItems, hasActiveDropdown }) {
if (hasActiveDropdown) {
this._selectHighlightedChoice(activeItems);
_onTabKey() {
if (this.dropdown.isActive) {
this._selectHighlightedChoice();
}
}

_selectHighlightedChoice() {
const highlightedChoice = this.dropdown.getChild(
const highlightedChoice = this.dropdown.element.querySelector(
`.${this.config.classNames.highlightedState}`,
);

if (highlightedChoice) {
const id = highlightedChoice.dataset.id;
const choice = id && this._store.getChoiceById(id);
const choice = id && this._store.getChoiceById(Number(id));
this._addItem({
id: choice.id,
value: choice.value,
label: choice.label,
choiceId: choice.id,
Expand All @@ -141,84 +86,18 @@ class ChoicesWrapper extends Choices {
});
this._triggerChange(choice.value);
}

event.preventDefault();
}

_onKeyDown(event) {
if (!this._isSelectOneElement) {
return super._onKeyDown(event);
}

const { target, keyCode, ctrlKey, metaKey } = event;

if (
target !== this.input.element &&
!this.containerOuter.element.contains(target)
) {
return;
}

const activeItems = this._store.activeItems;
const hasFocusedInput = this.input.isFocussed;
const hasActiveDropdown = this.dropdown.isActive;
const hasItems = this.itemList.hasChildren;
const keyString = String.fromCharCode(keyCode);

const {
BACK_KEY,
DELETE_KEY,
TAB_KEY,
ENTER_KEY,
A_KEY,
ESC_KEY,
UP_KEY,
DOWN_KEY,
PAGE_UP_KEY,
PAGE_DOWN_KEY,
} = KEY_CODES;
const hasCtrlDownKeyPressed = ctrlKey || metaKey;

// If a user is typing and the dropdown is not active
if (!hasActiveDropdown && !this._isTextElement && /[a-zA-Z0-9-_ ]/.test(keyString)) {
const currentValue = this.input.element.value;
this.input.element.value = currentValue ? `${currentValue}${keyString}` : keyString;
this.showDropdown();
}

// Map keys to key actions
const keyDownActions = {
[A_KEY]: this._onAKey,
[TAB_KEY]: this._onTabKey,
[ENTER_KEY]: this._onEnterKey,
[ESC_KEY]: this._onEscapeKey,
[UP_KEY]: this._onDirectionKey,
[PAGE_UP_KEY]: this._onDirectionKey,
[DOWN_KEY]: this._onDirectionKey,
[PAGE_DOWN_KEY]: this._onDirectionKey,
[DELETE_KEY]: this._onDeleteKey,
[BACK_KEY]: this._onDeleteKey,
};

// If keycode has a function, run it
if (keyDownActions[keyCode]) {
keyDownActions[keyCode]({
event,
target,
keyCode,
metaKey,
activeItems,
hasFocusedInput,
hasActiveDropdown,
hasItems,
hasCtrlDownKeyPressed,
});
}
const keyCode = event.keyCode;
return this._isSelectOneElement && keyCode === ExtendedKeyCodeMap.TAB_KEY
? this._onTabKey()
: super._onKeyDown(event);
}

onSelectValue({ event, activeItems, hasActiveDropdown }) {
onSelectValue(event, hasActiveDropdown) {
if (hasActiveDropdown) {
this._selectHighlightedChoice(activeItems);
this._selectHighlightedChoice();
}
else if (this._isSelectOneElement) {
this.showDropdown();
Expand All @@ -227,12 +106,14 @@ class ChoicesWrapper extends Choices {
}

showDropdown(...args) {
if (!this.shouldOpenDropDown) {
this.shouldOpenDropDown = true;
return;
}
setTimeout(() => {
if (!this.shouldOpenDropDown) {
this.shouldOpenDropDown = true;
return;
}

super.showDropdown(...args);
super.showDropdown(...args);
}, 0);
}

hideDropdown(...args) {
Expand All @@ -242,13 +123,6 @@ class ChoicesWrapper extends Choices {

super.hideDropdown(...args);
}

_onBlur(...args) {
if (this._isScrollingOnIe) {
return;
}
super._onBlur(...args);
}
}

export default ChoicesWrapper;
2 changes: 0 additions & 2 deletions test/unit/Radio.unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,7 @@ describe('Radio Component', () => {
}, 350);
}).catch(done);
});
});

describe('Radio Component', () => {
it('should have red asterisk left hand side to the options labels if component is required and label is hidden', () => {
return Harness.testCreate(RadioComponent, comp7).then(component => {
const options = component.element.querySelectorAll('.form-check-label');
Expand Down
Loading
Loading