X7ROOT File Manager
Current Path:
/home/cbholdings/pasukulu/course/format/amd/src/local/content/actions
home
/
cbholdings
/
pasukulu
/
course
/
format
/
amd
/
src
/
local
/
content
/
actions
/
📁
..
📄
bulkselection.js
(12.85 KB)
Editing: bulkselection.js
// 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/>. /** * Bulk selection auxiliar methods. * * @module core_courseformat/local/content/actions/bulkselection * @class core_courseformat/local/content/actions/bulkselection * @copyright 2023 Ferran Recio <ferran@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class BulkSelector { /** * The class constructor. * @param {CourseEditor} courseEditor the original actions component. */ constructor(courseEditor) { this.courseEditor = courseEditor; this.selectors = { BULKCMCHECKBOX: `[data-bulkcheckbox][data-action='toggleSelectionCm']`, BULKSECTIONCHECKBOX: `[data-bulkcheckbox][data-action='toggleSelectionSection']`, CONTENT: `#region-main`, }; } /** * Process a new selection. * @param {Number} id * @param {String} elementType cm or section * @param {Object} settings special selection settings * @param {Boolean} settings.all if the action is over all elements of the same type * @param {Boolean} settings.range if the action is over a range of elements */ processNewSelection(id, elementType, settings) { const value = !this._isBulkSelected(id, elementType); if (settings.all && settings.range) { this.switchCurrentSelection(); return; } if (!this._isSelectable(id, elementType)) { return; } if (settings.all) { if (elementType == 'cm') { this._updateBulkCmSiblings(id, value); } else { this._updateBulkSelectionAll(elementType, value); } return; } if (settings.range) { this._updateBulkSelectionRange(id, elementType, value); return; } this._updateBulkSelection([id], elementType, value); } /** * Switch between section and cm selection. */ switchCurrentSelection() { const bulk = this.courseEditor.get('bulk'); if (bulk.selectedType === '' || bulk.selection.length == 0) { return; } const newSelectedType = (bulk.selectedType === 'section') ? 'cm' : 'section'; let newSelectedIds; if (bulk.selectedType === 'section') { newSelectedIds = this._getCmIdsFromSections(bulk.selection); } else { newSelectedIds = this._getSectionIdsFromCms(bulk.selection); } // Formats can display only a few activities of the section, // We need to select on the activities present in the page. const affectedIds = []; newSelectedIds.forEach(newId => { if (this._getSelector(newId, newSelectedType)) { affectedIds.push(newId); } }); this.courseEditor.dispatch('bulkEnable', true); if (affectedIds.length != 0) { this._updateBulkSelection(affectedIds, newSelectedType, true); } } /** * Select all elements of the current type. * @param {Boolean} value the wanted selected value */ selectAll(value) { const bulk = this.courseEditor.get('bulk'); if (bulk.selectedType == '') { return; } if (!value) { this.courseEditor.dispatch('bulkEnable', true); return; } const elementType = bulk.selectedType; this._updateBulkSelectionAll(elementType, value); } /** * Checks if all selectable elements are selected. * @returns {Boolean} true if all are selected */ checkAllSelected() { const bulk = this.courseEditor.get('bulk'); if (bulk.selectedType == '') { return false; } return this._getContentCheckboxes(bulk.selectedType).every(bulkSelect => { if (bulkSelect.disabled) { return false; } // Section zero is never selectale for bulk actions. if (bulk.selectedType == 'section') { const section = this.courseEditor.get('section', bulkSelect.dataset.id); if (section.number == 0) { return true; } } return bulk.selection.includes(bulkSelect.dataset.id); }); } /** * Check if the id is part of the current bulk selection. * @private * @param {Number} id * @param {String} elementType * @returns {Boolean} if the element is present in the current selection. */ _isBulkSelected(id, elementType) { const bulk = this.courseEditor.get('bulk'); if (bulk.selectedType !== elementType) { return false; } return bulk.selection.includes(id); } /** * Update the current bulk selection removing or adding Ids. * @private * @param {Number[]} ids the user selected element id * @param {String} elementType cm or section * @param {Boolean} value the wanted selected value */ _updateBulkSelection(ids, elementType, value) { let mutation = elementType; mutation += (value) ? 'Select' : 'Unselect'; this.courseEditor.dispatch(mutation, ids); } /** * Get all content bulk selector checkboxes of one type (section/cm). * @private * @param {String} elementType section or cm * @returns {HTMLElement[]} an array with all checkboxes */ _getContentCheckboxes(elementType) { const selector = (elementType == 'cm') ? this.selectors.BULKCMCHECKBOX : this.selectors.BULKSECTIONCHECKBOX; const checkboxes = document.querySelectorAll(`${this.selectors.CONTENT} ${selector}`); // Converting to array because NodeList has less iteration methods. return [...checkboxes]; } /** * Validate if an element is selectable in the current page. * @private * @param {Number} id the user selected element id * @param {String} elementType cm or section * @return {Boolean} */ _isSelectable(id, elementType) { const bulkSelect = this._getSelector(id, elementType); if (!bulkSelect || bulkSelect.disabled) { return false; } return true; } /** * Get as specific element checkbox. * @private * @param {Number} id * @param {String} elementType cm or section * @returns {HTMLElement|undefined} */ _getSelector(id, elementType) { let selector = (elementType == 'cm') ? this.selectors.BULKCMCHECKBOX : this.selectors.BULKSECTIONCHECKBOX; selector += `[data-id='${id}']`; return document.querySelector(`${this.selectors.CONTENT} ${selector}`); } /** * Update the current bulk selection when a user uses shift to select a range. * @private * @param {Number} id the user selected element id * @param {String} elementType cm or section * @param {Boolean} value the wanted selected value */ _updateBulkSelectionRange(id, elementType, value) { const bulk = this.courseEditor.get('bulk'); let lastSelectedId = bulk.selection.at(-1); if (bulk.selectedType !== elementType || lastSelectedId == id) { this._updateBulkSelection([id], elementType, value); return; } const affectedIds = []; let found = 0; this._getContentCheckboxes(elementType).every(bulkSelect => { if (bulkSelect.disabled) { return true; } if (bulkSelect.dataset.id == id || bulkSelect.dataset.id == lastSelectedId) { found++; } if (found == 0) { return true; } affectedIds.push(bulkSelect.dataset.id); return found != 2; }); this._updateBulkSelection(affectedIds, elementType, value); } /** * Select or unselect all cm siblings. * @private * @param {Number} cmId the user selected element id * @param {Boolean} value the wanted selected value */ _updateBulkCmSiblings(cmId, value) { const bulk = this.courseEditor.get('bulk'); if (bulk.selectedType === 'section') { return; } const cm = this.courseEditor.get('cm', cmId); const section = this.courseEditor.get('section', cm.sectionid); // Formats can display only a few activities of the section, // We need to select on the activities selectable in the page. const affectedIds = []; section.cmlist.forEach(sectionCmId => { if (this._isSelectable(sectionCmId, 'cm')) { affectedIds.push(sectionCmId); } }); this._updateBulkSelection(affectedIds, 'cm', value); } /** * Select or unselects al elements of the same type. * @private * @param {String} elementType section or cm * @param {Boolean} value if the elements must be selected or unselected. */ _updateBulkSelectionAll(elementType, value) { const affectedIds = []; this._getContentCheckboxes(elementType).forEach(bulkSelect => { if (bulkSelect.disabled) { return; } if (elementType == 'section') { const section = this.courseEditor.get('section', bulkSelect.dataset.id); if (section?.number == 0) { return; } } affectedIds.push(bulkSelect.dataset.id); }); this._updateBulkSelection(affectedIds, elementType, value); } /** * Get all cm ids from a specific section ids. * @private * @param {Number[]} sectionIds * @returns {Number[]} the cm ids */ _getCmIdsFromSections(sectionIds) { const result = []; sectionIds.forEach(sectionId => { const section = this.courseEditor.get('section', sectionId); result.push(...section.cmlist); }); return result; } /** * Get all section ids containing a specific cm ids. * @private * @param {Number[]} cmIds * @returns {Number[]} the section ids */ _getSectionIdsFromCms(cmIds) { const result = new Set(); cmIds.forEach(cmId => { const cm = this.courseEditor.get('cm', cmId); if (cm.sectionnumber == 0) { return; } result.add(cm.sectionid); }); return [...result]; } } /** * Process a bulk selection toggle action. * @method * @param {CourseEditor} courseEditor * @param {HTMLElement} target the action element * @param {Event} event * @param {String} elementType cm or section */ export const toggleBulkSelectionAction = function(courseEditor, target, event, elementType) { const id = target.dataset.id; if (!id) { return; } // When the action cames from a form element (checkbox) we should not preventDefault. // If we do it the changechecker module will execute the state change twice. if (target.dataset.preventDefault) { event.preventDefault(); } // Using shift or alt key can produce text selection. document.getSelection().removeAllRanges(); const bulkSelector = new BulkSelector(courseEditor); bulkSelector.processNewSelection( id, elementType, { range: event.shiftKey, all: event.altKey, } ); }; /** * Switch the current bulk selection. * @method * @param {CourseEditor} courseEditor */ export const switchBulkSelection = function(courseEditor) { const bulkSelector = new BulkSelector(courseEditor); bulkSelector.switchCurrentSelection(); }; /** * Select/unselect all element of the selected type. * @method * @param {CourseEditor} courseEditor * @param {Boolean} value if the elements must be selected or unselected. */ export const selectAllBulk = function(courseEditor, value) { const bulkSelector = new BulkSelector(courseEditor); bulkSelector.selectAll(value); }; /** * Check if all possible elements are selected. * @method * @param {CourseEditor} courseEditor * @return {Boolean} if all elements of the current type are selected. */ export const checkAllBulkSelected = function(courseEditor) { const bulkSelector = new BulkSelector(courseEditor); return bulkSelector.checkAllSelected(); };
Upload File
Create Folder