Rev 1 | AutorÃa | Comparar con el anterior | Ultima modificación | Ver Log |
{"version":3,"file":"group.min.js","sources":["../../src/comboboxsearch/group.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 * Allow the user to search for groups.\n *\n * @module core_group/comboboxsearch/group\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */
\nimport search_combobox from 'core/comboboxsearch/search_combobox';\nimport {groupFetch} from 'core_group/comboboxsearch/repository';\nimport {renderForPromise, replaceNodeContents} from 'core/templates';\nimport {debounce} from 'core/utils';\nimport Notification from 'core/notification';\n\nexport default class GroupSearch extends search_combobox {\n\n courseID;\n cmID;\n bannedFilterFields = ['id', 'link', 'groupimageurl'];\n\n /**\n * Construct the class.\n *\n * @param {int|null} cmid ID of the course module initiating the group search (optional).\n */\n constructor(cmid = null) {\n super();\n this.selectors = {...this.selectors,\n courseid: '[data-region=\"courseid\"]',\n placeholder: '.groupsearchdropdown [data-region=\"searchplaceholder\"]',\n };\n const component = document.querySelector(this.componentSelector());\n this.courseID = component.querySelector(this.selectors.courseid).dataset.courseid;\n // Ove
rride the instance since the body is built outside the constructor for the combobox.\n this.instance = component.querySelector(this.selectors.instance).dataset.instance;\n this.cmID = cmid;\n\n const searchValueElement = this.component.querySelector(`#${this.searchInput.dataset.inputElement}`);\n searchValueElement.addEventListener('change', () => {\n this.toggleDropdown(); // Otherwise the dropdown stays open when user choose an option using keyboard.\n\n const valueElement = this.component.querySelector(`#${this.combobox.dataset.inputElement}`);\n if (valueElement.value !== searchValueElement.value) {\n valueElement.value = searchValueElement.value;\n valueElement.dispatchEvent(new Event('change', {bubbles: true}));\n }\n\n searchValueElement.value = '';\n });\n\n this.component.addEventListener('hide.bs.dropdown', () => {\n this.searchInput.removeAttribute('aria-actived
escendant');\n\n const listbox = document.querySelector(`#${this.searchInput.getAttribute('aria-controls')}[role=\"listbox\"]`);\n listbox.querySelectorAll('.active[role=\"option\"]').forEach(option => {\n option.classList.remove('active');\n });\n listbox.scrollTop = 0;\n\n // Use setTimeout to make sure the following code is executed after the click event is handled.\n setTimeout(() => {\n if (this.searchInput.value !== '') {\n this.searchInput.value = '';\n this.searchInput.dispatchEvent(new Event('input', {bubbles: true}));\n }\n });\n });\n\n this.renderDefault().catch(Notification.exception);\n }\n\n /**\n * Initialise an instance of the class.\n *\n * @param {int|null} cmid ID of the course module initiating the group search (optional).\n */\n static init(cmid = null) {\n return new GroupSearch(cmid
);\n }\n\n /**\n * The overall div that contains the searching widget.\n *\n * @returns {string}\n */\n componentSelector() {\n return '.group-search';\n }\n\n /**\n * The dropdown div that contains the searching widget result space.\n *\n * @returns {string}\n */\n dropdownSelector() {\n return '.groupsearchdropdown';\n }\n\n /**\n * Build the content then replace the node.\n */\n async renderDropdown() {\n const {html, js} = await renderForPromise('core_group/comboboxsearch/resultset', {\n groups: this.getMatchedResults(),\n hasresults: this.getMatchedResults().length > 0,\n instance: this.instance,\n searchterm: this.getSearchTerm(),\n });\n replaceNodeContents(this.selectors.placeholder, html, js);\n // Remove aria-activedescendant when the available options change.\n this.searchInput.removeAttribute('aria-activedescendant');\n }\n\n /**\n
* Build the content then replace the node by default we want our form to exist.\n */\n async renderDefault() {\n this.setMatchedResults(await this.filterDataset(await this.getDataset()));\n this.filterMatchDataset();\n\n await this.renderDropdown();\n\n this.updateNodes();\n }\n\n /**\n * Get the data we will be searching against in this component.\n *\n * @returns {Promise<*>}\n */\n async fetchDataset() {\n return await groupFetch(this.courseID, this.cmID).then((r) => r.groups);\n }\n\n /**\n * Dictate to the search component how and what we want to match upon.\n *\n * @param {Array} filterableData\n * @returns {Array} The users that match the given criteria.\n */\n async filterDataset(filterableData) {\n // Sometimes we just want to show everything.\n if (this.getPreppedSearchTerm() === '') {\n return filterableData;\n }\n return filterableData.filter((group) => Object.
keys(group).some((key) => {\n if (group[key] === \"\" || this.bannedFilterFields.includes(key)) {\n return false;\n }\n return group[key].toString().toLowerCase().includes(this.getPreppedSearchTerm());\n }));\n }\n\n /**\n * Given we have a subset of the dataset, set the field that we matched upon to inform the end user.\n */\n filterMatchDataset() {\n this.setMatchedResults(\n this.getMatchedResults().map((group) => {\n return {\n id: group.id,\n name: group.name,\n groupimageurl: group.groupimageurl,\n };\n })\n );\n }\n\n /**\n * The handler for when a user interacts with the component.\n *\n * @param {MouseEvent} e The triggering event that we are working with.\n */\n async clickHandler(e) {\n if (e.target.closest(this.selectors.clearSearch)) {\n e.stopPropagation();\n
// Clear the entered search query in the search bar.\n this.searchInput.value = '';\n this.setSearchTerms(this.searchInput.value);\n this.searchInput.focus();\n this.clearSearchButton.classList.add('d-none');\n // Display results.\n await this.filterrenderpipe();\n }\n }\n\n /**\n * The handler for when a user changes the value of the component (selects an option from the dropdown).\n *\n * @param {Event} e The change event.\n */\n changeHandler(e) {\n window.location = this.selectOneLink(e.target.value);\n }\n\n /**\n * Override the input event listener for the text input area.\n */\n registerInputHandlers() {\n // Register & handle the text input.\n this.searchInput.addEventListener('input', debounce(async() => {\n this.setSearchTerms(this.searchInput.value);\n // We can also require a set amount of input before search.\n if (this
.getSearchTerm() === '') {\n // Hide the \"clear\" search button in the search bar.\n this.clearSearchButton.classList.add('d-none');\n } else {\n // Display the \"clear\" search button in the search bar.\n this.clearSearchButton.classList.remove('d-none');\n }\n // User has given something for us to filter against.\n await this.filterrenderpipe();\n }, 300));\n }\n\n /**\n * Build up the view all link that is dedicated to a particular result.\n * We will call this function when a user interacts with the combobox to redirect them to show their results in the page.\n *\n * @param {Number} groupID The ID of the group selected.\n */\n selectOneLink(groupID) {\n throw new Error(`selectOneLink(${groupID}) must be implemented in ${this.constructor.name}`);\n }\n}\n"],"names":["GroupSearch","search_combobox","constructor","cmid","selectors","this","courseid","placehol
der","component","document","querySelector","componentSelector","courseID","dataset","instance","cmID","searchValueElement","searchInput","inputElement","addEventListener","toggleDropdown","valueElement","combobox","value","dispatchEvent","Event","bubbles","removeAttribute","listbox","getAttribute","querySelectorAll","forEach","option","classList","remove","scrollTop","setTimeout","renderDefault","catch","Notification","exception","dropdownSelector","html","js","groups","getMatchedResults","hasresults","length","searchterm","getSearchTerm","setMatchedResults","filterDataset","getDataset","filterMatchDataset","renderDropdown","updateNodes","then","r","filterableData","getPreppedSearchTerm","filter","group","Object","keys","some","key","bannedFilterFields","includes","toString","toLowerCase","map","id","name","groupimageurl","e","target","closest","clearSearch","stopPropagation","setSearchTerms","focus","clearSearchButton","add","filterrenderpipe","changeHandler","window","location","selectOneLink","registerIn
putHandlers","async","groupID","Error"],"mappings":"+rBA4BqBA,oBAAoBC,yBAWrCC,kBAAYC,4DAAO,mIAPE,CAAC,KAAM,OAAQ,uBAS3BC,UAAY,IAAIC,KAAKD,UACtBE,SAAU,2BACVC,YAAa,gEAEXC,UAAYC,SAASC,cAAcL,KAAKM,0BACzCC,SAAWJ,UAAUE,cAAcL,KAAKD,UAAUE,UAAUO,QAAQP,cAEpEQ,SAAWN,UAAUE,cAAcL,KAAKD,UAAUU,UAAUD,QAAQC,cACpEC,KAAOZ,WAENa,mBAAqBX,KAAKG,UAAUE,yBAAkBL,KAAKY,YAAYJ,QAAQK,eACrFF,mBAAmBG,iBAAiB,UAAU,UACrCC,uBAECC,aAAehB,KAAKG,UAAUE,yBAAkBL,KAAKiB,SAAST,QAAQK,eACxEG,aAAaE,QAAUP,mBAAmBO,QAC1CF,aAAaE,MAAQP,mBAAmBO,MACxCF,aAAaG,cAAc,IAAIC,MAAM,SAAU,CAACC,SAAS,MAG7DV,mBAAmBO,MAAQ,WAG1Bf,UAAUW,iBAAiB,oBAAoB,UAC3CF,YAAYU,gBAAgB,+BAE3BC,QAAUnB,SAASC,yBAAkBL,KAAKY,YAAYY,aAAa,sCACzED,QAAQE,iBAAiB,0BAA0BC,SAAQC,SACvDA,OAAOC,UAAUC,OAAO,aAE5BN,QAAQO,UAAY,EAGpBC,YAAW,KACwB,KAA3B/B,KAAKY,YAAYM,aACZN,YAAYM,MAAQ,QACpBN,YAAYO,cAAc,IAAIC,MAAM,QAAS,CAACC,SAAS,iBAKnEW,gBAAgBC,MAAMC,sBAAaC,gCASjC,IAAIxC,mEADI,MASnBW,0BACW,gBAQX8B,yBACW,oDAODC,KAACA,KAADC,GAAOA,UAAY,+BAAiB,sCAAuC,CAC7EC,OAAQvC,KAAKwC,oBACbC,WAAYzC,KAAKwC,oBAAoBE,OAAS,EAC9CjC,SAAUT,KA
AKS,SACfkC,WAAY3C,KAAK4C,qDAED5C,KAAKD,UAAUG,YAAamC,KAAMC,SAEjD1B,YAAYU,gBAAgB,oDAO5BuB,wBAAwB7C,KAAK8C,oBAAoB9C,KAAK+C,oBACtDC,2BAEChD,KAAKiD,sBAENC,gDASQ,0BAAWlD,KAAKO,SAAUP,KAAKU,MAAMyC,MAAMC,GAAMA,EAAEb,6BAShDc,sBAEoB,KAAhCrD,KAAKsD,uBACED,eAEJA,eAAeE,QAAQC,OAAUC,OAAOC,KAAKF,OAAOG,MAAMC,KAC1C,KAAfJ,MAAMI,OAAe5D,KAAK6D,mBAAmBC,SAASF,MAGnDJ,MAAMI,KAAKG,WAAWC,cAAcF,SAAS9D,KAAKsD,4BAOjEN,0BACSH,kBACD7C,KAAKwC,oBAAoByB,KAAKT,QACnB,CACHU,GAAIV,MAAMU,GACVC,KAAMX,MAAMW,KACZC,cAAeZ,MAAMY,sCAWlBC,GACXA,EAAEC,OAAOC,QAAQvE,KAAKD,UAAUyE,eAChCH,EAAEI,uBAEG7D,YAAYM,MAAQ,QACpBwD,eAAe1E,KAAKY,YAAYM,YAChCN,YAAY+D,aACZC,kBAAkBhD,UAAUiD,IAAI,gBAE/B7E,KAAK8E,oBASnBC,cAAcV,GACVW,OAAOC,SAAWjF,KAAKkF,cAAcb,EAAEC,OAAOpD,OAMlDiE,6BAESvE,YAAYE,iBAAiB,SAAS,oBAASsE,eAC3CV,eAAe1E,KAAKY,YAAYM,OAER,KAAzBlB,KAAK4C,qBAEAgC,kBAAkBhD,UAAUiD,IAAI,eAGhCD,kBAAkBhD,UAAUC,OAAO,gBAGtC7B,KAAK8E,qBACZ,MASPI,cAAcG,eACJ,IAAIC,8BAAuBD,4CAAmCrF,KAAKH,YAAYsE"}