X7ROOT File Manager
Current Path:
/home/cbholdings/pasukulu/grade/report/grader/amd/build/search
home
/
cbholdings
/
pasukulu
/
grade
/
report
/
grader
/
amd
/
build
/
search
/
📁
..
📄
repository.min.js
(698 B)
📄
repository.min.js.map
(1.67 KB)
📄
search_class.min.js
(7.53 KB)
📄
search_class.min.js.map
(19.75 KB)
Editing: search_class.min.js.map
{"version":3,"file":"search_class.min.js","sources":["../../src/search/search_class.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\nimport $ from 'jquery';\nimport CustomEvents from \"core/custom_interaction_events\";\nimport {debounce} from 'core/utils';\n\n/**\n * The class that manages the state of the search.\n *\n * @module gradereport_grader/search/search_class\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n// Reused variables for the class.\nconst events = [\n 'keydown',\n CustomEvents.events.activate,\n CustomEvents.events.keyboardActivate\n];\nconst UP = -1;\nconst DOWN = 1;\n\nexport default class {\n // Define our standard lookups.\n selectors = {\n component: this.setComponentSelector(),\n trigger: this.setTriggerSelector(),\n input: '[data-action=\"search\"]',\n clearSearch: '[data-action=\"clearsearch\"]',\n dropdown: this.setDropdownSelector(),\n resultitems: '[role=\"option\"]',\n viewall: '#select-all',\n };\n\n // The results from the called filter function.\n matchedResults = [];\n\n // What did the user search for?\n searchTerm = '';\n\n // What the user searched for as a lowercase.\n preppedSearchTerm = null;\n\n // The DOM nodes after the dropdown render.\n resultNodes = [];\n\n // Where does the user currently have focus?\n currentNode = null;\n\n // The current node for the view all link.\n currentViewAll = null;\n\n dataset = null;\n\n datasetSize = 0;\n\n // DOM nodes that persist.\n component = document.querySelector(this.selectors.component);\n searchInput = this.component.querySelector(this.selectors.input);\n searchDropdown = this.component.querySelector(this.selectors.dropdown);\n $searchButton = $(this.selectors.trigger);\n clearSearchButton = this.component.querySelector(this.selectors.clearSearch);\n $component = $(this.component);\n\n constructor() {\n // If we have a search input, try to get the value otherwise fallback.\n this.setSearchTerms(this.searchInput?.value ?? '');\n // Begin handling the base search component.\n this.registerClickHandlers();\n this.registerKeyHandlers();\n // Conditionally set up the input handler since we don't know exactly how we were called.\n if (this.searchInput !== null) {\n this.registerInputHandlers();\n }\n }\n\n /**\n * Stub out a required function.\n */\n fetchDataset() {\n throw new Error(`fetchDataset() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Stub out a required function.\n * @param {Array} dataset\n */\n filterDataset(dataset) {\n throw new Error(`filterDataset(${dataset}) must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Stub out a required function.\n */\n filterMatchDataset() {\n throw new Error(`filterMatchDataset() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Stub out a required function.\n */\n renderDropdown() {\n throw new Error(`renderDropdown() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Stub out a required function.\n */\n setComponentSelector() {\n throw new Error(`setComponentSelector() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Stub out a required function.\n */\n setDropdownSelector() {\n throw new Error(`setDropdownSelector() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Stub out a required function.\n */\n setTriggerSelector() {\n throw new Error(`setTriggerSelector() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Return the dataset that we will be searching upon.\n *\n * @returns {Promise<null>}\n */\n async getDataset() {\n if (!this.dataset) {\n this.dataset = await this.fetchDataset();\n }\n this.datasetSize = this.dataset.length;\n return this.dataset;\n }\n\n /**\n * Return the size of the dataset.\n *\n * @returns {number}\n */\n getDatasetSize() {\n return this.datasetSize;\n }\n\n /**\n * Return the results of the filter upon the dataset.\n *\n * @returns {Array}\n */\n getMatchedResults() {\n return this.matchedResults;\n }\n\n /**\n * Given a filter has been run across the dataset, store the matched results.\n *\n * @param {Array} result\n */\n setMatchedResults(result) {\n this.matchedResults = result;\n }\n\n /**\n * Get the value that the user entered.\n *\n * @returns {string}\n */\n getSearchTerm() {\n return this.searchTerm;\n }\n\n /**\n * Get the transformed search value.\n *\n * @returns {string}\n */\n getPreppedSearchTerm() {\n return this.preppedSearchTerm;\n }\n\n /**\n * When a user searches for something, set our variable to manage it.\n *\n * @param {string} result\n */\n setSearchTerms(result) {\n this.searchTerm = result;\n this.preppedSearchTerm = result.toLowerCase();\n }\n\n /**\n * Return an object containing a handfull of dom nodes that we sometimes need the value of.\n *\n * @returns {object}\n */\n getHTMLElements() {\n this.updateNodes();\n return {\n searchDropdown: this.searchDropdown,\n currentViewAll: this.currentViewAll,\n searchInput: this.searchInput,\n clearSearchButton: this.clearSearchButton\n };\n }\n\n /**\n * When called, close the dropdown and reset the input field attributes.\n *\n * @param {Boolean} clear Conditionality clear the input box.\n */\n closeSearch(clear = false) {\n this.toggleDropdown();\n // Hide the \"clear\" search button search bar.\n this.clearSearchButton.classList.add('d-none');\n if (clear) {\n // Clear the entered search query in the search bar and hide the search results container.\n this.setSearchTerms('');\n this.searchInput.value = \"\";\n }\n }\n\n /**\n * When called, update the dropdown fields.\n *\n * @param {Boolean} on Flag to toggle hiding or showing values.\n */\n toggleDropdown(on = false) {\n this.$component.dropdown('toggle');\n this.$searchButton.attr('aria-expanded', on);\n if (on) {\n this.searchDropdown.classList.add('show');\n $(this.searchDropdown).show();\n } else {\n this.searchDropdown.classList.remove('show');\n $(this.searchDropdown).hide();\n }\n }\n\n /**\n * These class members change when a new result set is rendered. So update for fresh data.\n */\n updateNodes() {\n this.resultNodes = [...this.component.querySelectorAll(this.selectors.resultitems)];\n this.currentNode = this.resultNodes.find(r => r.id === document.activeElement.id);\n this.currentViewAll = this.component.querySelector(this.selectors.viewall);\n this.clearSearchButton = this.component.querySelector(this.selectors.clearSearch);\n this.searchInput = this.component.querySelector(this.selectors.input);\n this.searchDropdown = this.component.querySelector(this.selectors.dropdown);\n }\n\n /**\n * Register clickable event listeners.\n */\n registerClickHandlers() {\n // Prevent the click triggering the dropdown.\n this.$searchButton.on('click', () => {\n this.toggleDropdown();\n });\n\n // Register click events within the component.\n this.component.addEventListener('click', this.clickHandler.bind(this));\n\n // Register a small click event onto the document since we need to check if they are clicking off the component.\n document.addEventListener('click', (e) => {\n // Since we are handling dropdowns manually, ensure we can close it when clicking off.\n if (!e.target.closest(this.selectors.component) && this.searchDropdown.classList.contains('show')) {\n this.toggleDropdown();\n }\n });\n }\n\n /**\n * Register key event listeners.\n */\n registerKeyHandlers() {\n CustomEvents.define(document, events);\n\n // Register click events.\n events.forEach((event) => {\n this.component.addEventListener(event, this.keyHandler.bind(this));\n });\n }\n\n /**\n * Register 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 this.toggleDropdown();\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 await this.renderAndShow();\n }\n }, 300));\n }\n\n /**\n * A combo method to take the matching fields and render out the results.\n *\n * @returns {Promise<void>}\n */\n async renderAndShow() {\n // User has given something for us to filter against.\n this.setMatchedResults(await this.filterDataset(await this.getDataset()));\n await this.filterMatchDataset();\n // Replace the dropdown node contents and show the results.\n await this.renderDropdown();\n // Set the dropdown to open.\n this.toggleDropdown(true);\n }\n\n /**\n * Set the current focus either on the preceding or next result item.\n *\n * @param {Number} direction Is the user moving up or down the resultset?\n * @param {KeyboardEvent} e The JS event from the event handler.\n */\n keyUpDown(direction, e) {\n e.preventDefault();\n // Stop Bootstrap from being clever.\n e.stopPropagation();\n // Current focus is on the input box so depending on direction, go to the top or the bottom of the displayed results.\n if (document.activeElement === this.searchInput && this.resultNodes.length > 0) {\n if (direction === UP) {\n this.moveToLastNode();\n } else {\n this.moveToFirstNode();\n }\n }\n const index = this.resultNodes.indexOf(this.currentNode);\n if (this.currentNode) {\n if (direction === UP) {\n if (index === 0) {\n this.moveToLastNode();\n } else {\n this.moveToNode(index - 1);\n }\n } else {\n if (index + 1 >= this.resultNodes.length) {\n this.moveToFirstNode();\n } else {\n this.moveToNode(index + 1);\n }\n }\n } else {\n if (direction === UP) {\n this.moveToLastNode();\n } else {\n this.moveToFirstNode();\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 this.updateNodes();\n\n // Prevent normal key presses activating this.\n if (e.target.closest('.dropdown-item') && e.button === 0) {\n window.location = e.target.closest('.dropdown-item').href;\n }\n // The \"clear search\" button is triggered.\n if (e.target.closest(this.selectors.clearSearch) && e.button === 0) {\n this.closeSearch(true);\n this.searchInput.focus({preventScroll: true});\n }\n // User may have accidentally clicked off the dropdown and wants to reopen it.\n if (e.target.closest(this.selectors.input) && this.getSearchTerm() !== '' && e.button === 0) {\n await this.renderAndShow();\n }\n }\n\n /**\n * The handler for when a user presses a key within the component.\n *\n * @param {KeyboardEvent} e The triggering event that we are working with.\n */\n keyHandler(e) {\n this.updateNodes();\n // Switch the key presses to handle keyboard nav.\n switch (e.key) {\n case 'ArrowUp':\n this.keyUpDown(UP, e);\n break;\n case 'ArrowDown':\n this.keyUpDown(DOWN, e);\n break;\n case 'Home':\n e.preventDefault();\n this.moveToFirstNode();\n break;\n case 'End':\n e.preventDefault();\n this.moveToLastNode();\n break;\n case 'Tab':\n // If the current focus is on the view all link, then close the widget then set focus on the next tertiary nav item.\n if (e.target.closest(this.selectors.viewall)) {\n this.closeSearch();\n }\n break;\n }\n }\n\n /**\n * Set focus on a given node after parsed through the calling functions.\n *\n * @param {HTMLElement} node The node to set focus upon.\n */\n selectNode = (node) => {\n node.focus({preventScroll: true});\n this.searchDropdown.scrollTop = node.offsetTop - (node.clientHeight / 2);\n };\n\n /**\n * Set the focus on the first node within the array.\n */\n moveToFirstNode = () => {\n if (this.resultNodes.length > 0) {\n this.selectNode(this.resultNodes[0]);\n }\n };\n\n /**\n * Set the focus to the final node within the array.\n */\n moveToLastNode = () => {\n if (this.resultNodes.length > 0) {\n this.selectNode(this.resultNodes[this.resultNodes.length - 1]);\n }\n };\n\n /**\n * Set focus on any given specified node within the node array.\n *\n * @param {Number} index Which item within the array to set focus upon.\n */\n moveToNode = (index) => {\n if (this.resultNodes.length > 0) {\n this.selectNode(this.resultNodes[index]);\n }\n };\n}\n"],"names":["events","activate","CustomEvents","keyboardActivate","constructor","component","this","setComponentSelector","trigger","setTriggerSelector","input","clearSearch","dropdown","setDropdownSelector","resultitems","viewall","document","querySelector","selectors","node","focus","preventScroll","searchDropdown","scrollTop","offsetTop","clientHeight","resultNodes","length","selectNode","index","setSearchTerms","searchInput","_this$searchInput","value","registerClickHandlers","registerKeyHandlers","registerInputHandlers","fetchDataset","Error","name","filterDataset","dataset","filterMatchDataset","renderDropdown","datasetSize","getDatasetSize","getMatchedResults","matchedResults","setMatchedResults","result","getSearchTerm","searchTerm","getPreppedSearchTerm","preppedSearchTerm","toLowerCase","getHTMLElements","updateNodes","currentViewAll","clearSearchButton","closeSearch","clear","toggleDropdown","classList","add","on","$component","$searchButton","attr","show","remove","hide","querySelectorAll","currentNode","find","r","id","activeElement","addEventListener","clickHandler","bind","e","target","closest","contains","define","forEach","event","keyHandler","async","renderAndShow","getDataset","keyUpDown","direction","preventDefault","stopPropagation","moveToLastNode","moveToFirstNode","indexOf","moveToNode","button","window","location","href","key"],"mappings":"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"}
Upload File
Create Folder