MDL-78288 core_course: Adding filter_shown_headers option to forms

This commit is contained in:
Amaia Anabitarte
2023-07-12 14:22:56 +02:00
parent ef93325f27
commit 290e6f4c6f
9 changed files with 177 additions and 23 deletions
+14 -4
View File
@@ -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.
+15 -12
View File
@@ -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']);
}
+10
View File
@@ -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)) {
+3
View File
@@ -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() {
+1 -1
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",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
File diff suppressed because one or more lines are too long
+10 -3
View File
@@ -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++;
+122 -2
View File
@@ -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';
}
+1
View File
@@ -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 ===