Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * Collapse or expand all form sections on clicking the expand all / collapse al link.
18
 *
19
 * @module core_form/collapsesections
20
 * @copyright 2021 Bas Brands
21
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 * @since 4.0
23
 */
24
 
25
import $ from 'jquery';
26
import Pending from 'core/pending';
27
 
28
const SELECTORS = {
29
    FORM: '.mform',
30
    FORMHEADER: '.fheader',
31
    FORMCONTAINER: 'fieldset > .fcontainer',
32
};
33
 
34
const CLASSES = {
35
    SHOW: 'show',
36
    COLLAPSED: 'collapsed',
37
    HIDDEN: 'd-none'
38
};
39
 
40
/**
41
 * Initialises the form section collapse / expand action.
42
 *
43
 * @param {string} collapsesections the collapse/expand link id.
44
 */
45
export const init = collapsesections => {
46
    // All jQuery in this code can be replaced when MDL-71979 is integrated (move to Bootstrap 5).
47
    const pendingPromise = new Pending('core_form/collapsesections');
48
    const collapsemenu = document.querySelector(collapsesections);
49
 
50
    const formParent = collapsemenu.closest(SELECTORS.FORM);
51
    const formContainers = formParent.querySelectorAll(SELECTORS.FORMCONTAINER);
52
 
53
    collapsemenu.addEventListener('keydown', e => {
54
        if (e.key === 'Enter' || e.key === ' ') {
55
            e.preventDefault();
56
            collapsemenu.click();
57
        }
58
    });
59
 
60
    // Override default collapse class if all visible containers are expanded on page load
61
    let formcontainercount = 0;
62
    let expandedcount = 0;
63
    formContainers.forEach(container => {
64
        const parentFieldset = container.parentElement;
65
        if (!parentFieldset.classList.contains(CLASSES.HIDDEN)) {
66
            formcontainercount++;
67
        }
68
        if (container.classList.contains(CLASSES.SHOW)) {
69
            expandedcount++;
70
        }
71
    });
72
 
73
    if (formcontainercount === expandedcount) {
74
        collapsemenu.classList.remove(CLASSES.COLLAPSED);
75
        collapsemenu.setAttribute('aria-expanded', true);
76
    }
77
 
78
    // When the collapse menu is toggled, update each form container to match.
79
    collapsemenu.addEventListener('click', () => {
80
        let action = 'hide';
81
        if (collapsemenu.classList.contains(CLASSES.COLLAPSED)) {
82
            action = 'show';
83
        }
84
 
85
        formContainers.forEach(container => $(container).collapse(action));
86
    });
87
 
88
    // Ensure collapse menu button adds aria-controls attribute referring to each collapsible element.
89
    const collapseElements = formParent.querySelectorAll(SELECTORS.FORMHEADER);
90
    const collapseElementIds = [...collapseElements].map((element, index) => {
91
        element.id = element.id || `collapseElement-${index}`;
92
        return element.id;
93
    });
94
    collapsemenu.setAttribute('aria-controls', collapseElementIds.join(' '));
95
 
96
    // When any form container is toggled, re-calculate collapse menu state.
97
    $(SELECTORS.FORMCONTAINER).on('hidden.bs.collapse', () => {
98
        const allCollapsed = [...formContainers].every(container => !container.classList.contains(CLASSES.SHOW));
99
        if (allCollapsed) {
100
            collapsemenu.classList.add(CLASSES.COLLAPSED);
101
            collapsemenu.setAttribute('aria-expanded', false);
102
        }
103
    });
104
    $(SELECTORS.FORMCONTAINER).on('shown.bs.collapse', () => {
105
        const allExpanded = [...formContainers].every(container => container.classList.contains(CLASSES.SHOW));
106
        if (allExpanded) {
107
            collapsemenu.classList.remove(CLASSES.COLLAPSED);
108
            collapsemenu.setAttribute('aria-expanded', true);
109
        }
110
    });
111
    pendingPromise.resolve();
112
};