AutorÃa | Ultima modificación | Ver Log |
{"version":3,"file":"dynamic.min.js","sources":["../src/dynamic.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 * Module to handle dynamic table features.\n *\n * @module core_table/dynamic\n * @copyright 2020 Simey Lameze <simey@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport * as Sele
ctors from 'core_table/local/dynamic/selectors';\nimport Events from './local/dynamic/events';\nimport Pending from 'core/pending';\nimport {addIconToContainer} from 'core/loadingicon';\nimport {fetch as fetchTableData} from 'core_table/local/dynamic/repository';\nimport Notification from 'core/notification';\n\nlet watching = false;\n\n/**\n * Ensure that a table is a dynamic table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Bool}\n */\nconst checkTableIsDynamic = tableRoot => {\n if (!tableRoot) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n if (!tableRoot.matches(Selectors.main.region)) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n return true;\n};\n\n/**\n * Get the filterset data from a known dynamic table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Object}\n */
\nconst getFiltersetFromTable = tableRoot => {\n return JSON.parse(tableRoot.dataset.tableFilters);\n};\n\n/**\n * Update the specified table based on its current values.\n *\n * @param {HTMLElement} tableRoot\n * @param {Bool} resetContent\n * @returns {Promise}\n */\nexport const refreshTableContent = (tableRoot, resetContent = false) => {\n const filterset = getFiltersetFromTable(tableRoot);\n addIconToContainer(tableRoot);\n\n const pendingPromise = new Pending('core_table/dynamic:refreshTableContent');\n\n return fetchTableData(\n tableRoot.dataset.tableComponent,\n tableRoot.dataset.tableHandler,\n tableRoot.dataset.tableUniqueid,\n {\n sortData: JSON.parse(tableRoot.dataset.tableSortData),\n joinType: filterset.jointype,\n filters: filterset.filters,\n firstinitial: tableRoot.dataset.tableFirstInitial,\n lastinitial: tableRoot.dataset.tableLastInitial,\n pageNumber: tableRoot.dataset.tablePageN
umber,\n pageSize: tableRoot.dataset.tablePageSize,\n hiddenColumns: JSON.parse(tableRoot.dataset.tableHiddenColumns),\n },\n resetContent,\n )\n .then(data => {\n const placeholder = document.createElement('div');\n placeholder.innerHTML = data.html;\n tableRoot.replaceWith(...placeholder.childNodes);\n\n // Update the tableRoot.\n return getTableFromId(tableRoot.dataset.tableUniqueid);\n }).then(tableRoot => {\n tableRoot.dispatchEvent(new CustomEvent(Events.tableContentRefreshed, {\n bubbles: true,\n }));\n\n return tableRoot;\n })\n .then(tableRoot => {\n pendingPromise.resolve();\n\n return tableRoot;\n });\n};\n\nexport const updateTable = (tableRoot, {\n sortBy = null,\n sortOrder = null,\n filters = null,\n firstInitial = null,\n lastInitial = null,\n pageNumber = null,\n pageSize = null,\n hiddenColumns = null,\n} = {}, refreshContent = true)
=> {\n checkTableIsDynamic(tableRoot);\n\n const pendingPromise = new Pending('core_table/dynamic:updateTable');\n let tableConfigChanged = false;\n\n // Update sort fields.\n if (sortBy && sortOrder) {\n // Always update the table if requested and there were sort fields.\n // These fields are only ever normalised in the backend.\n tableConfigChanged = true;\n\n const sortData = JSON.parse(tableRoot.dataset.tableSortData);\n sortData.unshift({\n sortby: sortBy,\n sortorder: parseInt(sortOrder, 10),\n });\n tableRoot.dataset.tableSortData = JSON.stringify(sortData);\n }\n\n // Update initials.\n if (firstInitial !== null) {\n if (tableRoot.dataset.tableFirstInitial !== firstInitial) {\n tableConfigChanged = true;\n }\n\n tableRoot.dataset.tableFirstInitial = firstInitial;\n }\n\n if (lastInitial !== null) {\n if (tableRoot.dataset.tableLastInitial !== lastInitial) {\n
tableConfigChanged = true;\n }\n\n tableRoot.dataset.tableLastInitial = lastInitial;\n }\n\n if (pageSize !== null) {\n if (tableRoot.dataset.tablePageSize != pageSize) {\n tableConfigChanged = true;\n }\n\n tableRoot.dataset.tablePageSize = pageSize;\n }\n\n // Update filters.\n if (filters) {\n const filterJson = JSON.stringify(filters);\n\n if (tableRoot.dataset.tableFilters !== filterJson) {\n tableConfigChanged = true;\n }\n\n tableRoot.dataset.tableFilters = filterJson;\n }\n\n // Reset to page 1 when table content is being altered by filtering or sorting.\n // This ensures the table page being loaded always exists, and gives a consistent experience.\n if (tableConfigChanged) {\n pageNumber = 1;\n }\n\n // Update hidden columns.\n if (hiddenColumns) {\n const columnJson = JSON.stringify(hiddenColumns);\n\n if (tableRoot.dataset.tableHiddenColumns !== colu
mnJson) {\n tableConfigChanged = true;\n }\n\n tableRoot.dataset.tableHiddenColumns = columnJson;\n }\n\n if (pageNumber !== null) {\n if (tableRoot.dataset.tablePageNumber != pageNumber) {\n tableConfigChanged = true;\n }\n\n tableRoot.dataset.tablePageNumber = pageNumber;\n }\n\n // Refresh.\n if (refreshContent && tableConfigChanged) {\n return refreshTableContent(tableRoot)\n .then(tableRoot => {\n pendingPromise.resolve();\n return tableRoot;\n });\n } else {\n pendingPromise.resolve();\n return Promise.resolve(tableRoot);\n }\n};\n\n/**\n * Get the table dataset for the specified tableRoot, ensuring that the provided table is a dynamic table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {DOMStringMap}\n */\nconst getTableData = tableRoot => {\n checkTableIsDynamic(tableRoot);\n\n return tableRoot.dataset;\n};\n\n/**\n * Update the specified table using the
new filters.\n *\n * @param {HTMLElement} tableRoot\n * @param {Object} filters\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setFilters = (tableRoot, filters, refreshContent = true) =>\n updateTable(tableRoot, {filters}, refreshContent);\n\n/**\n * Get the filter data for the specified table.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Object}\n */\nexport const getFilters = tableRoot => {\n checkTableIsDynamic(tableRoot);\n\n return getFiltersetFromTable(tableRoot);\n};\n\n/**\n * Update the sort order.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} sortBy\n * @param {Number} sortOrder\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setSortOrder = (tableRoot, sortBy, sortOrder, refreshContent = true) =>\n updateTable(tableRoot, {sortBy, sortOrder}, refreshContent);\n\n/**\n * Set the page number.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} pageNumber\n * @param {Bool} refreshContent\n * @returns {Promise
}\n */\nexport const setPageNumber = (tableRoot, pageNumber, refreshContent = true) =>\n updateTable(tableRoot, {pageNumber}, refreshContent);\n\n/**\n * Get the current page number.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Number}\n */\nexport const getPageNumber = tableRoot => getTableData(tableRoot).tablePageNumber;\n\n/**\n * Set the page size.\n *\n * @param {HTMLElement} tableRoot\n * @param {Number} pageSize\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setPageSize = (tableRoot, pageSize, refreshContent = true) =>\n updateTable(tableRoot, {pageSize, pageNumber: 1}, refreshContent);\n\n/**\n * Get the current page size.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Number}\n */\nexport const getPageSize = tableRoot => getTableData(tableRoot).tablePageSize;\n\n/**\n * Update the first initial to show.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} firstInitial\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setF
irstInitial = (tableRoot, firstInitial, refreshContent = true) =>\n updateTable(tableRoot, {firstInitial}, refreshContent);\n\n/**\n * Get the current first initial filter.\n *\n * @param {HTMLElement} tableRoot\n * @returns {String}\n */\nexport const getFirstInitial = tableRoot => getTableData(tableRoot).tableFirstInitial;\n\n/**\n * Update the last initial to show.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} lastInitial\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const setLastInitial = (tableRoot, lastInitial, refreshContent = true) =>\n updateTable(tableRoot, {lastInitial}, refreshContent);\n\n/**\n * Get the current last initial filter.\n *\n * @param {HTMLElement} tableRoot\n * @returns {String}\n */\nexport const getLastInitial = tableRoot => getTableData(tableRoot).tableLastInitial;\n\n/**\n * Hide a column in the participants table.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} columnToHide\n * @param {Bool} refreshContent\n * @returns {Prom
ise}\n */\nexport const hideColumn = (tableRoot, columnToHide, refreshContent = true) => {\n const hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);\n hiddenColumns.push(columnToHide);\n\n return updateTable(tableRoot, {hiddenColumns}, refreshContent);\n};\n\n/**\n * Make a hidden column visible in the participants table.\n *\n * @param {HTMLElement} tableRoot\n * @param {String} columnToShow\n * @param {Bool} refreshContent\n * @returns {Promise}\n */\nexport const showColumn = (tableRoot, columnToShow, refreshContent = true) => {\n let hiddenColumns = JSON.parse(tableRoot.dataset.tableHiddenColumns);\n hiddenColumns = hiddenColumns.filter(columnName => columnName !== columnToShow);\n\n return updateTable(tableRoot, {hiddenColumns}, refreshContent);\n};\n\n/**\n * Reset table preferences.\n *\n * @param {HTMLElement} tableRoot\n * @returns {Promise}\n */\nconst resetTablePreferences = tableRoot => refreshTableContent(tableRoot, true);\n\n/**\n * Set up listeners to handle t
able updates.\n */\nexport const init = () => {\n if (watching) {\n // Already watching.\n return;\n }\n watching = true;\n\n document.addEventListener('click', e => {\n const tableRoot = e.target.closest(Selectors.main.region);\n\n if (!tableRoot) {\n return;\n }\n\n const sortableLink = e.target.closest(Selectors.table.links.sortableColumn);\n if (sortableLink) {\n e.preventDefault();\n\n setSortOrder(tableRoot, sortableLink.dataset.sortby, sortableLink.dataset.sortorder)\n .catch(Notification.exception);\n }\n\n const firstInitialLink = e.target.closest(Selectors.initialsBar.links.firstInitial);\n if (firstInitialLink !== null) {\n e.preventDefault();\n\n setFirstInitial(tableRoot, firstInitialLink.dataset.initial).catch(Notification.exception);\n }\n\n const lastInitialLink = e.target.closest(Selectors.initialsBar.links.lastInitial);\n if
(lastInitialLink !== null) {\n e.preventDefault();\n\n setLastInitial(tableRoot, lastInitialLink.dataset.initial).catch(Notification.exception);\n }\n\n const pageItem = e.target.closest(Selectors.paginationBar.links.pageItem);\n if (pageItem) {\n e.preventDefault();\n\n setPageNumber(tableRoot, pageItem.dataset.pageNumber).catch(Notification.exception);\n }\n\n const hide = e.target.closest(Selectors.table.links.hide);\n if (hide) {\n e.preventDefault();\n\n hideColumn(tableRoot, hide.dataset.column).catch(Notification.exception);\n }\n\n const show = e.target.closest(Selectors.table.links.show);\n if (show) {\n e.preventDefault();\n\n showColumn(tableRoot, show.dataset.column).catch(Notification.exception);\n }\n\n const resetTablePreferencesLink = e.target.closest('.resettable a');\n if (resetTablePreferencesLink) {\n e.prev
entDefault();\n\n resetTablePreferences(tableRoot).catch(Notification.exception);\n }\n\n const showCountLink = e.target.closest(Selectors.showCount.links.toggle);\n if (showCountLink) {\n e.preventDefault();\n\n setPageSize(tableRoot, showCountLink.dataset.targetPageSize).catch(Notification.exception);\n }\n });\n};\n\n/**\n * Fetch the table via its table region id.\n *\n * @param {String} tableRegionId\n * @returns {HTMLElement}\n */\nexport const getTableFromId = tableRegionId => {\n const tableRoot = document.querySelector(Selectors.main.fromRegionId(tableRegionId));\n\n\n if (!tableRoot) {\n // The table is not a dynamic table.\n throw new Error(\"The table specified is not a dynamic table and cannot be updated\");\n }\n\n return tableRoot;\n};\n\nexport {\n Events\n};\n"],"names":["watching","checkTableIsDynamic","tableRoot","Error","matches","Selectors","main","region","getFiltersetFromTable","JSON","parse","
dataset","tableFilters","refreshTableContent","resetContent","filterset","pendingPromise","Pending","tableComponent","tableHandler","tableUniqueid","sortData","tableSortData","joinType","jointype","filters","firstinitial","tableFirstInitial","lastinitial","tableLastInitial","pageNumber","tablePageNumber","pageSize","tablePageSize","hiddenColumns","tableHiddenColumns","then","data","placeholder","document","createElement","innerHTML","html","replaceWith","childNodes","getTableFromId","dispatchEvent","CustomEvent","Events","tableContentRefreshed","bubbles","resolve","updateTable","sortBy","sortOrder","firstInitial","lastInitial","refreshContent","tableConfigChanged","unshift","sortby","sortorder","parseInt","stringify","filterJson","columnJson","Promise","getTableData","setSortOrder","setPageNumber","setPageSize","setFirstInitial","setLastInitial","hideColumn","columnToHide","push","showColumn","columnToShow","filter","columnName","addEventListener","e","target","closest","sortableLink","table","links","sortab
leColumn","preventDefault","catch","Notification","exception","firstInitialLink","initialsBar","initial","lastInitialLink","pageItem","paginationBar","hide","column","show","resetTablePreferences","showCountLink","showCount","toggle","targetPageSize","tableRegionId","querySelector","fromRegionId"],"mappings":"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"}