1import BaseController from 'common/controllers/base_controller' 2import URI from 'urijs' 3 4export default class extends BaseController { 5 static targets = ['pageBlock', 'form', 'checkbox', 'dropdown', 'sort', 'activeFilter', 'freetext', 'jobsSearchResults'] 6 7 connect() { 8 window.addEventListener('popstate', (e) => { 9 if (e.state && e.state.newHtml) { 10 Turbo.renderStreamMessage(e.state.newHtml) 11 } 12 requestAnimationFrame(() => { 13 this.updateFilterCheckboxes() 14 }) 15 }) 16 this.markConnected() 17 } 18 19 clearFilters() { 20 this.freetextTarget.value = '' 21 for (const checkboxTarget of this.checkboxTargets) { 22 checkboxTarget.checked = false 23 } 24 for (const dropdownTarget of this.dropdownTargets) { 25 dropdownTarget.options.selectedIndex = 0 26 } 27 this.filterChange() 28 } 29 30 clearMobileFilters() { 31 for (const dropdownTarget of this.dropdownTargets) { 32 for (const option of dropdownTarget.options) option.selected = false 33 } 34 this.filterChange() 35 } 36 37 sortJobs(event) { 38 this.sortTarget.value = event.target.value 39 this.findSearchJobResults(() => this.refocusSearchJobResults()) 40 } 41 42 filterChange() { 43 this.findSearchJobResults() 44 } 45 46 submitForm(e) { 47 e.preventDefault() 48 this.findSearchJobResults() 49 } 50 51 findSearchJobResults(callback) { 52 const jobSearchParams = this.convertFormDataToQueryParams(new FormData(this.formTarget)) 53 const jobSearchUrl = this.formTarget.action 54 const jobSearchUrlWithParams = URI(jobSearchUrl).search(jobSearchParams).toString() 55 fetch(jobSearchUrlWithParams, {headers: {Accept: 'text/vnd.turbo-stream.html'}}
55) 56 .then(response => response.text()) 57 .then(html => this.replaceSearchPage(jobSearchUrl, html, callback)) 58 59 document.dispatchEvent(new CustomEvent('clinch:job_search_results_updated', {detail: {jobSearchParamsAsJson: JSON.stringify(jobSearchParams)}})) 60 } 61 62 closeActiveFilters(event) { 63 const activeFilter = event.target.closest(".active-filter") 64 const checkbox = this.checkboxTargets.find((a) => a.id === activeFilter.dataset.filterId) 65 if (checkbox) { 66 checkbox.checked = false 67 } 68 activeFilter.classList.add("d-none") 69 } 70 71 replaceSearchPage(baseUrl, newHtml, callback) { 72 Turbo.renderStreamMessage(newHtml) 73 this.recordLocalHistoryState(baseUrl, newHtml) 74 if (callback) { 75 callback() 76 } 77 } 78 79 //there's a lot of manual coding going on here - think we could do better with some simpler Turbo stream code 80 recordLocalHistoryState(baseUrl, newHtml) { 81 const blockUid = this.pageBlockTarget.dataset.uid 82 const historyUrl = URI(baseUrl).search(this.serializeFormHistoricalInputs()).toString() 83 history.pushState({ 84 uid: blockUid, 85 newHtml: newHtml, 86 }, document.title, historyUrl) 87 } 88 89 serializeFormHistoricalInputs() { 90 const formData = new FormData() 91 for (const input of this.formTarget.querySelectorAll("input[type='hidden'].historical,input[type='text'].historical,input[type='checkbox'].historical:checked")) { 92 formData.append(input.name, input.value) 93 } 94 for (const input of this.formTarget.querySelectorAll("select.historical")) { 95 if (input.value !== '') { 96 formData.append(input.name, input.value) 97 } 98 } 99 return this.convertFormDataToQueryParams(formData) 100 } 101 102 convertFormDataToQueryParams(form) { 103 const formQueryParams = {} 104 for (const [key, value] of form.entries()) { 105 if (!Reflect.has(formQueryParams, key)) { 106 formQueryParams[key] = value 107 } else { 108 //convert the existing value to an array and add the new one 109 if (!Array.isArray(formQueryParams[key])) { 110 formQueryParams[key] = [formQueryParams[key]] 111 } 112 formQueryParams[key].push(value) 113 } 114 } 115 return formQueryParams 116 } 117 118 refocusSearchJobResults() { 119 // requestAnimationFrame is used to ensure document updates occur before focusing 120 requestAnimationFrame(() => { 121 this.jobsSearchResultsTarget.focus() 122 }) 123 } 124 125 updateFilterCheckboxes() { 126 const params = new URLSearchParams(window.location.search) 127 this.checkboxTargets.forEach((checkbox) => {checkbox.checked = params.getAll(checkbox.name).includes(checkbox.value)}) 128 } 129}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.