AutorÃa | Ultima modificación | Ver Log |
{"version":3,"file":"bulkselection.min.js","sources":["../../../../src/local/content/actions/bulkselection.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Bulk selection auxiliar methods.\n *\n * @module core_courseformat/local/content/actions/bulkselection\n * @class core_courseformat/local/content/actions/bulkselection\n * @cop
yright 2023 Ferran Recio <ferran@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass BulkSelector {\n\n /**\n * The class constructor.\n * @param {CourseEditor} courseEditor the original actions component.\n */\n constructor(courseEditor) {\n this.courseEditor = courseEditor;\n this.selectors = {\n BULKCMCHECKBOX: `[data-bulkcheckbox][data-action='toggleSelectionCm']`,\n BULKSECTIONCHECKBOX: `[data-bulkcheckbox][data-action='toggleSelectionSection']`,\n CONTENT: `#region-main`,\n };\n }\n\n /**\n * Process a new selection.\n * @param {Number} id\n * @param {String} elementType cm or section\n * @param {Object} settings special selection settings\n * @param {Boolean} settings.all if the action is over all elements of the same type\n * @param {Boolean} settings.range if the action is over a range of elements\n */\n processNewSelection(id, elementType, settin
gs) {\n const value = !this._isBulkSelected(id, elementType);\n if (settings.all && settings.range) {\n this.switchCurrentSelection();\n return;\n }\n if (!this._isSelectable(id, elementType)) {\n return;\n }\n if (settings.all) {\n if (elementType == 'cm') {\n this._updateBulkCmSiblings(id, value);\n } else {\n this._updateBulkSelectionAll(elementType, value);\n }\n return;\n }\n if (settings.range) {\n this._updateBulkSelectionRange(id, elementType, value);\n return;\n }\n this._updateBulkSelection([id], elementType, value);\n }\n\n /**\n * Switch between section and cm selection.\n */\n switchCurrentSelection() {\n const bulk = this.courseEditor.get('bulk');\n if (bulk.selectedType === '' || bulk.selection.length == 0) {\n return;\n }\n const newSelectedT
ype = (bulk.selectedType === 'section') ? 'cm' : 'section';\n let newSelectedIds;\n if (bulk.selectedType === 'section') {\n newSelectedIds = this._getCmIdsFromSections(bulk.selection);\n } else {\n newSelectedIds = this._getSectionIdsFromCms(bulk.selection);\n }\n // Formats can display only a few activities of the section,\n // We need to select on the activities present in the page.\n const affectedIds = [];\n newSelectedIds.forEach(newId => {\n if (this._getSelector(newId, newSelectedType)) {\n affectedIds.push(newId);\n }\n });\n this.courseEditor.dispatch('bulkEnable', true);\n if (affectedIds.length != 0) {\n this._updateBulkSelection(affectedIds, newSelectedType, true);\n }\n }\n\n /**\n * Select all elements of the current type.\n * @param {Boolean} value the wanted selected value\n */\n selectAll(value) {\n const bulk =
this.courseEditor.get('bulk');\n if (bulk.selectedType == '') {\n return;\n }\n if (!value) {\n this.courseEditor.dispatch('bulkEnable', true);\n return;\n }\n const elementType = bulk.selectedType;\n this._updateBulkSelectionAll(elementType, value);\n }\n\n /**\n * Checks if all selectable elements are selected.\n * @returns {Boolean} true if all are selected\n */\n checkAllSelected() {\n const bulk = this.courseEditor.get('bulk');\n if (bulk.selectedType == '') {\n return false;\n }\n return this._getContentCheckboxes(bulk.selectedType).every(bulkSelect => {\n if (bulkSelect.disabled) {\n return true;\n }\n // Some sections may not be selectale for bulk actions.\n if (bulk.selectedType == 'section') {\n const section = this.courseEditor.get('section', bulkSelect.dataset.id);\n if (!sec
tion.bulkeditable) {\n return true;\n }\n }\n return bulk.selection.includes(bulkSelect.dataset.id);\n });\n }\n\n /**\n * Check if the id is part of the current bulk selection.\n * @private\n * @param {Number} id\n * @param {String} elementType\n * @returns {Boolean} if the element is present in the current selection.\n */\n _isBulkSelected(id, elementType) {\n const bulk = this.courseEditor.get('bulk');\n if (bulk.selectedType !== elementType) {\n return false;\n }\n return bulk.selection.includes(id);\n }\n\n /**\n * Update the current bulk selection removing or adding Ids.\n * @private\n * @param {Number[]} ids the user selected element id\n * @param {String} elementType cm or section\n * @param {Boolean} value the wanted selected value\n */\n _updateBulkSelection(ids, elementType, value) {\n let mutation = elementType;\n mut
ation += (value) ? 'Select' : 'Unselect';\n this.courseEditor.dispatch(mutation, ids);\n }\n\n /**\n * Get all content bulk selector checkboxes of one type (section/cm).\n * @private\n * @param {String} elementType section or cm\n * @returns {HTMLElement[]} an array with all checkboxes\n */\n _getContentCheckboxes(elementType) {\n const selector = (elementType == 'cm') ? this.selectors.BULKCMCHECKBOX : this.selectors.BULKSECTIONCHECKBOX;\n const checkboxes = document.querySelectorAll(`${this.selectors.CONTENT} ${selector}`);\n // Converting to array because NodeList has less iteration methods.\n return [...checkboxes];\n }\n\n /**\n * Validate if an element is selectable in the current page.\n * @private\n * @param {Number} id the user selected element id\n * @param {String} elementType cm or section\n * @return {Boolean}\n */\n _isSelectable(id, elementType) {\n const bulkSelect = this._getSelector(id, el
ementType);\n if (!bulkSelect || bulkSelect.disabled) {\n return false;\n }\n return true;\n }\n\n /**\n * Get as specific element checkbox.\n * @private\n * @param {Number} id\n * @param {String} elementType cm or section\n * @returns {HTMLElement|undefined}\n */\n _getSelector(id, elementType) {\n let selector = (elementType == 'cm') ? this.selectors.BULKCMCHECKBOX : this.selectors.BULKSECTIONCHECKBOX;\n selector += `[data-id='${id}']`;\n return document.querySelector(`${this.selectors.CONTENT} ${selector}`);\n }\n\n /**\n * Update the current bulk selection when a user uses shift to select a range.\n * @private\n * @param {Number} id the user selected element id\n * @param {String} elementType cm or section\n * @param {Boolean} value the wanted selected value\n */\n _updateBulkSelectionRange(id, elementType, value) {\n const bulk = this.courseEditor.get('bulk');\n let lastSe
lectedId = bulk.selection.at(-1);\n if (bulk.selectedType !== elementType || lastSelectedId == id) {\n this._updateBulkSelection([id], elementType, value);\n return;\n }\n const affectedIds = [];\n let found = 0;\n this._getContentCheckboxes(elementType).every(bulkSelect => {\n if (bulkSelect.disabled) {\n return true;\n }\n if (elementType == 'section') {\n const section = this.courseEditor.get('section', bulkSelect.dataset.id);\n if (value && !section?.bulkeditable) {\n return true;\n }\n }\n if (bulkSelect.dataset.id == id || bulkSelect.dataset.id == lastSelectedId) {\n found++;\n }\n if (found == 0) {\n return true;\n }\n affectedIds.push(bulkSelect.dataset.id);\n return found != 2;\n });\n this._updateBulkSelection(aff
ectedIds, elementType, value);\n }\n\n /**\n * Select or unselect all cm siblings.\n * @private\n * @param {Number} cmId the user selected element id\n * @param {Boolean} value the wanted selected value\n */\n _updateBulkCmSiblings(cmId, value) {\n const bulk = this.courseEditor.get('bulk');\n if (bulk.selectedType === 'section') {\n return;\n }\n const cm = this.courseEditor.get('cm', cmId);\n const section = this.courseEditor.get('section', cm.sectionid);\n // Formats can display only a few activities of the section,\n // We need to select on the activities selectable in the page.\n const affectedIds = [];\n section.cmlist.forEach(sectionCmId => {\n if (this._isSelectable(sectionCmId, 'cm')) {\n affectedIds.push(sectionCmId);\n }\n });\n this._updateBulkSelection(affectedIds, 'cm', value);\n }\n\n /**\n * Select or unselects al elements of the s
ame type.\n * @private\n * @param {String} elementType section or cm\n * @param {Boolean} value if the elements must be selected or unselected.\n */\n _updateBulkSelectionAll(elementType, value) {\n const affectedIds = [];\n this._getContentCheckboxes(elementType).forEach(bulkSelect => {\n if (bulkSelect.disabled) {\n return;\n }\n if (elementType == 'section') {\n const section = this.courseEditor.get('section', bulkSelect.dataset.id);\n if (value && !section?.bulkeditable) {\n return;\n }\n }\n affectedIds.push(bulkSelect.dataset.id);\n });\n this._updateBulkSelection(affectedIds, elementType, value);\n }\n\n /**\n * Get all cm ids from a specific section ids.\n * @private\n * @param {Number[]} sectionIds\n * @returns {Number[]} the cm ids\n */\n _getCmIdsFromSections(sectionIds) {\n const res
ult = [];\n sectionIds.forEach(sectionId => {\n const section = this.courseEditor.get('section', sectionId);\n result.push(...section.cmlist);\n });\n return result;\n }\n\n /**\n * Get all section ids containing a specific cm ids.\n * @private\n * @param {Number[]} cmIds\n * @returns {Number[]} the section ids\n */\n _getSectionIdsFromCms(cmIds) {\n const result = new Set();\n cmIds.forEach(cmId => {\n const cm = this.courseEditor.get('cm', cmId);\n if (cm.sectionnumber == 0) {\n return;\n }\n result.add(cm.sectionid);\n });\n return [...result];\n }\n}\n\n/**\n * Process a bulk selection toggle action.\n * @method\n * @param {CourseEditor} courseEditor\n * @param {HTMLElement} target the action element\n * @param {Event} event\n * @param {String} elementType cm or section\n */\nexport const toggleBulkSelectionAction = function(courseEditor, target
, event, elementType) {\n const id = target.dataset.id;\n if (!id) {\n return;\n }\n // When the action cames from a form element (checkbox) we should not preventDefault.\n // If we do it the changechecker module will execute the state change twice.\n if (target.dataset.preventDefault) {\n event.preventDefault();\n }\n // Using shift or alt key can produce text selection.\n document.getSelection().removeAllRanges();\n\n const bulkSelector = new BulkSelector(courseEditor);\n bulkSelector.processNewSelection(\n id,\n elementType,\n {\n range: event.shiftKey,\n all: event.altKey,\n }\n );\n};\n\n/**\n * Switch the current bulk selection.\n * @method\n * @param {CourseEditor} courseEditor\n */\nexport const switchBulkSelection = function(courseEditor) {\n const bulkSelector = new BulkSelector(courseEditor);\n bulkSelector.switchCurrentSelection();\n};\n\n/**\n * Select/unselect all element of the selected ty
pe.\n * @method\n * @param {CourseEditor} courseEditor\n * @param {Boolean} value if the elements must be selected or unselected.\n */\nexport const selectAllBulk = function(courseEditor, value) {\n const bulkSelector = new BulkSelector(courseEditor);\n bulkSelector.selectAll(value);\n};\n\n/**\n * Check if all possible elements are selected.\n * @method\n * @param {CourseEditor} courseEditor\n * @return {Boolean} if all elements of the current type are selected.\n */\nexport const checkAllBulkSelected = function(courseEditor) {\n const bulkSelector = new BulkSelector(courseEditor);\n return bulkSelector.checkAllSelected();\n};\n"],"names":["BulkSelector","constructor","courseEditor","selectors","BULKCMCHECKBOX","BULKSECTIONCHECKBOX","CONTENT","processNewSelection","id","elementType","settings","value","this","_isBulkSelected","all","range","switchCurrentSelection","_isSelectable","_updateBulkCmSiblings","_updateBulkSelectionAll","_updateBulkSelectionRange","_updateBulkSelection","bulk","get","se
lectedType","selection","length","newSelectedType","newSelectedIds","_getCmIdsFromSections","_getSectionIdsFromCms","affectedIds","forEach","newId","_getSelector","push","dispatch","selectAll","checkAllSelected","_getContentCheckboxes","every","bulkSelect","disabled","dataset","bulkeditable","includes","ids","mutation","selector","document","querySelectorAll","querySelector","lastSelectedId","at","found","section","cmId","cm","sectionid","cmlist","sectionCmId","sectionIds","result","sectionId","cmIds","Set","sectionnumber","add","target","event","preventDefault","getSelection","removeAllRanges","shiftKey","altKey"],"mappings":"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"}