88 lines
2.9 KiB
JavaScript
88 lines
2.9 KiB
JavaScript
import { LionFieldset } from '@lion/fieldset';
|
|
|
|
export class LionCheckboxGroup extends LionFieldset {
|
|
constructor() {
|
|
super();
|
|
this._checkboxGroupTouched = false;
|
|
this._setTouchedAndPrefilled = this._setTouchedAndPrefilled.bind(this);
|
|
this._checkForOutsideClick = this._checkForOutsideClick.bind(this);
|
|
this._checkForChildrenClick = this._checkForChildrenClick.bind(this);
|
|
}
|
|
|
|
connectedCallback() {
|
|
super.connectedCallback();
|
|
// We listen for focusin(instead of foxus), because it bubbles and gives the right event order
|
|
window.addEventListener('focusin', this._setTouchedAndPrefilled);
|
|
|
|
document.addEventListener('click', this._checkForOutsideClick);
|
|
this.addEventListener('click', this._checkForChildrenClick);
|
|
|
|
// checks for any of the children to be prefilled
|
|
this._checkboxGroupPrefilled = super.prefilled;
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
super.disconnectedCallback();
|
|
window.removeEventListener('focusin', this._setTouchedAndPrefilled);
|
|
document.removeEventListener('click', this._checkForOutsideClick);
|
|
this.removeEventListener('click', this._checkForChildrenClick);
|
|
}
|
|
|
|
get touched() {
|
|
return this._checkboxGroupTouched;
|
|
}
|
|
|
|
/**
|
|
* Leave event will be fired when previous document.activeElement
|
|
* is inside group and current document.activeElement is outside.
|
|
*/
|
|
_setTouchedAndPrefilled() {
|
|
const groupHasFocus = this.focused;
|
|
if (this.__groupHadFocus && !groupHasFocus) {
|
|
this._checkboxGroupTouched = true;
|
|
this._checkboxGroupPrefilled = super.prefilled; // right time to reconsider prefilled
|
|
this.__checkboxGroupPrefilledHasBeenSet = true;
|
|
}
|
|
this.__groupHadFocus = groupHasFocus;
|
|
}
|
|
|
|
_checkForOutsideClick(event) {
|
|
const outsideGroupClicked = !this.contains(event.target);
|
|
if (outsideGroupClicked) {
|
|
this._setTouchedAndPrefilled();
|
|
}
|
|
}
|
|
|
|
// Whenever a user clicks a checkbox, error messages should become visible
|
|
_checkForChildrenClick(event) {
|
|
const childClicked = this._childArray.some(c => c === event.target || c.contains(event.target));
|
|
if (childClicked) {
|
|
this._checkboxGroupTouched = true;
|
|
}
|
|
}
|
|
|
|
get _childArray() {
|
|
// We assume here that the fieldset has one set of checkboxes/radios that are grouped via attr
|
|
// name="groupName[]"
|
|
const arrayKey = Object.keys(this.formElements).filter(k => k.substr(-2) === '[]')[0];
|
|
return this.formElements[arrayKey] || [];
|
|
}
|
|
|
|
// eslint-disable-next-line class-methods-use-this
|
|
__isRequired(modelValues) {
|
|
const keys = Object.keys(modelValues);
|
|
for (let i = 0; i < keys.length; i += 1) {
|
|
const modelValue = modelValues[keys[i]];
|
|
if (Array.isArray(modelValue)) {
|
|
// grouped via myName[]
|
|
return {
|
|
required: modelValue.some(node => node.checked),
|
|
};
|
|
}
|
|
return {
|
|
required: modelValue.checked,
|
|
};
|
|
}
|
|
return { required: false };
|
|
}
|
|
}
|