Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Field controller for choicedropdown field.** @module core_form/choicedropdown* @copyright 2023 Ferran Recio <ferran@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/import {getDropdownStatus} from 'core/local/dropdown/status';import {markFormAsDirty} from 'core_form/changechecker';const Classes = {notClickable: 'not-clickable',hidden: 'd-none',};/*** Internal form element class.** @private* @class FieldController* @copyright 2023 Ferran Recio <ferran@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class FieldController {/*** Class constructor.** @param {String} elementId Form element id*/constructor(elementId) {this.elementId = elementId;this.mainSelect = document.getElementById(this.elementId);this.dropdown = getDropdownStatus(`[data-form-controls="${this.elementId}"]`);this.dropdown.getElement().classList.remove(Classes.hidden);}/*** Add form element event listener.*/addEventListeners() {this.dropdown.getElement().addEventListener('change',this.updateSelect.bind(this));// Click on a dropdown link can trigger a wrong dirty form reload warning.this.dropdown.getElement().addEventListener('click',(event) => event.preventDefault());this.mainSelect.addEventListener('change',this.updateDropdown.bind(this));// Enabling or disabling the select does not trigger any JS event.const observerCallback = (mutations) => {mutations.forEach((mutation) => {if (mutation.type !== 'attributes' || mutation.attributeName !== 'disabled') {return;}this.updateDropdown();});};new MutationObserver(observerCallback).observe(this.mainSelect,{attributeFilter: ['disabled']});}/*** Check if the field is disabled.* @returns {Boolean}*/isDisabled() {return this.mainSelect?.hasAttribute('disabled');}/*** Update selected option preview in form.*/async updateDropdown() {this.dropdown.setButtonDisabled(this.isDisabled());if (this.dropdown.getSelectedValue() == this.mainSelect.value) {return;}this.dropdown.setSelectedValue(this.mainSelect.value);}/*** Update selected option preview in form.*/async updateSelect() {if (this.dropdown.getSelectedValue() == this.mainSelect.value) {return;}this.mainSelect.value = this.dropdown.getSelectedValue();markFormAsDirty(this.mainSelect.closest('form'));// Change the select element via JS does not trigger the standard change event.this.mainSelect.dispatchEvent(new Event('change'));}/*** Disable the choice dialog and convert it into a regular select field.*/disableInteractiveDialog() {this.mainSelect?.classList.remove(Classes.hidden);const dropdownElement = this.dropdown.getElement();dropdownElement.classList.add(Classes.hidden);}/*** Check if the field has a force dialog attribute.// ** The force dialog is a setting to force the javascript control even in* behat test.** @returns {Boolean} if the dialog modal should be forced or not*/hasForceDialog() {return !!this.mainSelect?.dataset.forceDialog;}}/*** Initialises a choice dialog field.** @method init* @param {String} elementId Form element id* @listens event:uploadStarted* @listens event:uploadCompleted*/export const init = (elementId) => {const field = new FieldController(elementId);// This field is just a select wrapper. To optimize tests, we don't want to keep behat// waiting for extra loadings in this case. The set field steps are about testing other// stuff, not to test fancy javascript form fields. However, we keep the possibility of// testing the javascript part using behat when necessary.if (document.body.classList.contains('behat-site') && !field.hasForceDialog()) {field.disableInteractiveDialog();return;}field.addEventListeners();};