From 290e6f4c6f54490d8b07bfa748df246c5a8094dc Mon Sep 17 00:00:00 2001 From: Amaia Anabitarte Date: Tue, 13 Jun 2023 12:00:54 +0200 Subject: [PATCH] MDL-78288 core_course: Adding filter_shown_headers option to forms --- course/editsection.php | 18 ++- course/editsection_form.php | 27 ++-- course/modedit.php | 10 ++ course/moodleform_mod.php | 3 + lib/form/amd/build/collapsesections.min.js | 2 +- .../amd/build/collapsesections.min.js.map | 2 +- lib/form/amd/src/collapsesections.js | 13 +- lib/formslib.php | 124 +++++++++++++++++- lib/upgrade.txt | 1 + 9 files changed, 177 insertions(+), 23 deletions(-) diff --git a/course/editsection.php b/course/editsection.php index 04ece14bf12..e5d10f0d1c9 100644 --- a/course/editsection.php +++ b/course/editsection.php @@ -30,8 +30,13 @@ require_once($CFG->libdir . '/formslib.php'); $id = required_param('id', PARAM_INT); // course_sections.id $sectionreturn = optional_param('sr', 0, PARAM_INT); $deletesection = optional_param('delete', 0, PARAM_BOOL); +$showonly = optional_param('showonly', 0, PARAM_TAGLIST); -$PAGE->set_url('/course/editsection.php', array('id'=>$id, 'sr'=> $sectionreturn)); +$params = ['id'=>$id, 'sr'=> $sectionreturn]; +if (!empty($showonly)) { + $params['showonly'] = $showonly; +} +$PAGE->set_url('/course/editsection.php', $params); $section = $DB->get_record('course_sections', array('id' => $id), '*', MUST_EXIST); $course = $DB->get_record('course', array('id' => $section->course), '*', MUST_EXIST); @@ -96,11 +101,13 @@ $editoroptions = array( $courseformat = course_get_format($course); $defaultsectionname = $courseformat->get_default_section_name($section); -$customdata = array( +$customdata = [ 'cs' => $sectioninfo, 'editoroptions' => $editoroptions, - 'defaultsectionname' => $defaultsectionname -); + 'defaultsectionname' => $defaultsectionname, + 'showonly' => $showonly, +]; + $mform = $courseformat->editsection_form($PAGE->url, $customdata); // set current value, make an editable copy of section_info object @@ -110,6 +117,9 @@ if (!empty($CFG->enableavailability)) { $initialdata['availabilityconditionsjson'] = $sectioninfo->availability; } $mform->set_data($initialdata); +if (!empty($showonly)) { + $mform->filter_shown_headers(explode(',', $showonly)); +} if ($mform->is_cancelled()){ // Form cancelled, return to course. diff --git a/course/editsection_form.php b/course/editsection_form.php index 264ae96ac0d..63465064e95 100644 --- a/course/editsection_form.php +++ b/course/editsection_form.php @@ -17,6 +17,7 @@ require_once($CFG->libdir.'/gradelib.php'); class editsection_form extends moodleform { function definition() { + global $CFG; $mform = $this->_form; $course = $this->_customdata['course']; @@ -47,26 +48,28 @@ class editsection_form extends moodleform { $elements = $courseformat->create_edit_form_elements($mform, true); } - $mform->_registerCancelButton('cancel'); - } - - public function definition_after_data() { - global $CFG, $DB; - - $mform = $this->_form; - $course = $this->_customdata['course']; - $context = context_course::instance($course->id); - if (!empty($CFG->enableavailability)) { $mform->addElement('header', 'availabilityconditions', - get_string('restrictaccess', 'availability')); + get_string('restrictaccess', 'availability')); $mform->setExpanded('availabilityconditions', false); // Availability field. This is just a textarea; the user interface // interaction is all implemented in JavaScript. The field is named // availabilityconditionsjson for consistency with moodleform_mod. $mform->addElement('textarea', 'availabilityconditionsjson', - get_string('accessrestrictions', 'availability')); + get_string('accessrestrictions', 'availability')); + } + + $mform->_registerCancelButton('cancel'); + } + + public function definition_after_data() { + global $CFG; + + $mform = $this->_form; + $course = $this->_customdata['course']; + + if (!empty($CFG->enableavailability)) { \core_availability\frontend::include_all_javascript($course, null, $this->_customdata['cs']); } diff --git a/course/modedit.php b/course/modedit.php index b3c9959b6b7..4cb5ee13dc3 100644 --- a/course/modedit.php +++ b/course/modedit.php @@ -37,12 +37,16 @@ $return = optional_param('return', 0, PARAM_BOOL); //return to course/view.ph $type = optional_param('type', '', PARAM_ALPHANUM); //TODO: hopefully will be removed in 2.0 $sectionreturn = optional_param('sr', null, PARAM_INT); $beforemod = optional_param('beforemod', 0, PARAM_INT); +$showonly = optional_param('showonly', '', PARAM_ALPHANUM); // Settings group to show expanded and hide the rest. $url = new moodle_url('/course/modedit.php'); $url->param('sr', $sectionreturn); if (!empty($return)) { $url->param('return', $return); } +if (!empty($showonly)) { + $url->param('showonly', $showonly); +} if (!empty($add)) { $section = required_param('section', PARAM_INT); @@ -113,6 +117,9 @@ if (!empty($add)) { $data->return = $return; $data->sr = $sectionreturn; $data->update = $update; + if (!empty($showonly)) { + $data->showonly = $showonly; + } $sectionname = get_section_name($course, $cw); $fullmodulename = get_string('modulename', $module->name); @@ -153,6 +160,9 @@ if (file_exists($modmoodleform)) { $mformclassname = 'mod_'.$module->name.'_mod_form'; $mform = new $mformclassname($data, $cw->section, $cm, $course); $mform->set_data($data); +if (!empty($showonly)) { + $mform->filter_shown_headers(explode(',', $showonly)); +} if ($mform->is_cancelled()) { if ($return && !empty($cm->id)) { diff --git a/course/moodleform_mod.php b/course/moodleform_mod.php index e11a5da2998..34c2de438c6 100644 --- a/course/moodleform_mod.php +++ b/course/moodleform_mod.php @@ -1064,6 +1064,9 @@ abstract class moodleform_mod extends moodleform { $mform->addElement('hidden', 'beforemod', 0); $mform->setType('beforemod', PARAM_INT); + + $mform->addElement('hidden', 'showonly', ''); + $mform->setType('showonly', PARAM_ALPHANUMEXT); } public function standard_grading_coursemodule_elements() { diff --git a/lib/form/amd/build/collapsesections.min.js b/lib/form/amd/build/collapsesections.min.js index c163e8553e8..ff3fd35b959 100644 --- a/lib/form/amd/build/collapsesections.min.js +++ b/lib/form/amd/build/collapsesections.min.js @@ -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",CLASSES_SHOW="show",CLASSES_COLLAPSED="collapsed";_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 expandedcount=0;const formcontainercount=(0,_jquery.default)(SELECTORS_FORMCONTAINER).length;(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=".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");collapsemenu.addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),collapsemenu.click())}));let formcontainercount=0;(0,_jquery.default)(SELECTORS_FORMCONTAINER).each(((_,container)=>{container.classList.contains(CLASSES_HIDDEN)||container.parentElement.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()}})); //# sourceMappingURL=collapsesections.min.js.map \ No newline at end of file diff --git a/lib/form/amd/build/collapsesections.min.js.map b/lib/form/amd/build/collapsesections.min.js.map index 692266169db..f2623578c63 100644 --- a/lib/form/amd/build/collapsesections.min.js.map +++ b/lib/form/amd/build/collapsesections.min.js.map @@ -1 +1 @@ -{"version":3,"file":"collapsesections.min.js","sources":["../src/collapsesections.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Collapse or expand all form sections on clicking the expand all / collapse al link.\n *\n * @module core_form/collapsesections\n * @copyright 2021 Bas Brands\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport $ from 'jquery';\nimport Pending from 'core/pending';\n\nconst SELECTORS = {\n FORMHEADER: '.fheader',\n FORMCONTAINER: '.fcontainer',\n};\n\nconst CLASSES = {\n SHOW: 'show',\n COLLAPSED: 'collapsed'\n};\n\n/**\n * Initialises the form section collapse / expand action.\n *\n * @param {string} collapsesections the collapse/expand link id.\n */\nexport const init = collapsesections => {\n // All jQuery in this code can be replaced when MDL-71979 is integrated (move to Bootstrap 5).\n const pendingPromise = new Pending('core_form/collapsesections');\n const collapsemenu = document.querySelector(collapsesections);\n const formParent = collapsemenu.closest('form');\n collapsemenu.addEventListener('keydown', e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n collapsemenu.click();\n }\n });\n\n // Override default collapse class if all containers are expanded on page load\n let expandedcount = 0;\n const formcontainercount = $(SELECTORS.FORMCONTAINER).length;\n $(SELECTORS.FORMCONTAINER).each((_, collapsecontainer) => {\n if (collapsecontainer.classList.contains(CLASSES.SHOW)) {\n expandedcount++;\n }\n });\n\n if (formcontainercount === expandedcount) {\n collapsemenu.classList.remove(CLASSES.COLLAPSED);\n collapsemenu.setAttribute('aria-expanded', true);\n }\n\n collapsemenu.addEventListener('click', () => {\n let action = 'hide';\n if (collapsemenu.classList.contains(CLASSES.COLLAPSED)) {\n action = 'show';\n }\n\n formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {\n $(collapsecontainer).collapse(action);\n });\n });\n\n // Ensure collapse menu button adds aria-controls attribute referring to each collapsible element.\n const collapseElements = $(SELECTORS.FORMHEADER);\n const collapseElementIds = [...collapseElements].map((element, index) => {\n element.id = element.id || `collapseElement-${index}`;\n return element.id;\n });\n collapsemenu.setAttribute('aria-controls', collapseElementIds.join(' '));\n\n $(SELECTORS.FORMCONTAINER).on('hidden.bs.collapse', () => {\n let allCollapsed = true;\n\n formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {\n if (collapsecontainer.classList.contains(CLASSES.SHOW)) {\n allCollapsed = false;\n }\n });\n\n if (allCollapsed) {\n collapsemenu.classList.add(CLASSES.COLLAPSED);\n collapsemenu.setAttribute('aria-expanded', false);\n }\n });\n $(SELECTORS.FORMCONTAINER).on('shown.bs.collapse', () => {\n let allExpanded = true;\n\n formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {\n if (!collapsecontainer.classList.contains(CLASSES.SHOW)) {\n allExpanded = false;\n }\n });\n\n if (allExpanded) {\n collapsemenu.classList.remove(CLASSES.COLLAPSED);\n collapsemenu.setAttribute('aria-expanded', true);\n }\n });\n pendingPromise.resolve();\n};\n"],"names":["SELECTORS","CLASSES","collapsesections","pendingPromise","Pending","collapsemenu","document","querySelector","formParent","closest","addEventListener","e","key","preventDefault","click","expandedcount","formcontainercount","length","each","_","collapsecontainer","classList","contains","remove","setAttribute","action","querySelectorAll","forEach","collapse","collapseElementIds","map","element","index","id","join","on","allCollapsed","add","allExpanded","resolve"],"mappings":";;;;;;;;0KA2BMA,qBACU,WADVA,wBAEa,cAGbC,aACI,OADJA,kBAES,0BAQKC,yBAEVC,eAAiB,IAAIC,iBAAQ,8BAC7BC,aAAeC,SAASC,cAAcL,kBACtCM,WAAaH,aAAaI,QAAQ,QACxCJ,aAAaK,iBAAiB,WAAWC,IACvB,UAAVA,EAAEC,KAA6B,MAAVD,EAAEC,MACvBD,EAAEE,iBACFR,aAAaS,gBAKjBC,cAAgB,QACdC,oBAAqB,mBAAEhB,yBAAyBiB,2BACpDjB,yBAAyBkB,MAAK,CAACC,EAAGC,qBAC5BA,kBAAkBC,UAAUC,SAASrB,eACrCc,mBAIJC,qBAAuBD,gBACvBV,aAAagB,UAAUE,OAAOtB,mBAC9BI,aAAamB,aAAa,iBAAiB,IAG/CnB,aAAaK,iBAAiB,SAAS,SAC/Be,OAAS,OACTpB,aAAagB,UAAUC,SAASrB,qBAChCwB,OAAS,QAGbjB,WAAWkB,iBAAiB1B,yBAAyB2B,SAASP,wCACxDA,mBAAmBQ,SAASH,oBAMhCI,mBAAqB,KADF,mBAAE7B,uBACsB8B,KAAI,CAACC,QAASC,SAC3DD,QAAQE,GAAKF,QAAQE,8BAAyBD,OACvCD,QAAQE,MAEnB5B,aAAamB,aAAa,gBAAiBK,mBAAmBK,KAAK,0BAEjElC,yBAAyBmC,GAAG,sBAAsB,SAC5CC,cAAe,EAEnB5B,WAAWkB,iBAAiB1B,yBAAyB2B,SAASP,oBACtDA,kBAAkBC,UAAUC,SAASrB,gBACrCmC,cAAe,MAInBA,eACA/B,aAAagB,UAAUgB,IAAIpC,mBAC3BI,aAAamB,aAAa,iBAAiB,2BAGjDxB,yBAAyBmC,GAAG,qBAAqB,SAC3CG,aAAc,EAElB9B,WAAWkB,iBAAiB1B,yBAAyB2B,SAASP,oBACrDA,kBAAkBC,UAAUC,SAASrB,gBACtCqC,aAAc,MAIlBA,cACAjC,aAAagB,UAAUE,OAAOtB,mBAC9BI,aAAamB,aAAa,iBAAiB,OAGnDrB,eAAeoC"} \ No newline at end of file +{"version":3,"file":"collapsesections.min.js","sources":["../src/collapsesections.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Collapse or expand all form sections on clicking the expand all / collapse al link.\n *\n * @module core_form/collapsesections\n * @copyright 2021 Bas Brands\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport $ from 'jquery';\nimport Pending from 'core/pending';\n\nconst SELECTORS = {\n FORMHEADER: '.fheader',\n FORMCONTAINER: '.fcontainer',\n};\n\nconst CLASSES = {\n SHOW: 'show',\n COLLAPSED: 'collapsed',\n HIDDEN: 'd-none'\n};\n\n/**\n * Initialises the form section collapse / expand action.\n *\n * @param {string} collapsesections the collapse/expand link id.\n */\nexport const init = collapsesections => {\n // All jQuery in this code can be replaced when MDL-71979 is integrated (move to Bootstrap 5).\n const pendingPromise = new Pending('core_form/collapsesections');\n const collapsemenu = document.querySelector(collapsesections);\n const formParent = collapsemenu.closest('form');\n collapsemenu.addEventListener('keydown', e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n collapsemenu.click();\n }\n });\n\n // Override default collapse class if all visible containers are expanded on page load\n let formcontainercount = 0;\n $(SELECTORS.FORMCONTAINER).each((_, container) => {\n if (!container.classList.contains(CLASSES.HIDDEN) &&\n !container.parentElement.classList.contains(CLASSES.HIDDEN)) {\n formcontainercount++;\n }\n });\n let expandedcount = 0;\n $(SELECTORS.FORMCONTAINER).each((_, collapsecontainer) => {\n if (collapsecontainer.classList.contains(CLASSES.SHOW)) {\n expandedcount++;\n }\n });\n\n if (formcontainercount === expandedcount) {\n collapsemenu.classList.remove(CLASSES.COLLAPSED);\n collapsemenu.setAttribute('aria-expanded', true);\n }\n\n collapsemenu.addEventListener('click', () => {\n let action = 'hide';\n if (collapsemenu.classList.contains(CLASSES.COLLAPSED)) {\n action = 'show';\n }\n\n formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {\n $(collapsecontainer).collapse(action);\n });\n });\n\n // Ensure collapse menu button adds aria-controls attribute referring to each collapsible element.\n const collapseElements = $(SELECTORS.FORMHEADER);\n const collapseElementIds = [...collapseElements].map((element, index) => {\n element.id = element.id || `collapseElement-${index}`;\n return element.id;\n });\n collapsemenu.setAttribute('aria-controls', collapseElementIds.join(' '));\n\n $(SELECTORS.FORMCONTAINER).on('hidden.bs.collapse', () => {\n let allCollapsed = true;\n\n formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {\n if (collapsecontainer.classList.contains(CLASSES.SHOW)) {\n allCollapsed = false;\n }\n });\n\n if (allCollapsed) {\n collapsemenu.classList.add(CLASSES.COLLAPSED);\n collapsemenu.setAttribute('aria-expanded', false);\n }\n });\n $(SELECTORS.FORMCONTAINER).on('shown.bs.collapse', () => {\n let allExpanded = true;\n\n formParent.querySelectorAll(SELECTORS.FORMCONTAINER).forEach((collapsecontainer) => {\n if (!collapsecontainer.classList.contains(CLASSES.SHOW)) {\n allExpanded = false;\n }\n });\n\n if (allExpanded) {\n collapsemenu.classList.remove(CLASSES.COLLAPSED);\n collapsemenu.setAttribute('aria-expanded', true);\n }\n });\n pendingPromise.resolve();\n};\n"],"names":["SELECTORS","CLASSES","collapsesections","pendingPromise","Pending","collapsemenu","document","querySelector","formParent","closest","addEventListener","e","key","preventDefault","click","formcontainercount","each","_","container","classList","contains","parentElement","expandedcount","collapsecontainer","remove","setAttribute","action","querySelectorAll","forEach","collapse","collapseElementIds","map","element","index","id","join","on","allCollapsed","add","allExpanded","resolve"],"mappings":";;;;;;;;0KA2BMA,qBACU,WADVA,wBAEa,cAGbC,aACI,OADJA,kBAES,YAFTA,eAGM,uBAQQC,yBAEVC,eAAiB,IAAIC,iBAAQ,8BAC7BC,aAAeC,SAASC,cAAcL,kBACtCM,WAAaH,aAAaI,QAAQ,QACxCJ,aAAaK,iBAAiB,WAAWC,IACvB,UAAVA,EAAEC,KAA6B,MAAVD,EAAEC,MACvBD,EAAEE,iBACFR,aAAaS,gBAKjBC,mBAAqB,sBACvBf,yBAAyBgB,MAAK,CAACC,EAAGC,aAC3BA,UAAUC,UAAUC,SAASnB,iBACjCiB,UAAUG,cAAcF,UAAUC,SAASnB,iBACxCc,4BAGJO,cAAgB,sBAClBtB,yBAAyBgB,MAAK,CAACC,EAAGM,qBAC5BA,kBAAkBJ,UAAUC,SAASnB,eACrCqB,mBAIJP,qBAAuBO,gBACvBjB,aAAac,UAAUK,OAAOvB,mBAC9BI,aAAaoB,aAAa,iBAAiB,IAG/CpB,aAAaK,iBAAiB,SAAS,SAC/BgB,OAAS,OACTrB,aAAac,UAAUC,SAASnB,qBAChCyB,OAAS,QAGblB,WAAWmB,iBAAiB3B,yBAAyB4B,SAASL,wCACxDA,mBAAmBM,SAASH,oBAMhCI,mBAAqB,KADF,mBAAE9B,uBACsB+B,KAAI,CAACC,QAASC,SAC3DD,QAAQE,GAAKF,QAAQE,8BAAyBD,OACvCD,QAAQE,MAEnB7B,aAAaoB,aAAa,gBAAiBK,mBAAmBK,KAAK,0BAEjEnC,yBAAyBoC,GAAG,sBAAsB,SAC5CC,cAAe,EAEnB7B,WAAWmB,iBAAiB3B,yBAAyB4B,SAASL,oBACtDA,kBAAkBJ,UAAUC,SAASnB,gBACrCoC,cAAe,MAInBA,eACAhC,aAAac,UAAUmB,IAAIrC,mBAC3BI,aAAaoB,aAAa,iBAAiB,2BAGjDzB,yBAAyBoC,GAAG,qBAAqB,SAC3CG,aAAc,EAElB/B,WAAWmB,iBAAiB3B,yBAAyB4B,SAASL,oBACrDA,kBAAkBJ,UAAUC,SAASnB,gBACtCsC,aAAc,MAIlBA,cACAlC,aAAac,UAAUK,OAAOvB,mBAC9BI,aAAaoB,aAAa,iBAAiB,OAGnDtB,eAAeqC"} \ No newline at end of file diff --git a/lib/form/amd/src/collapsesections.js b/lib/form/amd/src/collapsesections.js index 2ebfab88a08..b8f8f7e9641 100644 --- a/lib/form/amd/src/collapsesections.js +++ b/lib/form/amd/src/collapsesections.js @@ -32,7 +32,8 @@ const SELECTORS = { const CLASSES = { SHOW: 'show', - COLLAPSED: 'collapsed' + COLLAPSED: 'collapsed', + HIDDEN: 'd-none' }; /** @@ -52,9 +53,15 @@ export const init = collapsesections => { } }); - // Override default collapse class if all containers are expanded on page load + // Override default collapse class if all visible containers are expanded on page load + let formcontainercount = 0; + $(SELECTORS.FORMCONTAINER).each((_, container) => { + if (!container.classList.contains(CLASSES.HIDDEN) && + !container.parentElement.classList.contains(CLASSES.HIDDEN)) { + formcontainercount++; + } + }); let expandedcount = 0; - const formcontainercount = $(SELECTORS.FORMCONTAINER).length; $(SELECTORS.FORMCONTAINER).each((_, collapsecontainer) => { if (collapsecontainer.classList.contains(CLASSES.SHOW)) { expandedcount++; diff --git a/lib/formslib.php b/lib/formslib.php index 56270813653..bba17179d20 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -485,6 +485,24 @@ abstract class moodleform { $this->_form->setDefaults($default_values); } + /** + * Use this method to indicate that the fieldsets should be shown as expanded + * and all other fieldsets should be hidden. + * The method is applicable to header elements only. + * + * @param array $shownonly array of header element names + * @return void + */ + public function filter_shown_headers(array $shownonly): void { + $toshow = []; + foreach ($shownonly as $show) { + if ($this->_form->elementExists($show) && $this->_form->getElementType($show) == 'header') { + $toshow[] = $show; + } + } + $this->_form->filter_shown_headers($toshow); + } + /** * Check that form was submitted. Does not check validity of submitted data. * @@ -1636,6 +1654,14 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { */ var $_disableShortforms = false; + /** + * Array whose keys are the only elements to be shown. + * Rest of the elements that are not in this array will be hidden. + * + * @var array + */ + protected $_shownonlyelements = []; + /** @var bool whether to automatically initialise the form change detector this form. */ protected $_use_form_change_checker = true; @@ -1830,6 +1856,45 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { $this->_collapsibleElements[$headername] = !$expanded; } + /** + * Use this method to indicate that the fieldsets should be shown and expanded + * and all other fieldsets should be hidden. + * The method is applicable to header elements only. + * + * @param array $shownonly array of header element names + * @return void + */ + public function filter_shown_headers(array $shownonly): void { + $this->_shownonlyelements = []; + if (empty($shownonly)) { + return; + } + foreach ($shownonly as $headername) { + $element = $this->getElement($headername); + if ($element->getType() == 'header') { + $this->_shownonlyelements[] = $headername; + $this->setExpanded($headername); + } + } + } + + /** + * Use this method to check if the fieldsets could be shown. + * The method is applicable to header elements only. + * + * @param string $headername header element name to check in the shown only elements array. + * @return void + */ + public function is_shown(string $headername): bool { + if (empty($headername)) { + return true; + } + if (empty($this->_shownonlyelements)) { + return true; + } + return in_array($headername, $this->_shownonlyelements); + } + /** * Use this method to add show more/less status element required for passing * over the advanced elements visibility status on the form submission. @@ -2012,15 +2077,22 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { } if ($element->getType() == 'header') { + if (!$this->is_shown($headername)) { + $this->setExpanded($headername, false); + continue; + } if ($headercounter === 1 && !isset($this->_collapsibleElements[$headername])) { // By default the first section is always expanded, except if a state has already been set. $this->setExpanded($headername, true); - } else if (($headercounter === 2 && $headerscount === 2) && !isset($this->_collapsibleElements[$headername])) { + } else if ( + ($headercounter === 2 && $headerscount === 2) + && !isset($this->_collapsibleElements[$headername]) + ) { // The second section is always expanded if the form only contains 2 sections), // except if a state has already been set. $this->setExpanded($headername, true); } - } else if ($anyrequiredorerror) { + } else if ($anyrequiredorerror && (empty($headername) || $this->is_shown($headername))) { // If any error or required field are present within the header, we need to expand it. $this->setExpanded($headername, true, true); } else if (!isset($this->_collapsibleElements[$headername])) { @@ -2032,12 +2104,38 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { // Pass the array to renderer object. $renderer->setCollapsibleElements($this->_collapsibleElements); } + + $this->accept_set_nonvisible_elements($renderer); + if (method_exists($renderer, 'set_sticky_footer') && !empty($this->_stickyfooterelement)) { $renderer->set_sticky_footer($this->_stickyfooterelement); } parent::accept($renderer); } + /** + * Checking non-visible elements to set when accepting a renderer. + * @param HTML_QuickForm_Renderer $renderer + */ + private function accept_set_nonvisible_elements($renderer) { + if (!method_exists($renderer, 'set_nonvisible_elements') || $this->_disableShortforms) { + return; + } + $nonvisibles = []; + foreach (array_keys($this->_elements) as $index) { + $element =& $this->_elements[$index]; + if ($element->getType() != 'header') { + continue; + } + $headername = $element->getName(); + if (!$this->is_shown($headername)) { + $nonvisibles[] = $headername; + } + } + // Pass the array to renderer object. + $renderer->set_nonvisible_elements($nonvisibles); + } + /** * Adds one or more element names that indicate the end of a fieldset * @@ -3116,6 +3214,14 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ /** @var string advanced class HTML. */ protected $_advancedHTML; + /** + * Array whose keys are element names should be hidden. + * If the key exists this is an invisible element. + * + * @var array + */ + protected $_nonvisibleelements = []; + /** * Constructor */ @@ -3175,6 +3281,15 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ $this->_collapsibleElements = $elements; } + /** + * Setting non visible elements + * + * @param array $elements + */ + public function set_nonvisible_elements($elements) { + $this->_nonvisibleelements = $elements; + } + /** * What to do when starting the form * @@ -3437,6 +3552,11 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ } } + // Hide fieldsets not included in the shown only elements. + if (in_array($header->getName(), $this->_nonvisibleelements)) { + $fieldsetclasses[] = 'd-none'; + } + if (isset($this->_advancedElements[$name])){ $fieldsetclasses[] = 'containsadvancedelements'; } diff --git a/lib/upgrade.txt b/lib/upgrade.txt index e72cff8d4d5..2d06b7c66f9 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -42,6 +42,7 @@ information provided here is intended especially for developers. * New events course_started and course_ended have been created. For now, they are triggered when courses change automatically their visibility through the new scheduled tasks to hide/show courses based on their start/end dates. * The action_menu::set_constraint() method is deprecated. Please use action_menu::set_boundary() instead. +* New method moodleform::filter_shown_headers() is created to show some expanded headers only and hide the rest. === 4.2 ===