1document.addEventListener('DOMContentLoaded', function() { 2 const searchFields = document.querySelectorAll('.search-form .search-field'); 3 4 const forms = document.querySelectorAll('.search-form'); 5 forms.forEach(form => { 6 if(form.querySelector('.curved-input')) { 7 form.style.setProperty('--curved-input-width', form.querySelector('.curved-input').offsetWidth + 'px'); 8 } 9 }); 10 11 const getLanguage = () => document.documentElement.lang || 'en'; 12 13 const getTypeLabels = (lang) => ({ 14 'post': lang === 'en-US' ? 'News' : 'Actualité', 15 'page': lang === 'en-US' ? 'Page' : 'Page', 16 'event': lang === 'en-US' ? 'Event' : 'Ãvénement', 17 }); 18 19 const getMessages = (lang) => ({ 20 noResults: lang === 'en-US' ? 'No results for this search' : 'Aucun résultat pour cette recherche', 21 viewAll: lang === 'en-US' ? 'View all results' : 'Voir tous les résultats', 22 }); 23 24 const sortResults = (results) => { 25 const order = { 'page': 1, 'event': 2, 'post': 3 }; 26 return results.sort((a, b) => (order[a.type] || 4) - (order[b.type] || 4)); 27 }; 28 29 const createResultImage = (result) => { 30 if (result.type === 'pdf') { 31 return `<img 32 height="56" 33 width="56" 34 src="https://www.univ-larochelle.fr/wp-content/themes/universitelarochelle/img/pdf.png" 35 aria-hidden="true" 36 alt="">`; 37 } 38 39 return `<img 40 height="64" 41 width="64" 42 src="${result.img_url}" 43 aria-hidden="true" 44 alt="">`; 45 }; 46 47 const createResultItem = (result, typeLabels) => { 48 const imageHtml = createResultImage(result); 49 const typeLabel = typeLabels[result.type] || result.type; 50 const targetAttr = result.type === 'pdf' ? 'target="_blank"' : ''; 51 52 return ` 53 <li class="search-result-item"> 54 <div class="search-result-image"> 55 ${imageHtml} 56 </div> 57 <div class="search-result-content"> 58 <span href="${result.link}" class="search-result-link"> 59 ${result.label} 60 </span> 61 <span class="search-result-type">${typeLabel}</span> 62 </div> 63 <a ${targetAttr} href="${result.link}" class="search-absolute-link" aria-label="En savoir plus"></a> 64 </li> 65 `; 66 }; 67 68 const createViewAllLink = (searchTerm, lang) => { 69 const messages = getMessages(lang); 70 const langPath = lang === 'en-US' ? 'en/' : ''; 71 72 return ` 73 <li class="search-result-view-all"> 74 <a href="https://univ-larochelle.fr/${langPath}?s=${encodeURIComponent(searchTerm)}"> 75 ${messages.viewAll} 76 </a> 77 </li> 78 `; 79 }; 80 81 82 83 const renderResults = (data, searchTerm, container, lang) => { 84 const typeLabels = getTypeLabels(lang); 85 const messages = getMessages(lang); 86 87 if (!data || data.length === 0) { 88 container.innerHTML = `<li class="search-no-results">${messages.noResults}</li>`; 89 container.classList.remove('empty'); 90 return; 91 } 92 93 const uniqueResults = data.filter((item, index, self) => 94 index === self.findIndex(t => t.link === item.link) 95 ); 96 97 const nonPdfResults = uniqueResults.filter(item => item.type !== 'pdf'); 98 const pdfResults = uniqueResults.filter(item => item.type === 'pdf'); 99 100 let finalResults = [...nonPdfResults.slice(0, 5)]; 101 102 if (finalResults.length < 5 && pdfResults.length > 0) { 103 const remainingSlots = 5 - finalResults.length; 104 finalResults = [...finalResults, ...pdfResults.slice(0, remainingSlots)]; 105 } 106 107 const sortedResults = sortResults(finalResults); 108 109 const resultsHtml = sortedResults 110 .map(result => createResultItem(result, typeLabels)) 111 .join(''); 112 113 const viewAllHtml = createViewAllLink(searchTerm, lang); 114
115 container.innerHTML = resultsHtml + viewAllHtml; 116 container.classList.remove('empty'); 117 }; 118 119 const performSearch = (searchTerm, filterType, container, lang) => { 120 fetch(AutocompleteSearch.ajax_url, { 121 method: 'POST', 122 headers: { 123 'Content-Type': 'application/x-www-form-urlencoded', 124 }, 125 body: `term=${encodeURIComponent(searchTerm)}&post_type=${encodeURIComponent(filterType)}&action=autocompleteSearch&security=${encodeURIComponent(AutocompleteSearch.ajax_nonce)}`, 126 }) 127 .then(response => { 128 if (!response.ok) { 129 throw new Error('Network response was not ok'); 130 } 131 return response.json(); 132 }) 133 .then(data => { 134 renderResults(data, searchTerm, container, lang); 135 }) 136 .catch(error => { 137 console.error('Search error:', error); 138 container.innerHTML = `<li class="search-error">Error loading results</li>`; 139 container.classList.remove('empty'); 140 }); 141 }; 142 143 searchFields.forEach(searchField => { 144 searchField.addEventListener('input', function(event) { 145 const searchTerm = event.target.value; 146 const filterType = document.querySelector('input[name="post-type"]:checked')?.value || 'all'; 147 const searchResultsContainer = event.target.closest('.search-form').querySelector('.search-results'); 148 const lang = getLanguage(); 149 150 if (searchTerm.trim().length === 0) { 151 searchResultsContainer.innerHTML = ''; 152 searchResultsContainer.classList.add('empty'); 153 return; 154 } 155 156 performSearch(searchTerm, filterType, searchResultsContainer, lang); 157 }); 158 }); 159 160 document.addEventListener('click', function(event) { 161 const searchForms = document.querySelectorAll('.search-form'); 162 163 searchForms.forEach(form => { 164 const searchField = form.querySelector('.search-field'); 165 const searchResults = form.querySelector('.search-results'); 166 167 if (searchField && searchResults) { 168 const clickedInsideInput = searchField.contains(event.target); 169 const clickedInsideResults = searchResults.contains(event.target); 170 171 if (!clickedInsideInput && !clickedInsideResults) { 172 searchResults.innerHTML = ''; 173 searchResults.classList.add('empty'); 174 } 175 } 176 }); 177 }); 178});
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.