diff --git a/grade/amd/build/edittree_index.min.js b/grade/amd/build/edittree_index.min.js index 93869e0b88a..6a88a01d04e 100644 --- a/grade/amd/build/edittree_index.min.js +++ b/grade/amd/build/edittree_index.min.js @@ -5,6 +5,6 @@ define("core_grades/edittree_index",["exports","core/localstorage","core/loading * @module core_grades/edittree_index * @copyright 2016 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_localstorage=_interopRequireDefault(_localstorage),_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending);const SELECTORS_CATEGORY_TOGGLE=".toggle-category",SELECTORS_GRADEBOOK_SETUP_TABLE=".setup-grades",SELECTORS_WEIGHT_OVERRIDE_CHECKBOX=".weightoverride",SELECTORS_BULK_MOVE_SELECT="#menumoveafter",SELECTORS_BULK_MOVE_INPUT="#bulkmoveinput",SELECTORS_GRADEBOOK_SETUP_WRAPPER=".gradetree-wrapper",SELECTORS_GRADEBOOK_SETUP_BOX=".gradetreebox",toggleWeightInput=weightOverrideCheckbox=>{const row=weightOverrideCheckbox.closest("tr"),itemId=row.dataset.itemid;row.querySelector('input[name="weight_'.concat(itemId,'"]')).disabled=!weightOverrideCheckbox.checked},submitBulkMoveForm=bulkMoveSelect=>{const form=bulkMoveSelect.closest("form");form.querySelector(SELECTORS_BULK_MOVE_INPUT).value=1,form.submit()},toggleCategory=(toggleElement,courseId,userId,storeCollapsedState)=>{const target=toggleElement.dataset.target,category=toggleElement.dataset.category,isCollapsing="true"===toggleElement.getAttribute("aria-expanded"),gradebookSetup=toggleElement.closest(SELECTORS_GRADEBOOK_SETUP_TABLE),targetRows=gradebookSetup.querySelectorAll(target),maxGradeCell=toggleElement.closest("tr").querySelector(".column-range");if(isCollapsing){if(toggleElement.setAttribute("aria-expanded","false"),toggleElement.dataset.target="[data-hidden-by='".concat(category,"']"),maxGradeCell){const relatedCategoryAggregationRow=gradebookSetup.querySelector("[data-aggregationforcategory='".concat(category,"']"));maxGradeCell.innerHTML=relatedCategoryAggregationRow.querySelector(".column-range").innerHTML}}else toggleElement.setAttribute("aria-expanded","true"),toggleElement.dataset.target=".".concat(category,"[data-hidden='false']"),maxGradeCell&&(maxGradeCell.innerHTML="");storeCollapsedState&&((category,courseId,userId,isCollapsing)=>{const currentStoredCollapsedCategories=_localstorage.default.get("core_grade_collapsedgradecategories_".concat(courseId,"_").concat(userId));let collapsedCategories=currentStoredCollapsedCategories?JSON.parse(currentStoredCollapsedCategories):[];isCollapsing?collapsedCategories.push(category):collapsedCategories=collapsedCategories.filter((cat=>cat!==category)),_localstorage.default.set("core_grade_collapsedgradecategories_".concat(courseId,"_").concat(userId),JSON.stringify(collapsedCategories))})(category,courseId,userId,isCollapsing),targetRows.forEach((row=>{isCollapsing?(row.dataset.hidden="true",row.dataset.hiddenBy=category):(row.dataset.hidden="false",row.dataset.hiddenBy="")})),updateParentCategoryRowspans(toggleElement,targetRows.length)},updateParentCategoryRowspans=(toggleElement,num)=>{const gradebookSetup=toggleElement.closest(SELECTORS_GRADEBOOK_SETUP_TABLE);toggleElement.closest("tr").classList.forEach((className=>{const parentCategoryToggleElement=gradebookSetup.querySelector('[data-target=".'.concat(className,"[data-hidden='false']\""));if(parentCategoryToggleElement){const categoryRowSpanElement=parentCategoryToggleElement.closest("tr").nextElementSibling.querySelector("[rowspan]");"true"===toggleElement.getAttribute("aria-expanded")?categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan+num:categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan-num}}))};_exports.init=(courseId,userId)=>{const pendingPromise=new _pending.default,gradebookSetupBox=document.querySelector(SELECTORS_GRADEBOOK_SETUP_BOX);(0,_loadingicon.addIconToContainer)(gradebookSetupBox).then((loader=>{setTimeout((()=>{((courseId,userId)=>{const gradebookSetup=document.querySelector(SELECTORS_GRADEBOOK_SETUP_TABLE),storedCollapsedCategories=_localstorage.default.get("core_grade_collapsedgradecategories_".concat(courseId,"_").concat(userId));storedCollapsedCategories&&JSON.parse(storedCollapsedCategories).forEach((category=>{const categoryToggleElement=gradebookSetup.querySelector("".concat(SELECTORS_CATEGORY_TOGGLE,'[data-category="').concat(category,'"'));categoryToggleElement&&toggleCategory(categoryToggleElement,courseId,userId,!1)}))})(courseId,userId),loader.remove(),document.querySelector(SELECTORS_GRADEBOOK_SETUP_WRAPPER).classList.remove("d-none"),pendingPromise.resolve()}),150)})).fail(_notification.default.exception),((courseId,userId)=>{document.addEventListener("change",(e=>{e.target.matches(SELECTORS_WEIGHT_OVERRIDE_CHECKBOX)&&toggleWeightInput(e.target),e.target.matches(SELECTORS_BULK_MOVE_SELECT)&&submitBulkMoveForm(e.target)})),document.querySelector(SELECTORS_GRADEBOOK_SETUP_TABLE).addEventListener("click",(e=>{const toggle=e.target.closest(SELECTORS_CATEGORY_TOGGLE);toggle&&toggleCategory(toggle,courseId,userId,!0)}))})(courseId,userId)}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_localstorage=_interopRequireDefault(_localstorage),_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending);const SELECTORS_CATEGORY_TOGGLE=".toggle-category",SELECTORS_GRADEBOOK_SETUP_TABLE=".setup-grades",SELECTORS_WEIGHT_OVERRIDE_CHECKBOX=".weightoverride",SELECTORS_BULK_MOVE_SELECT="#menumoveafter",SELECTORS_BULK_MOVE_INPUT="#bulkmoveinput",SELECTORS_GRADEBOOK_SETUP_WRAPPER=".gradetree-wrapper",SELECTORS_GRADEBOOK_SETUP_BOX=".gradetreebox",toggleWeightInput=weightOverrideCheckbox=>{const row=weightOverrideCheckbox.closest("tr"),itemId=row.dataset.itemid;row.querySelector('input[name="weight_'.concat(itemId,'"]')).disabled=!weightOverrideCheckbox.checked},submitBulkMoveForm=bulkMoveSelect=>{const form=bulkMoveSelect.closest("form");form.querySelector(SELECTORS_BULK_MOVE_INPUT).value=1,form.submit()},toggleCategory=(toggleElement,courseId,userId,storeCollapsedState)=>{const target=toggleElement.dataset.target,category=toggleElement.dataset.category,isCollapsing="true"===toggleElement.getAttribute("aria-expanded"),gradebookSetup=toggleElement.closest(SELECTORS_GRADEBOOK_SETUP_TABLE),targetRows=gradebookSetup.querySelectorAll(target),maxGradeCell=toggleElement.closest("tr").querySelector(".column-range");if(isCollapsing){if(toggleElement.setAttribute("aria-expanded","false"),toggleElement.dataset.target="[data-hidden-by='".concat(category,"']"),maxGradeCell){const relatedCategoryAggregationRow=gradebookSetup.querySelector("[data-aggregationforcategory='".concat(category,"']"));maxGradeCell.innerHTML=relatedCategoryAggregationRow.querySelector(".column-range").innerHTML}}else toggleElement.setAttribute("aria-expanded","true"),toggleElement.dataset.target=".".concat(category,"[data-hidden='false']"),maxGradeCell&&(maxGradeCell.innerHTML="");storeCollapsedState&&((category,courseId,userId,isCollapsing)=>{const currentStoredCollapsedCategories=_localstorage.default.get("core_grade_collapsedgradecategories_".concat(courseId,"_").concat(userId));let collapsedCategories=currentStoredCollapsedCategories?JSON.parse(currentStoredCollapsedCategories):[];isCollapsing?collapsedCategories.push(category):collapsedCategories=collapsedCategories.filter((cat=>cat!==category)),_localstorage.default.set("core_grade_collapsedgradecategories_".concat(courseId,"_").concat(userId),JSON.stringify(collapsedCategories))})(category,courseId,userId,isCollapsing),targetRows.forEach((row=>{isCollapsing?(row.dataset.hidden="true",row.dataset.hiddenBy=category):(row.dataset.hidden="false",row.dataset.hiddenBy="")})),updateParentCategoryRowspans(toggleElement,targetRows.length)},updateParentCategoryRowspans=(toggleElement,num)=>{const gradebookSetup=toggleElement.closest(SELECTORS_GRADEBOOK_SETUP_TABLE);toggleElement.closest("tr").classList.forEach((className=>{const parentCategoryToggleElement=gradebookSetup.querySelector('[data-target=".'.concat(className,"[data-hidden='false']\""));if(parentCategoryToggleElement){const categoryRowSpanElement=parentCategoryToggleElement.closest("tr").nextElementSibling.querySelector("[rowspan]");"true"===toggleElement.getAttribute("aria-expanded")?categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan+num:categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan-num}}))};_exports.init=(courseId,userId)=>{const pendingPromise=new _pending.default,gradebookSetupBox=document.querySelector(SELECTORS_GRADEBOOK_SETUP_BOX);(0,_loadingicon.addIconToContainer)(gradebookSetupBox).then((loader=>{setTimeout((()=>{((courseId,userId)=>{const gradebookSetup=document.querySelector(SELECTORS_GRADEBOOK_SETUP_TABLE),storedCollapsedCategories=_localstorage.default.get("core_grade_collapsedgradecategories_".concat(courseId,"_").concat(userId));storedCollapsedCategories&&JSON.parse(storedCollapsedCategories).forEach((category=>{const categoryToggleElement=gradebookSetup.querySelector("".concat(SELECTORS_CATEGORY_TOGGLE,'[data-category="').concat(category,'"'));categoryToggleElement&&toggleCategory(categoryToggleElement,courseId,userId,!1)}))})(courseId,userId),loader.remove(),document.querySelector(SELECTORS_GRADEBOOK_SETUP_WRAPPER).classList.remove("d-none"),pendingPromise.resolve()}),150)})).fail(_notification.default.exception),((courseId,userId)=>{document.addEventListener("change",(e=>{e.target.matches(SELECTORS_WEIGHT_OVERRIDE_CHECKBOX)&&toggleWeightInput(e.target),e.target.matches(SELECTORS_BULK_MOVE_SELECT)&&submitBulkMoveForm(e.target)})),document.querySelector(SELECTORS_GRADEBOOK_SETUP_TABLE).addEventListener("click",(e=>{const toggle=e.target.closest(SELECTORS_CATEGORY_TOGGLE);toggle&&(e.preventDefault(),toggleCategory(toggle,courseId,userId,!0))}))})(courseId,userId)}})); //# sourceMappingURL=edittree_index.min.js.map \ No newline at end of file diff --git a/grade/amd/build/edittree_index.min.js.map b/grade/amd/build/edittree_index.min.js.map index a38559f4bcb..6bc37fccfbe 100644 --- a/grade/amd/build/edittree_index.min.js.map +++ b/grade/amd/build/edittree_index.min.js.map @@ -1 +1 @@ -{"version":3,"file":"edittree_index.min.js","sources":["../src/edittree_index.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 * Enhance the gradebook tree setup with various facilities.\n *\n * @module core_grades/edittree_index\n * @copyright 2016 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport storage from 'core/localstorage';\nimport {addIconToContainer} from 'core/loadingicon';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\n\nconst SELECTORS = {\n CATEGORY_TOGGLE: '.toggle-category',\n GRADEBOOK_SETUP_TABLE: '.setup-grades',\n WEIGHT_OVERRIDE_CHECKBOX: '.weightoverride',\n BULK_MOVE_SELECT: '#menumoveafter',\n BULK_MOVE_INPUT: '#bulkmoveinput',\n GRADEBOOK_SETUP_WRAPPER: '.gradetree-wrapper',\n GRADEBOOK_SETUP_BOX: '.gradetreebox'\n};\n\n/**\n * Register related event listeners.\n *\n * @method registerListenerEvents\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n */\nconst registerListenerEvents = (courseId, userId) => {\n\n document.addEventListener('change', e => {\n // Toggle the availability of the weight input field based on the changed state (checked/unchecked) of the\n // related checkbox element.\n if (e.target.matches(SELECTORS.WEIGHT_OVERRIDE_CHECKBOX)) {\n toggleWeightInput(e.target);\n }\n // Submit the bulk move form when the selected option in the bulk move select element has been changed.\n if (e.target.matches(SELECTORS.BULK_MOVE_SELECT)) {\n submitBulkMoveForm(e.target);\n }\n });\n\n const gradebookSetup = document.querySelector(SELECTORS.GRADEBOOK_SETUP_TABLE);\n gradebookSetup.addEventListener('click', e => {\n const toggle = e.target.closest(SELECTORS.CATEGORY_TOGGLE);\n // Collapse or expand the grade category when the visibility toggle button is activated.\n if (toggle) {\n toggleCategory(toggle, courseId, userId, true);\n }\n });\n};\n\n/**\n * Toggle the weight input field based on its checkbox.\n *\n * @method toggleWeightInput\n * @param {object} weightOverrideCheckbox The weight override checkbox element.\n */\nconst toggleWeightInput = (weightOverrideCheckbox) => {\n const row = weightOverrideCheckbox.closest('tr');\n const itemId = row.dataset.itemid;\n const weightOverrideInput = row.querySelector(`input[name=\"weight_${itemId}\"]`);\n weightOverrideInput.disabled = !weightOverrideCheckbox.checked;\n};\n\n/**\n * Submit the bulk move form.\n *\n * @method toggleWeightInput\n * @param {object} bulkMoveSelect The bulk move select element.\n */\nconst submitBulkMoveForm = (bulkMoveSelect) => {\n const form = bulkMoveSelect.closest('form');\n const bulkMoveInput = form.querySelector(SELECTORS.BULK_MOVE_INPUT);\n bulkMoveInput.value = 1;\n form.submit();\n};\n\n/**\n * Method that collapses all relevant grade categories based on the locally stored state of collapsed grade categories\n * for a given user.\n *\n * @method collapseGradeCategories\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n */\nconst collapseGradeCategories = (courseId, userId) => {\n const gradebookSetup = document.querySelector(SELECTORS.GRADEBOOK_SETUP_TABLE);\n const storedCollapsedCategories = storage.get(`core_grade_collapsedgradecategories_${courseId}_${userId}`);\n\n if (storedCollapsedCategories) {\n // Fetch all grade categories that are locally stored as collapsed and re-apply the collapse action.\n const collapsedCategories = JSON.parse(storedCollapsedCategories);\n\n collapsedCategories.forEach((category) => {\n const categoryToggleElement =\n gradebookSetup.querySelector(`${SELECTORS.CATEGORY_TOGGLE}[data-category=\"${category}\"`);\n if (categoryToggleElement) {\n toggleCategory(categoryToggleElement, courseId, userId, false);\n }\n });\n }\n};\n\n/**\n * Method that updates the locally stored state of collapsed grade categories based on a performed toggle action on a\n * given grade category.\n *\n * @method updateCollapsedCategoriesStoredState\n * @param {string} category The category to be added or removed from the collapsed grade categories local storage.\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n * @param {boolean} isCollapsing Whether the category is being collapsed or not.\n */\nconst updateCollapsedCategoriesStoredState = (category, courseId, userId, isCollapsing) => {\n const currentStoredCollapsedCategories = storage.get(`core_grade_collapsedgradecategories_${courseId}_${userId}`);\n let collapsedCategories = currentStoredCollapsedCategories ?\n JSON.parse(currentStoredCollapsedCategories) : [];\n\n if (isCollapsing) {\n collapsedCategories.push(category);\n } else {\n collapsedCategories = collapsedCategories.filter(cat => cat !== category);\n }\n storage.set(`core_grade_collapsedgradecategories_${courseId}_${userId}`, JSON.stringify(collapsedCategories));\n};\n\n/**\n * Method that handles the grade category toggle action.\n *\n * @method toggleCategory\n * @param {object} toggleElement The category toggle node that was clicked.\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n * @param {boolean} storeCollapsedState Whether to store (local storage) the state of collapsed grade categories.\n */\nconst toggleCategory = (toggleElement, courseId, userId, storeCollapsedState) => {\n const target = toggleElement.dataset.target;\n const category = toggleElement.dataset.category;\n // Whether the toggle action is collapsing the category or not.\n const isCollapsing = toggleElement.getAttribute('aria-expanded') === \"true\";\n const gradebookSetup = toggleElement.closest(SELECTORS.GRADEBOOK_SETUP_TABLE);\n // Find all targeted 'children' rows of the toggled category.\n const targetRows = gradebookSetup.querySelectorAll(target);\n // Find the maximum grade cell in the grade category that is being collapsed/expanded.\n const toggleElementRow = toggleElement.closest('tr');\n const maxGradeCell = toggleElementRow.querySelector('.column-range');\n\n if (isCollapsing) {\n toggleElement.setAttribute('aria-expanded', 'false');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to expand this category we only target rows which have been hidden by this category toggle action.\n toggleElement.dataset.target = `[data-hidden-by='${category}']`;\n if (maxGradeCell) {\n const relatedCategoryAggregationRow = gradebookSetup.querySelector(`[data-aggregationforcategory='${category}']`);\n maxGradeCell.innerHTML = relatedCategoryAggregationRow.querySelector('.column-range').innerHTML;\n }\n } else {\n toggleElement.setAttribute('aria-expanded', 'true');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to collapse this category we only target rows which are children of this category and are not currently hidden.\n toggleElement.dataset.target = `.${category}[data-hidden='false']`;\n if (maxGradeCell) {\n maxGradeCell.innerHTML = '';\n }\n }\n // If explicitly instructed, update accordingly the locally stored state of collapsed categories based on the\n // toggle action performed on the given grade category.\n if (storeCollapsedState) {\n updateCollapsedCategoriesStoredState(category, courseId, userId, isCollapsing);\n }\n\n // Loop through all targeted child row elements and update the required data attributes to either hide or show\n // them depending on the toggle action (collapsing or expanding).\n targetRows.forEach((row) => {\n if (isCollapsing) {\n row.dataset.hidden = 'true';\n row.dataset.hiddenBy = category;\n } else {\n row.dataset.hidden = 'false';\n row.dataset.hiddenBy = '';\n }\n });\n\n // Since the user report is presented in an HTML table, rowspans are used under each category to create a visual\n // hierarchy between categories and grading items. When expanding or collapsing a category we need to also update\n // (subtract or add) the rowspan values associated to each parent category row to preserve the correct visual\n // hierarchy in the table.\n updateParentCategoryRowspans(toggleElement, targetRows.length);\n};\n\n/**\n * Method that updates the rowspan value of all 'parent' category rows of a given category node.\n *\n * @method updateParentCategoryRowspans\n * @param {object} toggleElement The category toggle node that was clicked.\n * @param {int} num The number we want to add or subtract from the rowspan value of the 'parent' category row elements.\n */\nconst updateParentCategoryRowspans = (toggleElement, num) => {\n const gradebookSetup = toggleElement.closest(SELECTORS.GRADEBOOK_SETUP_TABLE);\n // Get the row element which contains the category toggle node.\n const rowElement = toggleElement.closest('tr');\n\n // Loop through the class list of the toggle category row element.\n // The list contains classes which identify all parent categories of the toggled category.\n rowElement.classList.forEach((className) => {\n // Find the toggle node of the 'parent' category that is identified by the given class name.\n const parentCategoryToggleElement = gradebookSetup.querySelector(`[data-target=\".${className}[data-hidden='false']\"`);\n if (parentCategoryToggleElement) {\n // Get the row element which contains the parent category toggle node.\n const categoryRowElement = parentCategoryToggleElement.closest('tr');\n // Find the rowspan element associated to this parent category.\n const categoryRowSpanElement = categoryRowElement.nextElementSibling.querySelector('[rowspan]');\n\n // Depending on whether the toggle action has expanded or collapsed the category, either add or\n // subtract from the 'parent' category rowspan.\n if (toggleElement.getAttribute('aria-expanded') === \"true\") {\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan + num;\n } else { // The category has been collapsed.\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan - num;\n }\n }\n });\n};\n\n/**\n * Initialize module.\n *\n * @method init\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n */\nexport const init = (courseId, userId) => {\n const pendingPromise = new Pending();\n const gradebookSetupBox = document.querySelector(SELECTORS.GRADEBOOK_SETUP_BOX);\n // Display a loader while the relevant grade categories are being re-collapsed on page load (based on the locally\n // stored state for the given user).\n addIconToContainer(gradebookSetupBox).then((loader) => {\n setTimeout(() => {\n collapseGradeCategories(courseId, userId);\n // Once the grade categories have been re-collapsed, remove the loader and display the Gradebook setup content.\n loader.remove();\n document.querySelector(SELECTORS.GRADEBOOK_SETUP_WRAPPER).classList.remove('d-none');\n pendingPromise.resolve();\n }, 150);\n return;\n }).fail(Notification.exception);\n\n registerListenerEvents(courseId, userId);\n};\n"],"names":["SELECTORS","toggleWeightInput","weightOverrideCheckbox","row","closest","itemId","dataset","itemid","querySelector","disabled","checked","submitBulkMoveForm","bulkMoveSelect","form","value","submit","toggleCategory","toggleElement","courseId","userId","storeCollapsedState","target","category","isCollapsing","getAttribute","gradebookSetup","targetRows","querySelectorAll","maxGradeCell","setAttribute","relatedCategoryAggregationRow","innerHTML","currentStoredCollapsedCategories","storage","get","collapsedCategories","JSON","parse","push","filter","cat","set","stringify","updateCollapsedCategoriesStoredState","forEach","hidden","hiddenBy","updateParentCategoryRowspans","length","num","classList","className","parentCategoryToggleElement","categoryRowSpanElement","nextElementSibling","rowSpan","pendingPromise","Pending","gradebookSetupBox","document","then","loader","setTimeout","storedCollapsedCategories","categoryToggleElement","collapseGradeCategories","remove","resolve","fail","Notification","exception","addEventListener","e","matches","toggle","registerListenerEvents"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"edittree_index.min.js","sources":["../src/edittree_index.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 * Enhance the gradebook tree setup with various facilities.\n *\n * @module core_grades/edittree_index\n * @copyright 2016 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport storage from 'core/localstorage';\nimport {addIconToContainer} from 'core/loadingicon';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\n\nconst SELECTORS = {\n CATEGORY_TOGGLE: '.toggle-category',\n GRADEBOOK_SETUP_TABLE: '.setup-grades',\n WEIGHT_OVERRIDE_CHECKBOX: '.weightoverride',\n BULK_MOVE_SELECT: '#menumoveafter',\n BULK_MOVE_INPUT: '#bulkmoveinput',\n GRADEBOOK_SETUP_WRAPPER: '.gradetree-wrapper',\n GRADEBOOK_SETUP_BOX: '.gradetreebox'\n};\n\n/**\n * Register related event listeners.\n *\n * @method registerListenerEvents\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n */\nconst registerListenerEvents = (courseId, userId) => {\n\n document.addEventListener('change', e => {\n // Toggle the availability of the weight input field based on the changed state (checked/unchecked) of the\n // related checkbox element.\n if (e.target.matches(SELECTORS.WEIGHT_OVERRIDE_CHECKBOX)) {\n toggleWeightInput(e.target);\n }\n // Submit the bulk move form when the selected option in the bulk move select element has been changed.\n if (e.target.matches(SELECTORS.BULK_MOVE_SELECT)) {\n submitBulkMoveForm(e.target);\n }\n });\n\n const gradebookSetup = document.querySelector(SELECTORS.GRADEBOOK_SETUP_TABLE);\n gradebookSetup.addEventListener('click', e => {\n const toggle = e.target.closest(SELECTORS.CATEGORY_TOGGLE);\n // Collapse or expand the grade category when the visibility toggle button is activated.\n if (toggle) {\n e.preventDefault();\n toggleCategory(toggle, courseId, userId, true);\n }\n });\n};\n\n/**\n * Toggle the weight input field based on its checkbox.\n *\n * @method toggleWeightInput\n * @param {object} weightOverrideCheckbox The weight override checkbox element.\n */\nconst toggleWeightInput = (weightOverrideCheckbox) => {\n const row = weightOverrideCheckbox.closest('tr');\n const itemId = row.dataset.itemid;\n const weightOverrideInput = row.querySelector(`input[name=\"weight_${itemId}\"]`);\n weightOverrideInput.disabled = !weightOverrideCheckbox.checked;\n};\n\n/**\n * Submit the bulk move form.\n *\n * @method toggleWeightInput\n * @param {object} bulkMoveSelect The bulk move select element.\n */\nconst submitBulkMoveForm = (bulkMoveSelect) => {\n const form = bulkMoveSelect.closest('form');\n const bulkMoveInput = form.querySelector(SELECTORS.BULK_MOVE_INPUT);\n bulkMoveInput.value = 1;\n form.submit();\n};\n\n/**\n * Method that collapses all relevant grade categories based on the locally stored state of collapsed grade categories\n * for a given user.\n *\n * @method collapseGradeCategories\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n */\nconst collapseGradeCategories = (courseId, userId) => {\n const gradebookSetup = document.querySelector(SELECTORS.GRADEBOOK_SETUP_TABLE);\n const storedCollapsedCategories = storage.get(`core_grade_collapsedgradecategories_${courseId}_${userId}`);\n\n if (storedCollapsedCategories) {\n // Fetch all grade categories that are locally stored as collapsed and re-apply the collapse action.\n const collapsedCategories = JSON.parse(storedCollapsedCategories);\n\n collapsedCategories.forEach((category) => {\n const categoryToggleElement =\n gradebookSetup.querySelector(`${SELECTORS.CATEGORY_TOGGLE}[data-category=\"${category}\"`);\n if (categoryToggleElement) {\n toggleCategory(categoryToggleElement, courseId, userId, false);\n }\n });\n }\n};\n\n/**\n * Method that updates the locally stored state of collapsed grade categories based on a performed toggle action on a\n * given grade category.\n *\n * @method updateCollapsedCategoriesStoredState\n * @param {string} category The category to be added or removed from the collapsed grade categories local storage.\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n * @param {boolean} isCollapsing Whether the category is being collapsed or not.\n */\nconst updateCollapsedCategoriesStoredState = (category, courseId, userId, isCollapsing) => {\n const currentStoredCollapsedCategories = storage.get(`core_grade_collapsedgradecategories_${courseId}_${userId}`);\n let collapsedCategories = currentStoredCollapsedCategories ?\n JSON.parse(currentStoredCollapsedCategories) : [];\n\n if (isCollapsing) {\n collapsedCategories.push(category);\n } else {\n collapsedCategories = collapsedCategories.filter(cat => cat !== category);\n }\n storage.set(`core_grade_collapsedgradecategories_${courseId}_${userId}`, JSON.stringify(collapsedCategories));\n};\n\n/**\n * Method that handles the grade category toggle action.\n *\n * @method toggleCategory\n * @param {object} toggleElement The category toggle node that was clicked.\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n * @param {boolean} storeCollapsedState Whether to store (local storage) the state of collapsed grade categories.\n */\nconst toggleCategory = (toggleElement, courseId, userId, storeCollapsedState) => {\n const target = toggleElement.dataset.target;\n const category = toggleElement.dataset.category;\n // Whether the toggle action is collapsing the category or not.\n const isCollapsing = toggleElement.getAttribute('aria-expanded') === \"true\";\n const gradebookSetup = toggleElement.closest(SELECTORS.GRADEBOOK_SETUP_TABLE);\n // Find all targeted 'children' rows of the toggled category.\n const targetRows = gradebookSetup.querySelectorAll(target);\n // Find the maximum grade cell in the grade category that is being collapsed/expanded.\n const toggleElementRow = toggleElement.closest('tr');\n const maxGradeCell = toggleElementRow.querySelector('.column-range');\n\n if (isCollapsing) {\n toggleElement.setAttribute('aria-expanded', 'false');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to expand this category we only target rows which have been hidden by this category toggle action.\n toggleElement.dataset.target = `[data-hidden-by='${category}']`;\n if (maxGradeCell) {\n const relatedCategoryAggregationRow = gradebookSetup.querySelector(`[data-aggregationforcategory='${category}']`);\n maxGradeCell.innerHTML = relatedCategoryAggregationRow.querySelector('.column-range').innerHTML;\n }\n } else {\n toggleElement.setAttribute('aria-expanded', 'true');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to collapse this category we only target rows which are children of this category and are not currently hidden.\n toggleElement.dataset.target = `.${category}[data-hidden='false']`;\n if (maxGradeCell) {\n maxGradeCell.innerHTML = '';\n }\n }\n // If explicitly instructed, update accordingly the locally stored state of collapsed categories based on the\n // toggle action performed on the given grade category.\n if (storeCollapsedState) {\n updateCollapsedCategoriesStoredState(category, courseId, userId, isCollapsing);\n }\n\n // Loop through all targeted child row elements and update the required data attributes to either hide or show\n // them depending on the toggle action (collapsing or expanding).\n targetRows.forEach((row) => {\n if (isCollapsing) {\n row.dataset.hidden = 'true';\n row.dataset.hiddenBy = category;\n } else {\n row.dataset.hidden = 'false';\n row.dataset.hiddenBy = '';\n }\n });\n\n // Since the user report is presented in an HTML table, rowspans are used under each category to create a visual\n // hierarchy between categories and grading items. When expanding or collapsing a category we need to also update\n // (subtract or add) the rowspan values associated to each parent category row to preserve the correct visual\n // hierarchy in the table.\n updateParentCategoryRowspans(toggleElement, targetRows.length);\n};\n\n/**\n * Method that updates the rowspan value of all 'parent' category rows of a given category node.\n *\n * @method updateParentCategoryRowspans\n * @param {object} toggleElement The category toggle node that was clicked.\n * @param {int} num The number we want to add or subtract from the rowspan value of the 'parent' category row elements.\n */\nconst updateParentCategoryRowspans = (toggleElement, num) => {\n const gradebookSetup = toggleElement.closest(SELECTORS.GRADEBOOK_SETUP_TABLE);\n // Get the row element which contains the category toggle node.\n const rowElement = toggleElement.closest('tr');\n\n // Loop through the class list of the toggle category row element.\n // The list contains classes which identify all parent categories of the toggled category.\n rowElement.classList.forEach((className) => {\n // Find the toggle node of the 'parent' category that is identified by the given class name.\n const parentCategoryToggleElement = gradebookSetup.querySelector(`[data-target=\".${className}[data-hidden='false']\"`);\n if (parentCategoryToggleElement) {\n // Get the row element which contains the parent category toggle node.\n const categoryRowElement = parentCategoryToggleElement.closest('tr');\n // Find the rowspan element associated to this parent category.\n const categoryRowSpanElement = categoryRowElement.nextElementSibling.querySelector('[rowspan]');\n\n // Depending on whether the toggle action has expanded or collapsed the category, either add or\n // subtract from the 'parent' category rowspan.\n if (toggleElement.getAttribute('aria-expanded') === \"true\") {\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan + num;\n } else { // The category has been collapsed.\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan - num;\n }\n }\n });\n};\n\n/**\n * Initialize module.\n *\n * @method init\n * @param {int} courseId The ID of course.\n * @param {int} userId The ID of the current logged user.\n */\nexport const init = (courseId, userId) => {\n const pendingPromise = new Pending();\n const gradebookSetupBox = document.querySelector(SELECTORS.GRADEBOOK_SETUP_BOX);\n // Display a loader while the relevant grade categories are being re-collapsed on page load (based on the locally\n // stored state for the given user).\n addIconToContainer(gradebookSetupBox).then((loader) => {\n setTimeout(() => {\n collapseGradeCategories(courseId, userId);\n // Once the grade categories have been re-collapsed, remove the loader and display the Gradebook setup content.\n loader.remove();\n document.querySelector(SELECTORS.GRADEBOOK_SETUP_WRAPPER).classList.remove('d-none');\n pendingPromise.resolve();\n }, 150);\n return;\n }).fail(Notification.exception);\n\n registerListenerEvents(courseId, userId);\n};\n"],"names":["SELECTORS","toggleWeightInput","weightOverrideCheckbox","row","closest","itemId","dataset","itemid","querySelector","disabled","checked","submitBulkMoveForm","bulkMoveSelect","form","value","submit","toggleCategory","toggleElement","courseId","userId","storeCollapsedState","target","category","isCollapsing","getAttribute","gradebookSetup","targetRows","querySelectorAll","maxGradeCell","setAttribute","relatedCategoryAggregationRow","innerHTML","currentStoredCollapsedCategories","storage","get","collapsedCategories","JSON","parse","push","filter","cat","set","stringify","updateCollapsedCategoriesStoredState","forEach","hidden","hiddenBy","updateParentCategoryRowspans","length","num","classList","className","parentCategoryToggleElement","categoryRowSpanElement","nextElementSibling","rowSpan","pendingPromise","Pending","gradebookSetupBox","document","then","loader","setTimeout","storedCollapsedCategories","categoryToggleElement","collapseGradeCategories","remove","resolve","fail","Notification","exception","addEventListener","e","matches","toggle","preventDefault","registerListenerEvents"],"mappings":"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"} \ No newline at end of file diff --git a/grade/amd/src/edittree_index.js b/grade/amd/src/edittree_index.js index 16f1566e7b4..4745a6718d0 100644 --- a/grade/amd/src/edittree_index.js +++ b/grade/amd/src/edittree_index.js @@ -62,6 +62,7 @@ const registerListenerEvents = (courseId, userId) => { const toggle = e.target.closest(SELECTORS.CATEGORY_TOGGLE); // Collapse or expand the grade category when the visibility toggle button is activated. if (toggle) { + e.preventDefault(); toggleCategory(toggle, courseId, userId, true); } }); diff --git a/grade/report/user/amd/build/gradecategorytoggle.min.js b/grade/report/user/amd/build/gradecategorytoggle.min.js index d3c76913e22..1a2b3cddf57 100644 --- a/grade/report/user/amd/build/gradecategorytoggle.min.js +++ b/grade/report/user/amd/build/gradecategorytoggle.min.js @@ -6,6 +6,6 @@ define("gradereport_user/gradecategorytoggle",["exports"],(function(_exports){Ob * @copyright 2022 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const SELECTORS_CATEGORY_TOGGLE=".toggle-category",SELECTORS_USER_REPORT_TABLE=".user-grade",toggleCategory=toggleElement=>{const target=toggleElement.dataset.target,categoryId=toggleElement.dataset.categoryid,isCollapsing="true"===toggleElement.getAttribute("aria-expanded"),targetRows=toggleElement.closest(SELECTORS_USER_REPORT_TABLE).querySelectorAll(target);isCollapsing?(toggleElement.setAttribute("aria-expanded","false"),toggleElement.dataset.target="[data-hidden-by='".concat(categoryId,"']")):(toggleElement.setAttribute("aria-expanded","true"),toggleElement.dataset.target=".cat_".concat(categoryId,"[data-hidden='false']")),targetRows.forEach((row=>{isCollapsing?(row.dataset.hidden="true",row.dataset.hiddenBy=categoryId):(row.dataset.hidden="false",row.dataset.hiddenBy="")})),updateParentCategoryRowspans(toggleElement,targetRows.length)},updateParentCategoryRowspans=(toggleElement,num)=>{const userReport=toggleElement.closest(SELECTORS_USER_REPORT_TABLE);toggleElement.closest("tr").classList.forEach((className=>{const parentCategoryToggleElement=userReport.querySelector('[data-target=".'.concat(className,"[data-hidden='false']\""));if(parentCategoryToggleElement){const categoryRowSpanElement=parentCategoryToggleElement.closest("tr").nextElementSibling.querySelector("[rowspan]");"true"===toggleElement.getAttribute("aria-expanded")?categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan+num:categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan-num}}))};_exports.init=userReportId=>{(userReportId=>{document.querySelector("#"+userReportId).querySelector(SELECTORS_USER_REPORT_TABLE).addEventListener("click",(e=>{const toggle=e.target.closest(SELECTORS_CATEGORY_TOGGLE);toggle&&toggleCategory(toggle)}))})(userReportId)}})); +const SELECTORS_CATEGORY_TOGGLE=".toggle-category",SELECTORS_USER_REPORT_TABLE=".user-grade",toggleCategory=toggleElement=>{const target=toggleElement.dataset.target,categoryId=toggleElement.dataset.categoryid,isCollapsing="true"===toggleElement.getAttribute("aria-expanded"),targetRows=toggleElement.closest(SELECTORS_USER_REPORT_TABLE).querySelectorAll(target);isCollapsing?(toggleElement.setAttribute("aria-expanded","false"),toggleElement.dataset.target="[data-hidden-by='".concat(categoryId,"']")):(toggleElement.setAttribute("aria-expanded","true"),toggleElement.dataset.target=".cat_".concat(categoryId,"[data-hidden='false']")),targetRows.forEach((row=>{isCollapsing?(row.dataset.hidden="true",row.dataset.hiddenBy=categoryId):(row.dataset.hidden="false",row.dataset.hiddenBy="")})),updateParentCategoryRowspans(toggleElement,targetRows.length)},updateParentCategoryRowspans=(toggleElement,num)=>{const userReport=toggleElement.closest(SELECTORS_USER_REPORT_TABLE);toggleElement.closest("tr").classList.forEach((className=>{const parentCategoryToggleElement=userReport.querySelector('[data-target=".'.concat(className,"[data-hidden='false']\""));if(parentCategoryToggleElement){const categoryRowSpanElement=parentCategoryToggleElement.closest("tr").nextElementSibling.querySelector("[rowspan]");"true"===toggleElement.getAttribute("aria-expanded")?categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan+num:categoryRowSpanElement.rowSpan=categoryRowSpanElement.rowSpan-num}}))};_exports.init=userReportId=>{(userReportId=>{document.querySelector("#"+userReportId).querySelector(SELECTORS_USER_REPORT_TABLE).addEventListener("click",(e=>{const toggle=e.target.closest(SELECTORS_CATEGORY_TOGGLE);toggle&&(e.preventDefault(),toggleCategory(toggle))}))})(userReportId)}})); //# sourceMappingURL=gradecategorytoggle.min.js.map \ No newline at end of file diff --git a/grade/report/user/amd/build/gradecategorytoggle.min.js.map b/grade/report/user/amd/build/gradecategorytoggle.min.js.map index f5c30f33f70..350f23a66d9 100644 --- a/grade/report/user/amd/build/gradecategorytoggle.min.js.map +++ b/grade/report/user/amd/build/gradecategorytoggle.min.js.map @@ -1 +1 @@ -{"version":3,"file":"gradecategorytoggle.min.js","sources":["../src/gradecategorytoggle.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 * Javascript module for toggling the visibility of the grade categories in the user report.\n *\n * @module gradereport_user/gradecategorytoggle\n * @copyright 2022 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst SELECTORS = {\n CATEGORY_TOGGLE: '.toggle-category',\n USER_REPORT_TABLE: '.user-grade'\n};\n\n/**\n * Register related event listeners.\n *\n * @method registerListenerEvents\n * @param {string} userReportId The ID of the user report container element.\n */\nconst registerListenerEvents = (userReportId) => {\n const reportContainer = document.querySelector('#' + userReportId);\n const userReport = reportContainer.querySelector(SELECTORS.USER_REPORT_TABLE);\n\n userReport.addEventListener('click', e => {\n const toggle = e.target.closest(SELECTORS.CATEGORY_TOGGLE);\n\n if (toggle) {\n toggleCategory(toggle);\n }\n });\n};\n\n/**\n * Method that handles the category toggle action.\n *\n * @method toggleCategory\n * @param {object} toggleElement The category toggle node that was clicked.\n */\nconst toggleCategory = (toggleElement) => {\n const target = toggleElement.dataset.target;\n const categoryId = toggleElement.dataset.categoryid;\n // Whether the toggle action is collapsing the category or not.\n const isCollapsing = toggleElement.getAttribute('aria-expanded') === \"true\";\n const userReport = toggleElement.closest(SELECTORS.USER_REPORT_TABLE);\n\n // Find all targeted 'children' rows of the toggled category.\n const targetRows = userReport.querySelectorAll(target);\n\n if (isCollapsing) {\n toggleElement.setAttribute('aria-expanded', 'false');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to expand this category we only target rows which have been hidden by this category toggle action.\n toggleElement.dataset.target = `[data-hidden-by='${categoryId}']`;\n } else {\n toggleElement.setAttribute('aria-expanded', 'true');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to collapse this category we only target rows which are children of this category and are not currently hidden.\n toggleElement.dataset.target = `.cat_${categoryId}[data-hidden='false']`;\n }\n\n // Loop through all targeted children row elements and update the required data attributes to either hide or show\n // them depending on the toggle action (collapsing or expanding).\n targetRows.forEach((row) => {\n if (isCollapsing) {\n row.dataset.hidden = 'true';\n row.dataset.hiddenBy = categoryId;\n } else {\n row.dataset.hidden = 'false';\n row.dataset.hiddenBy = '';\n }\n });\n\n // Since the user report is presented in an HTML table, rowspans are used under each category to create a visual\n // hierarchy between categories and grading items. When expanding or collapsing a category we need to also update\n // (subtract or add) the rowspan values associated to each parent category row to preserve the correct visual\n // hierarchy in the table.\n updateParentCategoryRowspans(toggleElement, targetRows.length);\n};\n\n/**\n * Method that updates the rowspan value of all 'parent' category rows of a given category node.\n *\n * @method updateParentCategoryRowspans\n * @param {object} toggleElement The category toggle node that was clicked.\n * @param {int} num The number we want to add or subtract from the rowspan value of the 'parent' category row elements.\n */\nconst updateParentCategoryRowspans = (toggleElement, num) => {\n const userReport = toggleElement.closest(SELECTORS.USER_REPORT_TABLE);\n // Get the row element which contains the category toggle node.\n const rowElement = toggleElement.closest('tr');\n\n // Loop through the class list of the toggle category row element.\n // The list contains classes which identify all parent categories of the toggled category.\n rowElement.classList.forEach((className) => {\n // Find the toggle node of the 'parent' category that is identified by the given class name.\n const parentCategoryToggleElement = userReport.querySelector(`[data-target=\".${className}[data-hidden='false']\"`);\n if (parentCategoryToggleElement) {\n // Get the row element which contains the parent category toggle node.\n const categoryRowElement = parentCategoryToggleElement.closest('tr');\n // Find the rowspan element associated to this parent category.\n const categoryRowSpanElement = categoryRowElement.nextElementSibling.querySelector('[rowspan]');\n\n // Depending on whether the toggle action has expanded or collapsed the category, either add or\n // subtract from the 'parent' category rowspan.\n if (toggleElement.getAttribute('aria-expanded') === \"true\") {\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan + num;\n } else { // The category has been collapsed.\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan - num;\n }\n }\n });\n};\n\n/**\n * Init method.\n *\n * @param {string} userReportId The ID of the user report container element.\n */\nexport const init = (userReportId) => {\n registerListenerEvents(userReportId);\n};\n"],"names":["SELECTORS","toggleCategory","toggleElement","target","dataset","categoryId","categoryid","isCollapsing","getAttribute","targetRows","closest","querySelectorAll","setAttribute","forEach","row","hidden","hiddenBy","updateParentCategoryRowspans","length","num","userReport","classList","className","parentCategoryToggleElement","querySelector","categoryRowSpanElement","nextElementSibling","rowSpan","userReportId","document","addEventListener","e","toggle","registerListenerEvents"],"mappings":";;;;;;;;MAuBMA,0BACe,mBADfA,4BAEiB,cA4BjBC,eAAkBC,sBACdC,OAASD,cAAcE,QAAQD,OAC/BE,WAAaH,cAAcE,QAAQE,WAEnCC,aAA+D,SAAhDL,cAAcM,aAAa,iBAI1CC,WAHaP,cAAcQ,QAAQV,6BAGXW,iBAAiBR,QAE3CI,cACAL,cAAcU,aAAa,gBAAiB,SAG5CV,cAAcE,QAAQD,kCAA6BE,mBAEnDH,cAAcU,aAAa,gBAAiB,QAG5CV,cAAcE,QAAQD,sBAAiBE,qCAK3CI,WAAWI,SAASC,MACZP,cACAO,IAAIV,QAAQW,OAAS,OACrBD,IAAIV,QAAQY,SAAWX,aAEvBS,IAAIV,QAAQW,OAAS,QACrBD,IAAIV,QAAQY,SAAW,OAQ/BC,6BAA6Bf,cAAeO,WAAWS,SAUrDD,6BAA+B,CAACf,cAAeiB,aAC3CC,WAAalB,cAAcQ,QAAQV,6BAEtBE,cAAcQ,QAAQ,MAI9BW,UAAUR,SAASS,kBAEpBC,4BAA8BH,WAAWI,uCAAgCF,yCAC3EC,4BAA6B,OAIvBE,uBAFqBF,4BAA4Bb,QAAQ,MAEbgB,mBAAmBF,cAAc,aAI/B,SAAhDtB,cAAcM,aAAa,iBAC3BiB,uBAAuBE,QAAUF,uBAAuBE,QAAUR,IAElEM,uBAAuBE,QAAUF,uBAAuBE,QAAUR,uBAW7DS,eAnGWA,CAAAA,eACJC,SAASL,cAAc,IAAMI,cAClBJ,cAAcxB,6BAEtC8B,iBAAiB,SAASC,UAC3BC,OAASD,EAAE5B,OAAOO,QAAQV,2BAE5BgC,QACA/B,eAAe+B,YA4FvBC,CAAuBL"} \ No newline at end of file +{"version":3,"file":"gradecategorytoggle.min.js","sources":["../src/gradecategorytoggle.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 * Javascript module for toggling the visibility of the grade categories in the user report.\n *\n * @module gradereport_user/gradecategorytoggle\n * @copyright 2022 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst SELECTORS = {\n CATEGORY_TOGGLE: '.toggle-category',\n USER_REPORT_TABLE: '.user-grade'\n};\n\n/**\n * Register related event listeners.\n *\n * @method registerListenerEvents\n * @param {string} userReportId The ID of the user report container element.\n */\nconst registerListenerEvents = (userReportId) => {\n const reportContainer = document.querySelector('#' + userReportId);\n const userReport = reportContainer.querySelector(SELECTORS.USER_REPORT_TABLE);\n\n userReport.addEventListener('click', e => {\n const toggle = e.target.closest(SELECTORS.CATEGORY_TOGGLE);\n\n if (toggle) {\n e.preventDefault();\n toggleCategory(toggle);\n }\n });\n};\n\n/**\n * Method that handles the category toggle action.\n *\n * @method toggleCategory\n * @param {object} toggleElement The category toggle node that was clicked.\n */\nconst toggleCategory = (toggleElement) => {\n const target = toggleElement.dataset.target;\n const categoryId = toggleElement.dataset.categoryid;\n // Whether the toggle action is collapsing the category or not.\n const isCollapsing = toggleElement.getAttribute('aria-expanded') === \"true\";\n const userReport = toggleElement.closest(SELECTORS.USER_REPORT_TABLE);\n\n // Find all targeted 'children' rows of the toggled category.\n const targetRows = userReport.querySelectorAll(target);\n\n if (isCollapsing) {\n toggleElement.setAttribute('aria-expanded', 'false');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to expand this category we only target rows which have been hidden by this category toggle action.\n toggleElement.dataset.target = `[data-hidden-by='${categoryId}']`;\n } else {\n toggleElement.setAttribute('aria-expanded', 'true');\n // Update the 'data-target' of the toggle category node to make sure that when we perform another toggle action\n // to collapse this category we only target rows which are children of this category and are not currently hidden.\n toggleElement.dataset.target = `.cat_${categoryId}[data-hidden='false']`;\n }\n\n // Loop through all targeted children row elements and update the required data attributes to either hide or show\n // them depending on the toggle action (collapsing or expanding).\n targetRows.forEach((row) => {\n if (isCollapsing) {\n row.dataset.hidden = 'true';\n row.dataset.hiddenBy = categoryId;\n } else {\n row.dataset.hidden = 'false';\n row.dataset.hiddenBy = '';\n }\n });\n\n // Since the user report is presented in an HTML table, rowspans are used under each category to create a visual\n // hierarchy between categories and grading items. When expanding or collapsing a category we need to also update\n // (subtract or add) the rowspan values associated to each parent category row to preserve the correct visual\n // hierarchy in the table.\n updateParentCategoryRowspans(toggleElement, targetRows.length);\n};\n\n/**\n * Method that updates the rowspan value of all 'parent' category rows of a given category node.\n *\n * @method updateParentCategoryRowspans\n * @param {object} toggleElement The category toggle node that was clicked.\n * @param {int} num The number we want to add or subtract from the rowspan value of the 'parent' category row elements.\n */\nconst updateParentCategoryRowspans = (toggleElement, num) => {\n const userReport = toggleElement.closest(SELECTORS.USER_REPORT_TABLE);\n // Get the row element which contains the category toggle node.\n const rowElement = toggleElement.closest('tr');\n\n // Loop through the class list of the toggle category row element.\n // The list contains classes which identify all parent categories of the toggled category.\n rowElement.classList.forEach((className) => {\n // Find the toggle node of the 'parent' category that is identified by the given class name.\n const parentCategoryToggleElement = userReport.querySelector(`[data-target=\".${className}[data-hidden='false']\"`);\n if (parentCategoryToggleElement) {\n // Get the row element which contains the parent category toggle node.\n const categoryRowElement = parentCategoryToggleElement.closest('tr');\n // Find the rowspan element associated to this parent category.\n const categoryRowSpanElement = categoryRowElement.nextElementSibling.querySelector('[rowspan]');\n\n // Depending on whether the toggle action has expanded or collapsed the category, either add or\n // subtract from the 'parent' category rowspan.\n if (toggleElement.getAttribute('aria-expanded') === \"true\") {\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan + num;\n } else { // The category has been collapsed.\n categoryRowSpanElement.rowSpan = categoryRowSpanElement.rowSpan - num;\n }\n }\n });\n};\n\n/**\n * Init method.\n *\n * @param {string} userReportId The ID of the user report container element.\n */\nexport const init = (userReportId) => {\n registerListenerEvents(userReportId);\n};\n"],"names":["SELECTORS","toggleCategory","toggleElement","target","dataset","categoryId","categoryid","isCollapsing","getAttribute","targetRows","closest","querySelectorAll","setAttribute","forEach","row","hidden","hiddenBy","updateParentCategoryRowspans","length","num","userReport","classList","className","parentCategoryToggleElement","querySelector","categoryRowSpanElement","nextElementSibling","rowSpan","userReportId","document","addEventListener","e","toggle","preventDefault","registerListenerEvents"],"mappings":";;;;;;;;MAuBMA,0BACe,mBADfA,4BAEiB,cA6BjBC,eAAkBC,sBACdC,OAASD,cAAcE,QAAQD,OAC/BE,WAAaH,cAAcE,QAAQE,WAEnCC,aAA+D,SAAhDL,cAAcM,aAAa,iBAI1CC,WAHaP,cAAcQ,QAAQV,6BAGXW,iBAAiBR,QAE3CI,cACAL,cAAcU,aAAa,gBAAiB,SAG5CV,cAAcE,QAAQD,kCAA6BE,mBAEnDH,cAAcU,aAAa,gBAAiB,QAG5CV,cAAcE,QAAQD,sBAAiBE,qCAK3CI,WAAWI,SAASC,MACZP,cACAO,IAAIV,QAAQW,OAAS,OACrBD,IAAIV,QAAQY,SAAWX,aAEvBS,IAAIV,QAAQW,OAAS,QACrBD,IAAIV,QAAQY,SAAW,OAQ/BC,6BAA6Bf,cAAeO,WAAWS,SAUrDD,6BAA+B,CAACf,cAAeiB,aAC3CC,WAAalB,cAAcQ,QAAQV,6BAEtBE,cAAcQ,QAAQ,MAI9BW,UAAUR,SAASS,kBAEpBC,4BAA8BH,WAAWI,uCAAgCF,yCAC3EC,4BAA6B,OAIvBE,uBAFqBF,4BAA4Bb,QAAQ,MAEbgB,mBAAmBF,cAAc,aAI/B,SAAhDtB,cAAcM,aAAa,iBAC3BiB,uBAAuBE,QAAUF,uBAAuBE,QAAUR,IAElEM,uBAAuBE,QAAUF,uBAAuBE,QAAUR,uBAW7DS,eApGWA,CAAAA,eACJC,SAASL,cAAc,IAAMI,cAClBJ,cAAcxB,6BAEtC8B,iBAAiB,SAASC,UAC3BC,OAASD,EAAE5B,OAAOO,QAAQV,2BAE5BgC,SACAD,EAAEE,iBACFhC,eAAe+B,aA4FvBE,CAAuBN"} \ No newline at end of file diff --git a/grade/report/user/amd/src/gradecategorytoggle.js b/grade/report/user/amd/src/gradecategorytoggle.js index 262b5a8a628..62d17f9e4c6 100644 --- a/grade/report/user/amd/src/gradecategorytoggle.js +++ b/grade/report/user/amd/src/gradecategorytoggle.js @@ -40,6 +40,7 @@ const registerListenerEvents = (userReportId) => { const toggle = e.target.closest(SELECTORS.CATEGORY_TOGGLE); if (toggle) { + e.preventDefault(); toggleCategory(toggle); } });