1
0
Files
breadcrumb-the-shire/web/js/core/app-conditional-controls.js
fs 31ecb40235 refactor: clean up web assets and consolidate PHP helpers
- Remove 2079 unused bootstrap-icons SVGs + min.css (~9.3 MB saved, app uses font approach only)
- Remove unused editorjs.umd.js (only .mjs is imported)
- Extract shared syncControlState into app-conditional-controls.js, deduplicate SSO/LDAP toggles
- Add settingToBool() helper to DRY up repeated bool-parsing pattern across 6 call sites
- Merge single-function auth.php into app.php, delete auth.php
- Extract 9 branding functions from app.php into dedicated branding.php (app.php 709→528 lines)
- Remove empty web/img/ directory

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 21:31:59 +02:00

91 lines
2.8 KiB
JavaScript

/**
* Shared utilities for conditional-controls toggles.
*
* Several components follow the same pattern: a checkbox enables/disables
* a block of form controls. This module centralises that logic so
* individual toggles (SSO, LDAP, …) only contain their domain-specific
* wiring.
*/
import { resolveHost } from './app-dom.js';
/**
* Show or hide a container and sync the disabled state of all nested
* form controls. Controls that were already disabled before the first
* toggle are kept disabled regardless of the toggle state.
*
* @param {Element|null} container
* @param {boolean} show
*/
export const syncControlState = (container, show) => {
if (!(container instanceof HTMLElement)) {
return;
}
container.hidden = !show;
container.querySelectorAll('input, select, textarea, button').forEach((control) => {
if ((control instanceof HTMLInputElement) && control.type === 'hidden') {
return;
}
if (!control.dataset.initialDisabled) {
control.dataset.initialDisabled = control.hasAttribute('disabled') ? '1' : '0';
}
if (!show) {
control.setAttribute('disabled', 'disabled');
return;
}
if (control.dataset.initialDisabled === '1') {
control.setAttribute('disabled', 'disabled');
return;
}
control.removeAttribute('disabled');
});
};
/**
* Create a reusable init function for conditional-controls toggles.
*
* The returned function matches the component-runtime signature
* `init(root, options) → { destroy }` so it can be registered directly.
*
* @param {object} config
* @param {string} config.rootSelector CSS selector for root elements
* @param {string} config.boundKey dataset key to track bound state (camelCase)
* @param {function} config.initRoot (rootElement) → cleanup function | null
* @returns {function} init(root, options) → { destroy }
*/
export const createConditionalToggleInit = (config) =>
function init(root = document, options = {}) {
const host = resolveHost(root);
const selector =
String(options.selector || config.rootSelector).trim() || config.rootSelector;
const roots = Array.from(host.querySelectorAll(selector));
if (!roots.length) {
return { destroy: () => {} };
}
const cleanupFns = [];
roots.forEach((item) => {
if (!(item instanceof HTMLElement) || item.dataset[config.boundKey] === '1') {
return;
}
item.dataset[config.boundKey] = '1';
const cleanup = config.initRoot(item);
if (typeof cleanup === 'function') {
cleanupFns.push(cleanup);
}
cleanupFns.push(() => {
delete item.dataset[config.boundKey];
});
});
const destroy = () => {
cleanupFns.forEach((cleanup) => cleanup());
};
return { destroy };
};