https://www.neuehofburg.at/_assets/5e439985603ece5f8b37fa61dd03305…/suggest_controller.js?1791375810
1function SuggestController() { 2 3 const _self = this; 4 5 this.run = () => { 6 if ('interactive' === document.readyState || 'complete' === document.readyState) { 7 _initialize(); 8 } else { 9 document.addEventListener('DOMContentLoaded', _initialize, {once: true}); 10 } 11 jQuery('body').on('tx_solr_updated', _initialize); 12 }; 13 14 this.initializeForm = (form, suppress) => { 15 16 if (!(form instanceof HTMLFormElement)) { 17 throw new Error(`Argument 1 of SuggestController.initializeForm has to be an instance of HTMLFormElement, "${typeof form}" given.`); 18 } 19 20 suppress = suppress || false; 21 22 const 23 searchBox = form.querySelector('.tx-solr-suggest') || form, 24 autocomplete = form.querySelector('.tx-solr-autocomplete') || document.body, 25 focusElement = form.querySelector('.tx-solr-suggest-focus') 26 ; 27 28 searchBox.style.position = 'relative'; 29 if (focusElement) focusElement.focus(); 30 31 // prevent submission of empty search form 32 form.addEventListener('submit', event => { 33 if (!searchBox.value) { 34 event.preventDefault(); 35 if (focusElement) { 36 focusElement.focus(); 37 } 38 } 39 }); 40 41 // initialize actual autocomplete 42 const options = { 43 serviceUrl: form.dataset.suggest, 44 dataType: 'json', 45 ajaxSettings: { 46 jsonp: "tx_solr[callback]" 47 }, 48 paramName: form.dataset.suggestParam || 'tx_solr[queryString]', 49 groupBy: 'category', 50 maxHeight: 1000, 51 appendTo: autocomplete, 52 autoSelectFirst: false, 53 triggerSelectOnValidInput: false, 54 width: searchBox.offsetWidth * 0.66, 55 minChars: suppress ? 9999 : 1, 56 transformResult: response => { 57 const result = {suggestions: []}; 58 // ad first object to select at the very top 59 if (response.documents) { 60 response.documents.some(document => { 61 if ('tx_theme_objectdb_object' === document.type) { 62 result.suggestions.push({ 63 value: 'Objekt', 64 data: document 65 }); 66 return true; 67 } 68 }); 69 } 70 // ad regular suggestions 71 if (response.suggestions) { 72 for (let suggestion in response.suggestions) { 73 if (!response.suggestions.hasOwnProperty(suggestion)) { 74 continue; 75 } 76 result.suggestions.push({ 77 value: suggestion, 78 data: {category: 'suggestion', count: response.suggestions[suggestion]} 79 }); 80 } 81 } 82 // treat a response object with exclusive numeric keys as array of suggestions 83 // (for object quick search) 84 if (Object.keys(response).every(_isNumeric)) { 85 Object.values(response).slice(0, 10).forEach(suggestion => { 86 result.suggestions.push({ 87 value: suggestion, 88 data: {category: 'suggestion', count: 1} 89 }); 90 }); 91 } 92 return result; 93 }, 94 beforeRender: container => { 95 // remove first group header 96 container.find('.autocomplete-group:first').remove(); 97 container.addClass('tx-solr-autosuggest'); 98 // add active class to container 99 jQuery(searchBox).parent().addClass('autocomplete-active').fadeIn(); 100 }, 101 formatResult: (suggestion, currentValue) => { 102 if (!currentValue) return suggestion.value; 103 // regular suggestion 104 if ('suggestion' === suggestion.data.category) { 105 return _parseHtml(suggestion.value, currentValue); 106 } 107 // object type suggestion 108 if ('tx_theme_objectdb_object' === suggestion.data.type) { 109 return '<div class="' + suggestion.data.type + '">' + 110 '<a href="' + suggestion.data.link + '" class="internal-link">' + 111 '<span class="badge">Online Sammlung</span><br />' + 112 '<span>' + _parseHtml(suggestion.data.title, currentValue) + '</span>' + 113 '<span class="icon material-symbols-outlined flex-shrink-0 align-bottom notranslate" aria-hidden="true">arrow_outward</span>' + 114 '</a>' + 115 '</div>' 116 ; 117 } 118 // default suggestion 119 return '<div class="' + suggestion.data.type + '">' + 120 (suggestion.data.previewImage ? '<figure' + (suggestion.data.hasVideo ? ' class="hasVideo"' : '') + '>
120<img src="' + suggestion.data.previewImage + '" /></figure>' : '') + 121 '<a href="' + suggestion.data.link + '" class="internal-link">' + _parseHtml(suggestion.data.title, currentValue) + '</a>' + 122 '</div>' 123 ; 124 }, 125 onSelect: suggestion => { 126 if (suggestion.data.link) { 127 if (suggestion.data.link.indexOf('https://www.youtube.com') === 0) { 128 openVideoOverlay(suggestion.data.link); 129 } else { 130 window.location.href = suggestion.data.link; 131 } 132 return true; 133 } 134 _submitForm(form); 135 } 136 }; 137 138 const filters = _extractFilters(form); 139 if (filters.hasOwnProperty('tx_solr')) { 140 options.params = filters; 141 } 142 143 jQuery(searchBox) 144 .devbridgeAutocomplete(options) 145 .on('blur', () => { 146 searchBox.parentNode.classList.remove('autocomplete-active'); 147 const $subject = jQuery(this); 148 setTimeout(() => {$subject.devbridgeAutocomplete('hide');}, 200); 149 }) 150 ; 151 152 if (suppress) { 153 requestAnimationFrame(() => { 154 jQuery(searchBox) 155 .blur() 156 .devbridgeAutocomplete().setOptions({minChars: 1}) 157 ; 158 }); 159 } 160 }; 161 162 function _submitForm(form) { 163 // ugly check to properly submit forms utilizing htmx 164 if (form.hasAttribute('hx-post')) { 165 form.requestSubmit(); 166 } else { 167 jQuery(form).trigger('submit'); 168 } 169 } 170 171 function _extractFilters(form) { 172 if (!form.dataset.suggestFq) { 173 return {}; 174 } 175 176 const filters = {}; 177 178 form.dataset.suggestFq.split(',').forEach(filter => { 179 let value = filter.split(':'); 180 if (value.length < 2) { 181 return; 182 } 183 let name = value.shift(); 184 value = value.join(':'); 185 if (!name || !value) { 186 return; 187 } 188 filters['tx_solr'] = filters.tx_solr || {}; 189 filters.tx_solr['additionalFilters'] = filters.tx_solr.additionalFilters || {}; 190 filters.tx_solr.additionalFilters[name] = value; 191 }); 192 193 return filters; 194 } 195 196 function _initialize() { 197 [...document.querySelectorAll('form[data-suggest]')].forEach(form => { 198 _self.initializeForm(form); 199 }); 200 } 201 202 function _parseHtml(html, currentValue) { 203 return html 204 .replace( 205 new RegExp(`(${jQuery.Autocomplete.utils.escapeRegExChars(currentValue.trim())})`, 'gi'), 206 '<strong>$1<\/strong>' 207 ) 208 .replace(/&/g, '&') 209 .replace(/</g, '<') 210 .replace(/>/g, '>') 211 .replace(/"/g, '"') 212 .replace(/<(\/?strong)>/g, '<$1>') 213 ; 214 } 215 216 function _isNumeric(value) { 217 if ('number' === typeof value) return true; 218 if ('string' !== typeof value) return false; 219 return !isNaN(value) && !isNaN(parseFloat(value)); 220 } 221} 222 223(new SuggestController()).run();
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.