MDL-78707 forms: improve form container collapsing mechanism.

By using a more explicit selector for matching containers we avoid
previous problems such as incorrect count, and collapsing of elements
that had the same class name.
This commit is contained in:
Paul Holden 2023-07-14 18:25:31 +01:00
parent e998f14061
commit 0d4d8f8a8c
No known key found for this signature in database
GPG Key ID: A81A96D6045F6164
4 changed files with 16 additions and 31 deletions

View File

@ -6,6 +6,6 @@ define("core_form/collapsesections",["exports","jquery","core/pending"],(functio
* @copyright 2021 Bas Brands
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_pending=_interopRequireDefault(_pending);const SELECTORS_FORMHEADER=".fheader",SELECTORS_FORMCONTAINER=".fcontainer",SELECTORS_FIELDSET="fieldset",CLASSES_SHOW="show",CLASSES_COLLAPSED="collapsed",CLASSES_HIDDEN="d-none";_exports.init=collapsesections=>{const pendingPromise=new _pending.default("core_form/collapsesections"),collapsemenu=document.querySelector(collapsesections),formParent=collapsemenu.closest("form");collapsemenu.addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),collapsemenu.click())}));let formcontainercount=0;(0,_jquery.default)(SELECTORS_FORMCONTAINER).each(((_,container)=>{const parentFieldset=container.closest(SELECTORS_FIELDSET);parentFieldset!=container.parentElement||parentFieldset.classList.contains(CLASSES_HIDDEN)||formcontainercount++}));let expandedcount=0;(0,_jquery.default)(SELECTORS_FORMCONTAINER).each(((_,collapsecontainer)=>{collapsecontainer.classList.contains(CLASSES_SHOW)&&expandedcount++})),formcontainercount===expandedcount&&(collapsemenu.classList.remove(CLASSES_COLLAPSED),collapsemenu.setAttribute("aria-expanded",!0)),collapsemenu.addEventListener("click",(()=>{let action="hide";collapsemenu.classList.contains(CLASSES_COLLAPSED)&&(action="show"),formParent.querySelectorAll(SELECTORS_FORMCONTAINER).forEach((collapsecontainer=>{(0,_jquery.default)(collapsecontainer).collapse(action)}))}));const collapseElementIds=[...(0,_jquery.default)(SELECTORS_FORMHEADER)].map(((element,index)=>(element.id=element.id||"collapseElement-".concat(index),element.id)));collapsemenu.setAttribute("aria-controls",collapseElementIds.join(" ")),(0,_jquery.default)(SELECTORS_FORMCONTAINER).on("hidden.bs.collapse",(()=>{let allCollapsed=!0;formParent.querySelectorAll(SELECTORS_FORMCONTAINER).forEach((collapsecontainer=>{collapsecontainer.classList.contains(CLASSES_SHOW)&&(allCollapsed=!1)})),allCollapsed&&(collapsemenu.classList.add(CLASSES_COLLAPSED),collapsemenu.setAttribute("aria-expanded",!1))})),(0,_jquery.default)(SELECTORS_FORMCONTAINER).on("shown.bs.collapse",(()=>{let allExpanded=!0;formParent.querySelectorAll(SELECTORS_FORMCONTAINER).forEach((collapsecontainer=>{collapsecontainer.classList.contains(CLASSES_SHOW)||(allExpanded=!1)})),allExpanded&&(collapsemenu.classList.remove(CLASSES_COLLAPSED),collapsemenu.setAttribute("aria-expanded",!0))})),pendingPromise.resolve()}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_pending=_interopRequireDefault(_pending);const SELECTORS_FORMHEADER=".fheader",SELECTORS_FORMCONTAINER="fieldset > .fcontainer",CLASSES_SHOW="show",CLASSES_COLLAPSED="collapsed",CLASSES_HIDDEN="d-none";_exports.init=collapsesections=>{const pendingPromise=new _pending.default("core_form/collapsesections"),collapsemenu=document.querySelector(collapsesections),formParent=collapsemenu.closest("form"),formContainers=(null==formParent?void 0:formParent.querySelectorAll(SELECTORS_FORMCONTAINER))||[];collapsemenu.addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),collapsemenu.click())}));let formcontainercount=0,expandedcount=0;formContainers.forEach((container=>{container.parentElement.classList.contains(CLASSES_HIDDEN)||formcontainercount++,container.classList.contains(CLASSES_SHOW)&&expandedcount++})),formcontainercount===expandedcount&&(collapsemenu.classList.remove(CLASSES_COLLAPSED),collapsemenu.setAttribute("aria-expanded",!0)),collapsemenu.addEventListener("click",(()=>{let action="hide";collapsemenu.classList.contains(CLASSES_COLLAPSED)&&(action="show"),formContainers.forEach((container=>(0,_jquery.default)(container).collapse(action)))}));const collapseElementIds=[...(0,_jquery.default)(SELECTORS_FORMHEADER)].map(((element,index)=>(element.id=element.id||"collapseElement-".concat(index),element.id)));collapsemenu.setAttribute("aria-controls",collapseElementIds.join(" ")),(0,_jquery.default)(SELECTORS_FORMCONTAINER).on("hidden.bs.collapse",(()=>{[...formContainers].every((container=>!container.classList.contains(CLASSES_SHOW)))&&(collapsemenu.classList.add(CLASSES_COLLAPSED),collapsemenu.setAttribute("aria-expanded",!1))})),(0,_jquery.default)(SELECTORS_FORMCONTAINER).on("shown.bs.collapse",(()=>{[...formContainers].every((container=>container.classList.contains(CLASSES_SHOW)))&&(collapsemenu.classList.remove(CLASSES_COLLAPSED),collapsemenu.setAttribute("aria-expanded",!0))})),pendingPromise.resolve()}}));
//# sourceMappingURL=collapsesections.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -27,8 +27,7 @@ import Pending from 'core/pending';
const SELECTORS = {
FORMHEADER: '.fheader',
FORMCONTAINER: '.fcontainer',
FIELDSET: 'fieldset',
FORMCONTAINER: 'fieldset > .fcontainer',
};
const CLASSES = {
@ -47,6 +46,8 @@ export const init = collapsesections => {
const pendingPromise = new Pending('core_form/collapsesections');
const collapsemenu = document.querySelector(collapsesections);
const formParent = collapsemenu.closest('form');
const formContainers = formParent?.querySelectorAll(SELECTORS.FORMCONTAINER) || [];
collapsemenu.addEventListener('keydown', e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
@ -56,15 +57,13 @@ export const init = collapsesections => {
// Override default collapse class if all visible containers are expanded on page load
let formcontainercount = 0;
$(SELECTORS.FORMCONTAINER).each((_, container) => {
const parentFieldset = container.closest(SELECTORS.FIELDSET);
if (parentFieldset == container.parentElement && !parentFieldset.classList.contains(CLASSES.HIDDEN)) {
let expandedcount = 0;
formContainers.forEach(container => {
const parentFieldset = container.parentElement;
if (!parentFieldset.classList.contains(CLASSES.HIDDEN)) {
formcontainercount++;
}
});
let expandedcount = 0;
$(SELECTORS.FORMCONTAINER).each((_, collapsecontainer) => {
if (collapsecontainer.classList.contains(CLASSES.SHOW)) {
if (container.classList.contains(CLASSES.SHOW)) {
expandedcount++;
}
});
@ -74,15 +73,14 @@ export const init = collapsesections => {
collapsemenu.setAttribute('aria-expanded', true);
}
// When the collapse menu is toggled, update each form container to match.
collapsemenu.addEventListener('click', () => {
let action = 'hide';
if (collapsemenu.classList.contains(CLASSES.COLLAPSED)) {
action = 'show';
}
formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {
$(collapsecontainer).collapse(action);
});
formContainers.forEach(container => $(container).collapse(action));
});
// Ensure collapse menu button adds aria-controls attribute referring to each collapsible element.
@ -93,29 +91,16 @@ export const init = collapsesections => {
});
collapsemenu.setAttribute('aria-controls', collapseElementIds.join(' '));
// When any form container is toggled, re-calculate collapse menu state.
$(SELECTORS.FORMCONTAINER).on('hidden.bs.collapse', () => {
let allCollapsed = true;
formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {
if (collapsecontainer.classList.contains(CLASSES.SHOW)) {
allCollapsed = false;
}
});
const allCollapsed = [...formContainers].every(container => !container.classList.contains(CLASSES.SHOW));
if (allCollapsed) {
collapsemenu.classList.add(CLASSES.COLLAPSED);
collapsemenu.setAttribute('aria-expanded', false);
}
});
$(SELECTORS.FORMCONTAINER).on('shown.bs.collapse', () => {
let allExpanded = true;
formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {
if (!collapsecontainer.classList.contains(CLASSES.SHOW)) {
allExpanded = false;
}
});
const allExpanded = [...formContainers].every(container => container.classList.contains(CLASSES.SHOW));
if (allExpanded) {
collapsemenu.classList.remove(CLASSES.COLLAPSED);
collapsemenu.setAttribute('aria-expanded', true);

View File

@ -1,4 +1,4 @@
@core
@core @core_form
Feature: Read-only forms should work
In order to use certain forms on large Moodle installations
As a user