116 lines
3.4 KiB
JavaScript
116 lines
3.4 KiB
JavaScript
import { Utility } from '../../core/utility';
|
|
|
|
const INTERACTIVE_FIELDSET_UTIL_TARGET_SELECTOR = '.interactive-fieldset__target';
|
|
|
|
const INTERACTIVE_FIELDSET_INITIALIZED_CLASS = 'interactive-fieldset--initialized';
|
|
const INTERACTIVE_FIELDSET_CHILD_SELECTOR = 'input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled])';
|
|
|
|
@Utility({
|
|
selector: '[uw-interactive-fieldset]',
|
|
})
|
|
export class InteractiveFieldset {
|
|
|
|
_element;
|
|
|
|
conditionalInput;
|
|
conditionalValue;
|
|
target;
|
|
childInputs;
|
|
negated;
|
|
|
|
constructor(element) {
|
|
if (!element) {
|
|
throw new Error('Interactive Fieldset utility cannot be setup without an element!');
|
|
}
|
|
|
|
this._element = element;
|
|
|
|
if (this._element.classList.contains(INTERACTIVE_FIELDSET_INITIALIZED_CLASS)) {
|
|
return false;
|
|
}
|
|
|
|
if (this._element.querySelector('[uw-interactive-fieldset]')) {
|
|
return false;
|
|
}
|
|
|
|
// param conditionalInput
|
|
if (!this._element.dataset.conditionalInput) {
|
|
throw new Error('Interactive Fieldset needs a selector for a conditional input!');
|
|
}
|
|
this.conditionalInput = document.querySelector('#' + this._element.dataset.conditionalInput);
|
|
if (!this.conditionalInput) {
|
|
// abort if form has no required inputs
|
|
throw new Error('Couldn\'t find the conditional input. Aborting setup for interactive fieldset.');
|
|
}
|
|
|
|
// param conditionalValue
|
|
if (!('conditionalValue' in this._element.dataset) && !this._isCheckbox()) {
|
|
throw new Error('Interactive Fieldset needs a conditional value!');
|
|
}
|
|
this.conditionalValue = this._element.dataset.conditionalValue;
|
|
|
|
this.negated = 'conditionalNegated' in this._element.dataset;
|
|
|
|
this.target = this._element.closest(INTERACTIVE_FIELDSET_UTIL_TARGET_SELECTOR);
|
|
if (!this.target || this._element.matches(INTERACTIVE_FIELDSET_UTIL_TARGET_SELECTOR)) {
|
|
this.target = this._element;
|
|
}
|
|
|
|
this.childInputs = Array.from(this._element.querySelectorAll(INTERACTIVE_FIELDSET_CHILD_SELECTOR));
|
|
|
|
// add event listener
|
|
const observer = new MutationObserver(() => this._updateVisibility());
|
|
observer.observe(this.conditionalInput, { attributes: true, attributeFilter: ['data-interactive-fieldset-hidden'] });
|
|
this.conditionalInput.addEventListener('input', () => this._updateVisibility());
|
|
|
|
// initial visibility update
|
|
this._updateVisibility();
|
|
|
|
// mark as initialized
|
|
this._element.classList.add(INTERACTIVE_FIELDSET_INITIALIZED_CLASS);
|
|
|
|
}
|
|
|
|
destroy() {
|
|
// TODO
|
|
}
|
|
|
|
_updateVisibility() {
|
|
const active = this._matchesConditionalValue() && !this.conditionalInput.dataset.interactiveFieldsetHidden;
|
|
|
|
this.target.classList.toggle('hidden', !active);
|
|
|
|
this.childInputs.forEach((el) => this._updateChildVisibility(el, active));
|
|
}
|
|
|
|
_updateChildVisibility(el, active) {
|
|
el.disabled = !active;
|
|
|
|
if (active) {
|
|
delete el.dataset.interactiveFieldsetHidden;
|
|
} else {
|
|
el.dataset.interactiveFieldsetHidden = true;
|
|
}
|
|
}
|
|
|
|
_matchesConditionalValue() {
|
|
var matches;
|
|
|
|
if (this._isCheckbox()) {
|
|
matches = this.conditionalInput.checked === true;
|
|
} else {
|
|
matches = this.conditionalInput.value === this.conditionalValue;
|
|
}
|
|
|
|
if (this.negated) {
|
|
return !matches;
|
|
} else {
|
|
return matches;
|
|
}
|
|
}
|
|
|
|
_isCheckbox() {
|
|
return this.conditionalInput.getAttribute('type') === 'checkbox';
|
|
}
|
|
}
|