Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

{"version":3,"file":"bulkedittools.min.js","sources":["../../../src/local/content/bulkedittools.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 * The bulk editor tools bar.\n *\n * @module     core_courseformat/local/content/bulkedittools\n * @class      core_courseformat/local/content/bulkedittools\n * @copyright  2023 Ferran Recio <ferran@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent} from 'core/reactive';\nimport {disableStickyFooter, enableStickyFooter} from 'core/sticky-footer';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport {getString} from 'core/str';\nimport Pending from 'core/pending';\nimport {prefetchStrings} from 'core/prefetch';\nimport {\n    selectAllBulk,\n    switchBulkSelection,\n    checkAllBulkSelected\n} from 'core_courseformat/local/content/actions/bulkselection';\nimport Notification from 'core/notification';\n\n// Load global strings.\nprefetchStrings(\n    'core_courseformat',\n    ['bulkselection']\n);\n\nexport default class Component extends BaseComponent {\n\n    /**\n     * Constructor hook.\n     */\n    create() {\n        // Optional component name for debugging.\n        this.name = 'bulk_editor_tools';\n        // Default query selectors.\n        this.selectors = {\n            ACTIONS: `[data-for=\"bulkaction\"]`,\n            ACTIONTOOL: `[data-for=\"bulkactions\"] li`,\n            CANCEL: `[data-for=\"bulkcancel\"]`,\n            COUNT: `[data-for='bulkcount']`,\n            SELECTABLE: `[data-bulkcheckbox][data-is-selectable]`,\n            SELECTALL: `[data-for=\"selectall\"]`,\n            BULKBTN: `[data-for=\"enableBulk\"]`,\n        };\n        // Most classes will be loaded later by DndCmItem.\n        this.classes = {\n            HIDE: 'd-none',\n            DISABLED: 'disabled',\n        };\n    }\n\n    /**\n     * Static method to create a component instance from the mustache template.\n     *\n     * @param {string} target optional altentative DOM main element CSS selector\n     * @param {object} selectors optional css selector overrides\n     * @return {Component}\n     */\n    static init(target, selectors) {\n        return new this({\n            element: document.querySelector(target),\n            reactive: getCurrentCourseEditor(),\n            selectors\n        });\n    }\n\n    /**\n     * Initial state ready method.\n     */\n    stateReady() {\n        const cancelBtn = this.getElement(this.selectors.CANCEL);\n        if (cancelBtn) {\n            this.addEventListener(cancelBtn, 'click', this._cancelBulk);\n        }\n        const selectAll = this.getElement(this.selectors.SELECTALL);\n        if (selectAll) {\n            this.addEventListener(selectAll, 'click', this._selectAllClick);\n        }\n    }\n\n    /**\n     * Component watchers.\n     *\n     * @returns {Array} of watchers\n     */\n    getWatchers() {\n        return [\n            {watch: `bulk.enabled:updated`, handler: this._refreshEnabled},\n            {watch: `bulk:updated`, handler: this._refreshTools},\n        ];\n    }\n\n    /**\n     * Hide and show the bulk edit tools.\n     *\n     * @param {object} param\n     * @param {Object} param.element details the update details (state.bulk in this case).\n     */\n    _refreshEnabled({element}) {\n        this._updatePageTitle(element.enabled).catch(Notification.exception);\n\n        if (element.enabled) {\n            enableStickyFooter();\n        } else {\n            disableStickyFooter();\n        }\n    }\n\n    /**\n     * Refresh the tools depending on the current selection.\n     *\n     * @param {object} param the state watcher information\n     * @param {Object} param.state the full state data.\n     * @param {Object} param.element the affected element (bulk in this case).\n     */\n    _refreshTools(param) {\n        this._refreshSelectCount(param);\n        this._refreshSelectAll(param);\n        this._refreshActions(param);\n    }\n\n    /**\n     * Refresh the selection count.\n     *\n     * @param {object} param\n     * @param {Object} param.element the affected element (bulk in this case).\n     */\n    async _refreshSelectCount({element: bulk}) {\n        const stringName = (bulk.selection.length > 1) ? 'bulkselection_plural' : 'bulkselection';\n        const selectedCount = await getString(stringName, 'core_courseformat', bulk.selection.length);\n        const selectedElement = this.getElement(this.selectors.COUNT);\n        if (selectedElement) {\n            selectedElement.innerHTML = selectedCount;\n        }\n    }\n\n    /**\n     * Refresh the select all element.\n     *\n     * @param {object} param\n     * @param {Object} param.element the affected element (bulk in this case).\n     */\n    _refreshSelectAll({element: bulk}) {\n        const selectall = this.getElement(this.selectors.SELECTALL);\n        if (!selectall) {\n            return;\n        }\n        selectall.disabled = (bulk.selectedType === '');\n        // The changechecker module can prevent the checkbox form changing it's value.\n        // To avoid that we leave the sniffer to act before changing the value.\n        const pending = new Pending(`courseformat/bulktools:refreshSelectAll`);\n        setTimeout(\n            () => {\n                selectall.checked = checkAllBulkSelected(this.reactive);\n                pending.resolve();\n            },\n            100\n        );\n    }\n\n    /**\n     * Refresh the visible action buttons depending on the selection type.\n     *\n     * @param {object} param\n     * @param {Object} param.element the affected element (bulk in this case).\n     */\n    _refreshActions({element: bulk}) {\n        // By default, we show the cm options.\n        const displayType = (bulk.selectedType == 'section') ? 'section' : 'cm';\n        const enabled = (bulk.selectedType !== '');\n        this.getElements(this.selectors.ACTIONS).forEach(action => {\n            action.classList.toggle(this.classes.DISABLED, !enabled);\n            action.tabIndex = (enabled) ? 0 : -1;\n\n            const actionTool = action.closest(this.selectors.ACTIONTOOL);\n            const isHidden = (action.dataset.bulk != displayType);\n            actionTool?.classList.toggle(this.classes.HIDE, isHidden);\n        });\n    }\n\n    /**\n     * Cancel bulk handler.\n     */\n    _cancelBulk() {\n        const pending = new Pending(`courseformat/content:bulktoggle_off`);\n        this.reactive.dispatch('bulkEnable', false);\n        // Wait for a while and focus on enable bulk button.\n        setTimeout(() => {\n            document.querySelector(this.selectors.BULKBTN)?.focus();\n            pending.resolve();\n        }, 150);\n    }\n\n    /**\n     * Handle special select all cases.\n     * @param {Event} event\n     */\n    _selectAllClick(event) {\n        event.preventDefault();\n        if (event.altKey) {\n            switchBulkSelection(this.reactive);\n            return;\n        }\n        if (checkAllBulkSelected(this.reactive)) {\n            this._handleUnselectAll();\n            return;\n        }\n        selectAllBulk(this.reactive, true);\n    }\n\n    /**\n     * Process unselect all elements.\n     */\n    _handleUnselectAll() {\n        const pending = new Pending(`courseformat/content:bulktUnselectAll`);\n        selectAllBulk(this.reactive, false);\n        // Wait for a while and focus on the first checkbox.\n        setTimeout(() => {\n            document.querySelector(this.selectors.SELECTABLE)?.focus();\n            pending.resolve();\n        }, 150);\n    }\n\n    /**\n     * Updates the <title> attribute of the page whenever bulk editing is toggled.\n     *\n     * This helps users, especially screen reader users, to understand the current state of the course homepage.\n     *\n     * @param {Boolean} enabled True when bulk editing is turned on. False, otherwise.\n     * @returns {Promise<void>}\n     * @private\n     */\n    async _updatePageTitle(enabled) {\n        const enableBulk = document.querySelector(this.selectors.BULKBTN);\n        let params, bulkEditTitle, editingTitle;\n        if (enableBulk.dataset.sectiontitle) {\n            // Section editing mode.\n            params = {\n                course: enableBulk.dataset.coursename,\n                sectionname: enableBulk.dataset.sectionname,\n                sectiontitle: enableBulk.dataset.sectiontitle,\n            };\n            bulkEditTitle = await getString('coursesectiontitlebulkediting', 'moodle', params);\n            editingTitle = await getString('coursesectiontitleediting', 'moodle', params);\n        } else {\n            // Whole course editing mode.\n            params = {\n                course: enableBulk.dataset.coursename\n            };\n            bulkEditTitle = await getString('coursetitlebulkediting', 'moodle', params);\n            editingTitle = await getString('coursetitleediting', 'moodle', params);\n        }\n        const pageTitle = document.title;\n        if (enabled) {\n            // Use bulk editing string for the page title.\n            // At this point, the current page title should be the normal editing title.\n            // So replace the normal editing title with the bulk editing title.\n            document.title = pageTitle.replace(editingTitle, bulkEditTitle);\n        } else {\n            // Use the normal editing string for the page title.\n            // At this point, the current page title should be the bulk editing title.\n            // So replace the bulk editing title with the normal editing title.\n            document.title = pageTitle.replace(bulkEditTitle, editingTitle);\n        }\n    }\n}\n"],"names":["Component","BaseComponent","create","name","selectors","ACTIONS","ACTIONTOOL","CANCEL","COUNT","SELECTABLE","SELECTALL","BULKBTN","classes","HIDE","DISABLED","target","this","element","document","querySelector","reactive","stateReady","cancelBtn","getElement","addEventListener","_cancelBulk","selectAll","_selectAllClick","getWatchers","watch","handler","_refreshEnabled","_refreshTools","_updatePageTitle","enabled","catch","Notification","exception","param","_refreshSelectCount","_refreshSelectAll","_refreshActions","bulk","stringName","selection","length","selectedCount","selectedElement","innerHTML","selectall","disabled","selectedType","pending","Pending","setTimeout","checked","resolve","displayType","getElements","forEach","action","classList","toggle","tabIndex","actionTool","closest","isHidden","dataset","dispatch","focus","event","preventDefault","altKey","_handleUnselectAll","enableBulk","params","bulkEditTitle","editingTitle","sectiontitle","course","coursename","sectionname","pageTitle","title","replace"],"mappings":"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"}