PageSourceSearch

https://www.univ-larochelle.fr/wp-content/themes/univ-2026/assets/js/autocomplete.js?ver=6.7.9

js univ-larochelle.fr collected 2026-09-24 08:46:18 UTC 7,092 bytes, 178 lines download raw bytes

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.