diff --git a/lib/amd/build/datafilter/filtertype.min.js b/lib/amd/build/datafilter/filtertype.min.js index 84b94559f41..c8ebc04e503 100644 --- a/lib/amd/build/datafilter/filtertype.min.js +++ b/lib/amd/build/datafilter/filtertype.min.js @@ -5,6 +5,6 @@ define("core/datafilter/filtertype",["exports","core/form-autocomplete","core/da * @module core/datafilter/filtertype * @copyright 2020 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_formAutocomplete=_interopRequireDefault(_formAutocomplete),_selectors=_interopRequireDefault(_selectors);return _exports.default=class{constructor(filterType,rootNode,initialValues){this.filterType=filterType,this.rootNode=rootNode,this.addValueSelector(initialValues)}tearDown(){}get placeholder(){return(0,_str.get_string)("placeholdertypeorselect","core")}get showSuggestions(){return!0}async addValueSelector(){let initialValues=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];const filterValueNode=this.getFilterValueNode(),sourceDataNode=this.getSourceDataForFilter();if(!sourceDataNode)return;filterValueNode.innerHTML=sourceDataNode.outerHTML;const dataSource=filterValueNode.querySelector("select");dataSource.id="filter-value-"+dataSource.getAttribute("data-field-name");const filterValueLabel=document.createElement("label");filterValueLabel.setAttribute("for",dataSource.id),filterValueLabel.classList.add("sr-only"),filterValueLabel.innerText=dataSource.getAttribute("data-field-title"),filterValueNode.appendChild(filterValueLabel),initialValues.forEach((filterValue=>{let selectedOption=dataSource.querySelector('option[value="'.concat(filterValue,'"]'));selectedOption?selectedOption.selected=!0:this.showSuggestions||(selectedOption=document.createElement("option"),selectedOption.value=filterValue,selectedOption.innerHTML=filterValue,selectedOption.selected=!0,dataSource.append(selectedOption))})),_formAutocomplete.default.enhance(dataSource,"1"==dataSource.dataset.allowCustom,null,await this.placeholder,!1,this.showSuggestions,null,!dataSource.multiple,{items:"core/datafilter/autocomplete_selection_items",layout:"core/datafilter/autocomplete_layout",selection:"core/datafilter/autocomplete_selection"})}get filterRoot(){return this.rootNode.querySelector(_selectors.default.filter.byName(this.filterType))}getSourceDataForFilter(){return this.rootNode.querySelector(_selectors.default.filterset.regions.datasource).querySelector(_selectors.default.data.fields.byName(this.filterType))}getFilterValueNode(){return this.filterRoot.querySelector(_selectors.default.filter.regions.values)}get name(){return this.filterType}get jointype(){return parseInt(this.filterRoot.querySelector(_selectors.default.filter.fields.join).value,10)}get rawValues(){const filterValueSelect=this.getFilterValueNode().querySelector("select");return Object.values((select=filterValueSelect,select.querySelectorAll(":checked"))).map((option=>option.value));var select}get values(){return this.rawValues.map((option=>parseInt(option,10)))}get filterValue(){return{name:this.name,jointype:this.jointype,values:this.values}}},_exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_formAutocomplete=_interopRequireDefault(_formAutocomplete),_selectors=_interopRequireDefault(_selectors);return _exports.default=class{constructor(filterType,rootNode,initialValues){this.filterType=filterType,this.rootNode=rootNode,this.addValueSelector(initialValues)}tearDown(){}get placeholder(){return(0,_str.get_string)("placeholdertypeorselect","core")}get showSuggestions(){return!0}async addValueSelector(){let initialValues=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];const filterValueNode=this.getFilterValueNode(),sourceDataNode=this.getSourceDataForFilter();if(!sourceDataNode)return;filterValueNode.innerHTML=sourceDataNode.outerHTML;const dataSource=filterValueNode.querySelector("select");dataSource.id="filter-value-"+dataSource.getAttribute("data-field-name");const filterValueLabel=document.createElement("label");filterValueLabel.setAttribute("for",dataSource.id),filterValueLabel.classList.add("sr-only"),filterValueLabel.innerText=dataSource.getAttribute("data-field-title"),filterValueNode.appendChild(filterValueLabel),initialValues.forEach((filterValue=>{let selectedOption=dataSource.querySelector('option[value="'.concat(filterValue,'"]'));selectedOption?selectedOption.selected=!0:this.showSuggestions||(selectedOption=document.createElement("option"),selectedOption.value=filterValue,selectedOption.innerHTML=filterValue,selectedOption.selected=!0,dataSource.append(selectedOption))})),_formAutocomplete.default.enhance(dataSource,"1"==dataSource.dataset.allowCustom,null,await this.placeholder,!1,this.showSuggestions,null,!dataSource.multiple,{items:"core/datafilter/autocomplete_selection_items",layout:"core/datafilter/autocomplete_layout",selection:"core/datafilter/autocomplete_selection"})}get filterRoot(){return this.rootNode.querySelector(_selectors.default.filter.byName(this.filterType))}getSourceDataForFilter(){return this.rootNode.querySelector(_selectors.default.filterset.regions.datasource).querySelector(_selectors.default.data.fields.byName(this.filterType))}getFilterValueNode(){return this.filterRoot.querySelector(_selectors.default.filter.regions.values)}get name(){return this.filterType}get jointype(){return parseInt(this.filterRoot.querySelector(_selectors.default.filter.fields.join).value,10)}get rawValues(){const filterValueSelect=this.getFilterValueNode().querySelector("select");return Object.values((select=filterValueSelect,select.querySelectorAll(":checked"))).map((option=>option.value));var select}get values(){return this.rawValues.map((option=>parseInt(option,10)))}get filterOptions(){return[]}get filterValue(){return{name:this.name,jointype:this.jointype,values:this.values,filteroptions:this.filterOptions}}},_exports.default})); //# sourceMappingURL=filtertype.min.js.map \ No newline at end of file diff --git a/lib/amd/build/datafilter/filtertype.min.js.map b/lib/amd/build/datafilter/filtertype.min.js.map index a8b5c6eccf7..5316bcc380a 100644 --- a/lib/amd/build/datafilter/filtertype.min.js.map +++ b/lib/amd/build/datafilter/filtertype.min.js.map @@ -1 +1 @@ -{"version":3,"file":"filtertype.min.js","sources":["../../src/datafilter/filtertype.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 * Base Filter class for a filter type in the filter UI.\n *\n * @module core/datafilter/filtertype\n * @copyright 2020 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Autocomplete from 'core/form-autocomplete';\nimport Selectors from 'core/datafilter/selectors';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Fetch all checked options in the select.\n *\n * This is a poor-man's polyfill for select.selectedOptions, which is not available in IE11.\n *\n * @param {HTMLSelectElement} select\n * @returns {HTMLOptionElement[]} All selected options\n */\nconst getOptionsForSelect = select => {\n return select.querySelectorAll(':checked');\n};\n\nexport default class {\n\n /**\n * Constructor for a new filter.\n *\n * @param {String} filterType The type of filter that this relates to\n * @param {HTMLElement} rootNode The root node for the participants filterset\n * @param {Array} initialValues The initial values for the selector\n */\n constructor(filterType, rootNode, initialValues) {\n this.filterType = filterType;\n this.rootNode = rootNode;\n\n this.addValueSelector(initialValues);\n }\n\n /**\n * Perform any tear-down for this filter type.\n */\n tearDown() {\n // eslint-disable-line no-empty-function\n }\n\n /**\n * Get the placeholder to use when showing the value selector.\n *\n * @return {Promise} Resolving to a String\n */\n get placeholder() {\n return getString('placeholdertypeorselect', 'core');\n }\n\n /**\n * Whether to show suggestions in the autocomplete.\n *\n * @return {Boolean}\n */\n get showSuggestions() {\n return true;\n }\n\n /**\n * Add the value selector to the filter row.\n *\n * @param {Array} initialValues\n */\n async addValueSelector(initialValues = []) {\n const filterValueNode = this.getFilterValueNode();\n\n // Copy the data in place.\n const sourceDataNode = this.getSourceDataForFilter();\n if (!sourceDataNode) {\n return;\n }\n filterValueNode.innerHTML = sourceDataNode.outerHTML;\n\n const dataSource = filterValueNode.querySelector('select');\n\n // Set an ID for this filter value element.\n dataSource.id = 'filter-value-' + dataSource.getAttribute('data-field-name');\n\n // Create a hidden label for the filter value.\n const filterValueLabel = document.createElement('label');\n filterValueLabel.setAttribute('for', dataSource.id);\n filterValueLabel.classList.add('sr-only');\n filterValueLabel.innerText = dataSource.getAttribute('data-field-title');\n\n // Append this label to the filter value container.\n filterValueNode.appendChild(filterValueLabel);\n\n // If there are any initial values then attempt to apply them.\n initialValues.forEach(filterValue => {\n let selectedOption = dataSource.querySelector(`option[value=\"${filterValue}\"]`);\n if (selectedOption) {\n selectedOption.selected = true;\n } else if (!this.showSuggestions) {\n selectedOption = document.createElement('option');\n selectedOption.value = filterValue;\n selectedOption.innerHTML = filterValue;\n selectedOption.selected = true;\n\n dataSource.append(selectedOption);\n }\n });\n\n Autocomplete.enhance(\n // The source select element.\n dataSource,\n\n // Whether to allow 'tags' (custom entries).\n dataSource.dataset.allowCustom == \"1\",\n\n // We do not require AJAX at all as standard.\n null,\n\n // The string to use as a placeholder.\n await this.placeholder,\n\n // Disable case sensitivity on searches.\n false,\n\n // Show suggestions.\n this.showSuggestions,\n\n // Do not override the 'no suggestions' string.\n null,\n\n // Close the suggestions if this is not a multi-select.\n !dataSource.multiple,\n\n // Template overrides.\n {\n items: 'core/datafilter/autocomplete_selection_items',\n layout: 'core/datafilter/autocomplete_layout',\n selection: 'core/datafilter/autocomplete_selection',\n }\n );\n }\n\n /**\n * Get the root node for this filter.\n *\n * @returns {HTMLElement}\n */\n get filterRoot() {\n return this.rootNode.querySelector(Selectors.filter.byName(this.filterType));\n }\n\n /**\n * Get the possible data for this filter type.\n *\n * @returns {Array}\n */\n getSourceDataForFilter() {\n const filterDataNode = this.rootNode.querySelector(Selectors.filterset.regions.datasource);\n\n return filterDataNode.querySelector(Selectors.data.fields.byName(this.filterType));\n }\n\n /**\n * Get the HTMLElement which contains the value selector.\n *\n * @returns {HTMLElement}\n */\n getFilterValueNode() {\n return this.filterRoot.querySelector(Selectors.filter.regions.values);\n }\n\n /**\n * Get the name of this filter.\n *\n * @returns {String}\n */\n get name() {\n return this.filterType;\n }\n\n /**\n * Get the type of join specified.\n *\n * @returns {Number}\n */\n get jointype() {\n return parseInt(this.filterRoot.querySelector(Selectors.filter.fields.join).value, 10);\n }\n\n /**\n * Get the list of raw values for this filter type.\n *\n * @returns {Array}\n */\n get rawValues() {\n const filterValueNode = this.getFilterValueNode();\n const filterValueSelect = filterValueNode.querySelector('select');\n\n return Object.values(getOptionsForSelect(filterValueSelect)).map(option => option.value);\n }\n\n /**\n * Get the list of values for this filter type.\n *\n * @returns {Array}\n */\n get values() {\n return this.rawValues.map(option => parseInt(option, 10));\n }\n\n /**\n * Get the composed value for this filter.\n *\n * @returns {Object}\n */\n get filterValue() {\n return {\n name: this.name,\n jointype: this.jointype,\n values: this.values,\n };\n }\n}\n"],"names":["constructor","filterType","rootNode","initialValues","addValueSelector","tearDown","placeholder","showSuggestions","filterValueNode","this","getFilterValueNode","sourceDataNode","getSourceDataForFilter","innerHTML","outerHTML","dataSource","querySelector","id","getAttribute","filterValueLabel","document","createElement","setAttribute","classList","add","innerText","appendChild","forEach","filterValue","selectedOption","selected","value","append","enhance","dataset","allowCustom","multiple","items","layout","selection","filterRoot","Selectors","filter","byName","filterset","regions","datasource","data","fields","values","name","jointype","parseInt","join","rawValues","filterValueSelect","Object","select","querySelectorAll","map","option"],"mappings":";;;;;;;6NA+CIA,YAAYC,WAAYC,SAAUC,oBACzBF,WAAaA,gBACbC,SAAWA,cAEXE,iBAAiBD,eAM1BE,YASIC,yBACO,mBAAU,0BAA2B,QAQ5CC,6BACO,+BAQYJ,qEAAgB,SAC7BK,gBAAkBC,KAAKC,qBAGvBC,eAAiBF,KAAKG,6BACvBD,sBAGLH,gBAAgBK,UAAYF,eAAeG,gBAErCC,WAAaP,gBAAgBQ,cAAc,UAGjDD,WAAWE,GAAK,gBAAkBF,WAAWG,aAAa,yBAGpDC,iBAAmBC,SAASC,cAAc,SAChDF,iBAAiBG,aAAa,MAAOP,WAAWE,IAChDE,iBAAiBI,UAAUC,IAAI,WAC/BL,iBAAiBM,UAAYV,WAAWG,aAAa,oBAGrDV,gBAAgBkB,YAAYP,kBAG5BhB,cAAcwB,SAAQC,kBACdC,eAAiBd,WAAWC,sCAA+BY,mBAC3DC,eACAA,eAAeC,UAAW,EAClBrB,KAAKF,kBACbsB,eAAiBT,SAASC,cAAc,UACxCQ,eAAeE,MAAQH,YACvBC,eAAehB,UAAYe,YAC3BC,eAAeC,UAAW,EAE1Bf,WAAWiB,OAAOH,8CAIbI,QAETlB,WAGkC,KAAlCA,WAAWmB,QAAQC,YAGnB,WAGM1B,KAAKH,aAGX,EAGAG,KAAKF,gBAGL,MAGCQ,WAAWqB,SAGZ,CACIC,MAAO,+CACPC,OAAQ,sCACRC,UAAW,2CAUnBC,wBACO/B,KAAKP,SAASc,cAAcyB,mBAAUC,OAAOC,OAAOlC,KAAKR,aAQpEW,gCAC2BH,KAAKP,SAASc,cAAcyB,mBAAUG,UAAUC,QAAQC,YAEzD9B,cAAcyB,mBAAUM,KAAKC,OAAOL,OAAOlC,KAAKR,aAQ1ES,4BACWD,KAAK+B,WAAWxB,cAAcyB,mBAAUC,OAAOG,QAAQI,QAQ9DC,kBACOzC,KAAKR,WAQZkD,sBACOC,SAAS3C,KAAK+B,WAAWxB,cAAcyB,mBAAUC,OAAOM,OAAOK,MAAMtB,MAAO,IAQnFuB,sBAEMC,kBADkB9C,KAAKC,qBACaM,cAAc,iBAEjDwC,OAAOP,QAnLMQ,OAmLqBF,kBAlLtCE,OAAOC,iBAAiB,cAkLkCC,KAAIC,QAAUA,OAAO7B,QAnL9D0B,IAAAA,OA2LpBR,oBACOxC,KAAK6C,UAAUK,KAAIC,QAAUR,SAASQ,OAAQ,MAQrDhC,wBACO,CACHsB,KAAMzC,KAAKyC,KACXC,SAAU1C,KAAK0C,SACfF,OAAQxC,KAAKwC"} \ No newline at end of file +{"version":3,"file":"filtertype.min.js","sources":["../../src/datafilter/filtertype.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 * Base Filter class for a filter type in the filter UI.\n *\n * @module core/datafilter/filtertype\n * @copyright 2020 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Autocomplete from 'core/form-autocomplete';\nimport Selectors from 'core/datafilter/selectors';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Fetch all checked options in the select.\n *\n * This is a poor-man's polyfill for select.selectedOptions, which is not available in IE11.\n *\n * @param {HTMLSelectElement} select\n * @returns {HTMLOptionElement[]} All selected options\n */\nconst getOptionsForSelect = select => {\n return select.querySelectorAll(':checked');\n};\n\nexport default class {\n\n /**\n * Constructor for a new filter.\n *\n * @param {String} filterType The type of filter that this relates to\n * @param {HTMLElement} rootNode The root node for the participants filterset\n * @param {Array} initialValues The initial values for the selector\n */\n constructor(filterType, rootNode, initialValues) {\n this.filterType = filterType;\n this.rootNode = rootNode;\n\n this.addValueSelector(initialValues);\n }\n\n /**\n * Perform any tear-down for this filter type.\n */\n tearDown() {\n // eslint-disable-line no-empty-function\n }\n\n /**\n * Get the placeholder to use when showing the value selector.\n *\n * @return {Promise} Resolving to a String\n */\n get placeholder() {\n return getString('placeholdertypeorselect', 'core');\n }\n\n /**\n * Whether to show suggestions in the autocomplete.\n *\n * @return {Boolean}\n */\n get showSuggestions() {\n return true;\n }\n\n /**\n * Add the value selector to the filter row.\n *\n * @param {Array} initialValues\n */\n async addValueSelector(initialValues = []) {\n const filterValueNode = this.getFilterValueNode();\n\n // Copy the data in place.\n const sourceDataNode = this.getSourceDataForFilter();\n if (!sourceDataNode) {\n return;\n }\n filterValueNode.innerHTML = sourceDataNode.outerHTML;\n\n const dataSource = filterValueNode.querySelector('select');\n\n // Set an ID for this filter value element.\n dataSource.id = 'filter-value-' + dataSource.getAttribute('data-field-name');\n\n // Create a hidden label for the filter value.\n const filterValueLabel = document.createElement('label');\n filterValueLabel.setAttribute('for', dataSource.id);\n filterValueLabel.classList.add('sr-only');\n filterValueLabel.innerText = dataSource.getAttribute('data-field-title');\n\n // Append this label to the filter value container.\n filterValueNode.appendChild(filterValueLabel);\n\n // If there are any initial values then attempt to apply them.\n initialValues.forEach(filterValue => {\n let selectedOption = dataSource.querySelector(`option[value=\"${filterValue}\"]`);\n if (selectedOption) {\n selectedOption.selected = true;\n } else if (!this.showSuggestions) {\n selectedOption = document.createElement('option');\n selectedOption.value = filterValue;\n selectedOption.innerHTML = filterValue;\n selectedOption.selected = true;\n\n dataSource.append(selectedOption);\n }\n });\n\n Autocomplete.enhance(\n // The source select element.\n dataSource,\n\n // Whether to allow 'tags' (custom entries).\n dataSource.dataset.allowCustom == \"1\",\n\n // We do not require AJAX at all as standard.\n null,\n\n // The string to use as a placeholder.\n await this.placeholder,\n\n // Disable case sensitivity on searches.\n false,\n\n // Show suggestions.\n this.showSuggestions,\n\n // Do not override the 'no suggestions' string.\n null,\n\n // Close the suggestions if this is not a multi-select.\n !dataSource.multiple,\n\n // Template overrides.\n {\n items: 'core/datafilter/autocomplete_selection_items',\n layout: 'core/datafilter/autocomplete_layout',\n selection: 'core/datafilter/autocomplete_selection',\n }\n );\n }\n\n /**\n * Get the root node for this filter.\n *\n * @returns {HTMLElement}\n */\n get filterRoot() {\n return this.rootNode.querySelector(Selectors.filter.byName(this.filterType));\n }\n\n /**\n * Get the possible data for this filter type.\n *\n * @returns {Array}\n */\n getSourceDataForFilter() {\n const filterDataNode = this.rootNode.querySelector(Selectors.filterset.regions.datasource);\n\n return filterDataNode.querySelector(Selectors.data.fields.byName(this.filterType));\n }\n\n /**\n * Get the HTMLElement which contains the value selector.\n *\n * @returns {HTMLElement}\n */\n getFilterValueNode() {\n return this.filterRoot.querySelector(Selectors.filter.regions.values);\n }\n\n /**\n * Get the name of this filter.\n *\n * @returns {String}\n */\n get name() {\n return this.filterType;\n }\n\n /**\n * Get the type of join specified.\n *\n * @returns {Number}\n */\n get jointype() {\n return parseInt(this.filterRoot.querySelector(Selectors.filter.fields.join).value, 10);\n }\n\n /**\n * Get the list of raw values for this filter type.\n *\n * @returns {Array}\n */\n get rawValues() {\n const filterValueNode = this.getFilterValueNode();\n const filterValueSelect = filterValueNode.querySelector('select');\n\n return Object.values(getOptionsForSelect(filterValueSelect)).map(option => option.value);\n }\n\n /**\n * Get the list of values for this filter type.\n *\n * @returns {Array}\n */\n get values() {\n return this.rawValues.map(option => parseInt(option, 10));\n }\n\n /**\n * Get options specific to this filter type.\n *\n * @returns {Array} of {name:, value:} objects\n */\n get filterOptions() {\n return [];\n }\n\n /**\n * Get the composed value for this filter.\n *\n * @returns {Object}\n */\n get filterValue() {\n return {\n name: this.name,\n jointype: this.jointype,\n values: this.values,\n filteroptions: this.filterOptions,\n };\n }\n}\n"],"names":["constructor","filterType","rootNode","initialValues","addValueSelector","tearDown","placeholder","showSuggestions","filterValueNode","this","getFilterValueNode","sourceDataNode","getSourceDataForFilter","innerHTML","outerHTML","dataSource","querySelector","id","getAttribute","filterValueLabel","document","createElement","setAttribute","classList","add","innerText","appendChild","forEach","filterValue","selectedOption","selected","value","append","enhance","dataset","allowCustom","multiple","items","layout","selection","filterRoot","Selectors","filter","byName","filterset","regions","datasource","data","fields","values","name","jointype","parseInt","join","rawValues","filterValueSelect","Object","select","querySelectorAll","map","option","filterOptions","filteroptions"],"mappings":";;;;;;;6NA+CIA,YAAYC,WAAYC,SAAUC,oBACzBF,WAAaA,gBACbC,SAAWA,cAEXE,iBAAiBD,eAM1BE,YASIC,yBACO,mBAAU,0BAA2B,QAQ5CC,6BACO,+BAQYJ,qEAAgB,SAC7BK,gBAAkBC,KAAKC,qBAGvBC,eAAiBF,KAAKG,6BACvBD,sBAGLH,gBAAgBK,UAAYF,eAAeG,gBAErCC,WAAaP,gBAAgBQ,cAAc,UAGjDD,WAAWE,GAAK,gBAAkBF,WAAWG,aAAa,yBAGpDC,iBAAmBC,SAASC,cAAc,SAChDF,iBAAiBG,aAAa,MAAOP,WAAWE,IAChDE,iBAAiBI,UAAUC,IAAI,WAC/BL,iBAAiBM,UAAYV,WAAWG,aAAa,oBAGrDV,gBAAgBkB,YAAYP,kBAG5BhB,cAAcwB,SAAQC,kBACdC,eAAiBd,WAAWC,sCAA+BY,mBAC3DC,eACAA,eAAeC,UAAW,EAClBrB,KAAKF,kBACbsB,eAAiBT,SAASC,cAAc,UACxCQ,eAAeE,MAAQH,YACvBC,eAAehB,UAAYe,YAC3BC,eAAeC,UAAW,EAE1Bf,WAAWiB,OAAOH,8CAIbI,QAETlB,WAGkC,KAAlCA,WAAWmB,QAAQC,YAGnB,WAGM1B,KAAKH,aAGX,EAGAG,KAAKF,gBAGL,MAGCQ,WAAWqB,SAGZ,CACIC,MAAO,+CACPC,OAAQ,sCACRC,UAAW,2CAUnBC,wBACO/B,KAAKP,SAASc,cAAcyB,mBAAUC,OAAOC,OAAOlC,KAAKR,aAQpEW,gCAC2BH,KAAKP,SAASc,cAAcyB,mBAAUG,UAAUC,QAAQC,YAEzD9B,cAAcyB,mBAAUM,KAAKC,OAAOL,OAAOlC,KAAKR,aAQ1ES,4BACWD,KAAK+B,WAAWxB,cAAcyB,mBAAUC,OAAOG,QAAQI,QAQ9DC,kBACOzC,KAAKR,WAQZkD,sBACOC,SAAS3C,KAAK+B,WAAWxB,cAAcyB,mBAAUC,OAAOM,OAAOK,MAAMtB,MAAO,IAQnFuB,sBAEMC,kBADkB9C,KAAKC,qBACaM,cAAc,iBAEjDwC,OAAOP,QAnLMQ,OAmLqBF,kBAlLtCE,OAAOC,iBAAiB,cAkLkCC,KAAIC,QAAUA,OAAO7B,QAnL9D0B,IAAAA,OA2LpBR,oBACOxC,KAAK6C,UAAUK,KAAIC,QAAUR,SAASQ,OAAQ,MAQrDC,0BACO,GAQPjC,wBACO,CACHsB,KAAMzC,KAAKyC,KACXC,SAAU1C,KAAK0C,SACfF,OAAQxC,KAAKwC,OACba,cAAerD,KAAKoD"} \ No newline at end of file diff --git a/lib/amd/src/datafilter/filtertype.js b/lib/amd/src/datafilter/filtertype.js index c424518e9cd..ee9867aab15 100644 --- a/lib/amd/src/datafilter/filtertype.js +++ b/lib/amd/src/datafilter/filtertype.js @@ -223,6 +223,15 @@ export default class { return this.rawValues.map(option => parseInt(option, 10)); } + /** + * Get options specific to this filter type. + * + * @returns {Array} of {name:, value:} objects + */ + get filterOptions() { + return []; + } + /** * Get the composed value for this filter. * @@ -233,6 +242,7 @@ export default class { name: this.name, jointype: this.jointype, values: this.values, + filteroptions: this.filterOptions, }; } } diff --git a/lib/classes/output/datafilter.php b/lib/classes/output/datafilter.php index 35c1ff27a52..2d62d3a1482 100644 --- a/lib/classes/output/datafilter.php +++ b/lib/classes/output/datafilter.php @@ -81,7 +81,8 @@ abstract class datafilter implements renderable, templatable { bool $multiple, ?string $filterclass, array $values, - bool $allowempty = false + bool $allowempty = false, + ?stdClass $filteroptions = null ): ?stdClass { if (!$allowempty && empty($values)) { @@ -96,6 +97,7 @@ abstract class datafilter implements renderable, templatable { 'allowmultiple' => $multiple, 'filtertypeclass' => $filterclass, 'values' => $values, + 'filteroptions' => $filteroptions, ]; } } diff --git a/lib/table/classes/external/dynamic/get.php b/lib/table/classes/external/dynamic/get.php index 0b6b3893785..32fbce7e5e0 100644 --- a/lib/table/classes/external/dynamic/get.php +++ b/lib/table/classes/external/dynamic/get.php @@ -82,7 +82,15 @@ class get extends external_api { new external_value(PARAM_RAW, 'Filter value'), 'The value to filter on', VALUE_REQUIRED - ) + ), + 'filteroptions' => new external_multiple_structure( + new external_single_structure([ + 'name' => new external_value(PARAM_ALPHANUM, 'Name of the filter option', VALUE_REQUIRED), + 'value' => new external_value(PARAM_RAW, 'Value of the filter option', VALUE_REQUIRED), + ]), + 'Additional options for this filter', + VALUE_OPTIONAL, + ), ]), 'The filters that will be applied in the request', VALUE_OPTIONAL diff --git a/lib/upgrade.txt b/lib/upgrade.txt index d1c97007233..0581d611e28 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -87,6 +87,9 @@ information provided here is intended especially for developers. to ensure in some test that the block drawer is closed. This helps with random failures due to the block drawer being forced open in all behat tests. * The core_useragent::get_device_type_list() function has been deprecated. Use core_useragent::devicetypes instead as a replacement. +* New `filteroptions` field added to getFilterValue() in core/datafilter/filtertype. This is generated by `get filterOptions()` + and returns an arbitrary list of options specific to the filter type, in [{name:, value}] format. This allows filters to extend + the values returned with additional fields. === 4.2 ===