PageSourceSearch

https://www.uandes.cl/wp-content/themes/uandes-main/js/search-ajax.js?ver=1767791955

js uandes.cl collected 2026-10-01 10:40:51 UTC 13,358 bytes, 380 lines download raw bytes

1(function($) {
2    'use strict';
3
4    let currentType = 'todos';
5    let currentSearch = '';
6    let originalSearch = '';
7    let wasAutoCorrected = false;
8    let isLoading = false;
9    let initialCountsLoaded = false; // Los conteos ya se cargaron en el HTML inicial
10
11    $(document).ready(function() {
12        initSearchTabs();
13        initPagination();
14
15        const urlParams = new URLSearchParams(window.location.search);
16        currentType = urlParams.get('type') || 'todos';
17
18        const urlSearch = urlParams.get('s') || '';
19        const dataSearch = $('.search-tab').first().data('search') || '';
20
21        if (urlSearch && dataSearch && urlSearch !== dataSearch) {
22            originalSearch = urlSearch;
23            currentSearch = dataSearch;
24            wasAutoCorrected = true;
25        } else {
26            originalSearch = urlSearch || dataSearch;
27            currentSearch = originalSearch;
28        }
29
30        // Los conteos iniciales ya vienen calculados del servidor (search.php)
31        initialCountsLoaded = true;
32    });
33
34    function initSearchTabs() {
35        $('.search-tab').on('click', function(e) {
36            e.preventDefault();
37
38            if (isLoading) return;
39
40            const type = $(this).data('type');
41            const search = $(this).data('search');
42
43            $('.tabs-cat ul li').removeClass('current');
44            $(this).closest('li').addClass('current');
45
46            $('html, body').animate({
47                scrollTop: $('#search-results-container').offset().top - 100
48            }, 300);
49
50            updateURL(search, type, 1);
51            performSearch(search, type, 1);
52        });
53    }
54
55    function initPagination() {
56        $(document).on('click', '#search-pagination a.page-numbers', function(e) {
57            e.preventDefault();
58
59            if (isLoading || $(this).hasClass('current')) return;
60
61            const href = $(this).attr('href');
62            let page = 1;
63
64            const pageMatch = href.match(/\/page\/(\d+)\//);
65            if (pageMatch) {
66                page = parseInt(pageMatch[1]);
67            } else {
68                const urlParams = new URLSearchParams(href.split('?')[1] || '');
69                if (urlParams.get('paged')) {
70                    page = parseInt(urlParams.get('paged'));
71                }
72            }
73
74            $('html, body').animate({
75                scrollTop: $('#search-results-container').offset().top - 100
76            }, 300);
77
78            updateURL(currentSearch, currentType, page);
79            performSearch(currentSearch, currentType, page);
80        });
81    }
82
83    function performSearch(search, type, page) {
84        if (isLoading) return;
85
86        isLoading = true;
87        currentType = type;
88        currentSearch = search;
89
90        showLoading();
91
92        $.ajax({
93            url: uandesSearch.ajaxUrl,
94            type: 'POST',
95            data: {
96                action: 'uandes_search',
97                nonce: uandesSearch.nonce,
98                search: search,
99                type: type,
100                paged: page,
101                original_search: wasAutoCorrected ? originalSearch : '',
102                was_auto_corrected: wasAutoCorrected ? 1 : 0
103            },
104            success: function(response) {
105                if (response.success) {
106                    if (response.is_auto_corrected && response.effective_query) {
107                        originalSearch = response.original_query;
108                        currentSearch = response.effective_query;
109                        wasAutoCorrected = true;
110                        $('.search-tab').attr('data-search', response.effective_query);
111                    }
112                    updateResults(response);
113                    // NO actualizar conteos - ya vienen del servidor inicial
114                    // Los conteos son consistentes para toda la sesión de búsqueda
115                } else {
116                    showError('Error al realizar la búsqueda.');
117                }
118            },
119            error: function() {
120                showError('Error de conexión.');
121            },
122            complete: function() {
123                hideLoading();
124                isLoading = false;
125            }
126        });
127    }
128
129    function updateResults(response) {
130        const $container = $('#search-results-container');
131
132        $container.find('.auto-correction-notice').remove();
133
134        $('.total-results p').html(`Mostrando ${response.post_count} de ${response.found_posts} resultados`);
135
136        const $existingResults = $container.find('.results-list, .results-not-found');
137        if ($existingResults.length) {
138            $existingResults.first().replaceWith(response.html);
139            $existingResults.slice(1).remove();
140        } else {
141            $container.prepend(response.html);
142        }
143
144        const $pagination = $('#search-pagination');
145        if (response.pagination) {
146            const paginationHtml = `
147                <nav id="search-pagination" class="navigation pagination" aria-label="Posts pagination">
148                    <h2 class="screen-reader-text">Posts pagination</h2>
149                    <div class="nav-links">${response.pagination}</div>
150                </nav>
151            `;
152            if ($pagination.length) {
153                $pagination.replaceWith(paginationHtml);
154            } else {
155                $container.append(paginationHtml);
156            }
157        } else {
158            if ($pagination.length) {
159                $pagination.hide();
160            }
161        }
162    }
163
164    function updateTabCounts(search) {
165        $.ajax({
166            url: uandesSearch.ajaxUrl,
167            type: 'POST',
168            data: {
169                action: 'uandes_search_counts',
170                nonce: uandesSearch.nonce,
171                search: search
172            },
173            success: function(response) {
174                if (response.success && response.data) {
175                    $.each(response.data, function(type, data) {
176                        const $tab = $(`.search-tab[data-type="${type}"]`);
177                        const currentText = $tab.text();
178                        const newText = currentText.replace(/\(\d+\)/, `(${data.count})`);
179                        $tab.text(newText);
180                    });
181                }
182            }
183        });
184    }
185
186    function updateURL(search, type, page) {
187        const params = new URLSearchParams();
188
189        const urlSearch = wasAutoCorrected ? originalSearch : search;
190
191        if (urlSearch) params.set('s', urlSearch);
192        if (type && type !== 'todos') params.set('type', type);
193        if (page && page > 1) params.set('paged', page);
194
195        const newURL = `${window.location.pathname}?${params.toString()}`;
196        window.history.pushState({}, '', newURL);
197    }
198
199    function showLoading() {
200        $('#search-loading').fadeIn(200);
201        $('#search-results-container').css('opacity', '0.5');
202    }
203
204    function hideLoading() {
205        $('#search-loading').fadeOut(200);
206        $('#search-results-container').css('opacity', '1');
207    }
208
209    function showError(message) {
210        alert(message);
211    }
212
213
214    let searchTimeout = null;
215    let currentFocusIndex = -1;
216
217    function initSearchSuggestions() {
218        const $searchInput = $('.desktop-hover-search-form input.search-box');
219        const $searchContainers = $('.desktop-search-hover');
220
221        if (!$searchInput.length) return;
222
223        // Initialize a dropdown for each container (mobile/desktop)
224        $searchContainers.each(function() {
225            createDropdown($(this));
226        });
227
228        $searchInput.on('focus click', function() {
229            const query = $(this).val().trim();
230            fetchSuggestions(query, $(this));
231        });
232        $searchInput.on('input', function() {
233            const $thisInput = $(this);
234            const query = $thisInput.val().trim();
235            clearTimeout(searchTimeout);
236            searchTimeout = setTimeout(function() {
237                fetchSuggestions(query, $thisInput);
238            }, 300);
239        });
240
241        $searchInput.on('keydown', function(e) {
242            const $currentDropdown = $(this).closest('.desktop-search-hover').find('.desktop-search-suggestions-dropdown');
243            if (!$currentDropdown.is(':visible')) return;
244
245            const $items = $currentDropdown.find('.suggestion-item');
246            const itemCount = $items.length;
247
248            switch(e.keyCode) {
249                case 40: // Down
250                    e.preventDefault();
251                    currentFocusIndex = (currentFocusIndex + 1) % itemCount;
252                    updateFocus($items, $currentDropdown);
253                    break;
254                case 38: // Up
255                    e.preventDefault();
256                    currentFocusIndex = currentFocusIndex <= 0 ? itemCount - 1 : currentFocusIndex - 1;
257                    updateFocus($items, $currentDropdown);
258                    break;
259                case 27: // Esc
260                    hideDropdown($currentDropdown);
261                    break;
262                case 13: // Enter
263                    if (currentFocusIndex >= 0) {
264                        e.preventDefault();
265                        const $focused = $items.eq(currentFocusIndex);
266                        if ($focused.length) window.location.href = $focused.data('url');
267                    }
268                    break;
269            }
270        });
271
272        $(document).on('click', function(e) {
273            if (!$(e.target).closest('.desktop-search-hover').length) {
274                hideDropdown();
275            }
276        });
277
278        $(document).on('mouseenter', '.suggestion-item', function() {
279            $('.suggestion-item').removeClass('focused');
280            $(this).addClass('focused');
281            currentFocusIndex = $(this).index();
282        });
283
284        $(document).on('click', '.suggestion-item', function(e) {
285            e.preventDefault();
286            const url = $(this).data('url');
287            if (url) {
288                window.location.href = url;
289            }
290        });
291    }
292
293    function createDropdown($container) {
294        const $dropdown = $('<div>', { // Added 'const'
295            class: 'desktop-search-suggestions-dropdown',
296            css: { display: 'none' }
297        });
298
299        $container.append($dropdown);
300    }
301
302    function fetchSuggestions(query, $input) { // Add $input as parameter
303        if (typeof uandesSearch === 'undefined') return;
304
305        $.ajax({
306            url: uandesSearch.ajaxUrl,
307            type: 'POST',
308            data: {
309                action: 'uandes_search_suggestions',
310                nonce: uandesSearch.nonce,
311                query: query
312            },
313            success: function(response) {
314                // Find the specific dropdown for THIS input
315                const $targetDropdown = $input.closest('.desktop-search-hover').find('.desktop-search-suggestions-dropdown');
316
317                if (response.success && response.suggestions && response.suggestions.length > 0) {
318                    renderSuggestions(response, $targetDropdown); // Pass it along
319                    showDropdown($targetDropdown);
320                } else {
321                    hideDropdown($targetDropdown);
322                }
323            },
324            error: function() {
325                const $targetDropdown = $input.closest('.desktop-search-hover').find('.desktop-search-suggestions-dropdown');
326                hideDropdown($targetDropdown);
327            }
328        });
329    }
330
331    function renderSuggestions(data, $targetDropdown) {
332        let html = '';
333        if (data.title) html += '<h3 class="suggestions-title">' + data.title + '</h3>';
334        html += '<div class="suggestions-grid">';
335        data.suggestions.forEach(function(item) {
336            html += '<a href="' + item.url + '" class="suggestion-item" data-url="' + item.url + '">';
337            html += '<span>' + item.title + '</span>';
338            html += '</a>';
339        });
340        html += '</div>';
341
342        $targetDropdown.html(html); // Use passed dropdown
343        currentFocusIndex = -1;
344    }
345
346    function showDropdown($targetDropdown) {
347        if ($targetDropdown) $targetDropdown.fadeIn(200);
348    }
349
350    function hideDropdown($targetDropdown) {
351        // If no specific dropdown passed, hide ALL (useful for the document click listener)
352        const $target = $targetDropdown || $('.desktop-search-suggestions-dropdown');
353        $target.fadeOut(200);
354        currentFocusIndex = -1;
355    }
356
357    function updateFocus($items) {
358        $items.removeClass('focused');
359        if (currentFocusIndex >= 0 && currentFocusIndex < $items.length) {
360            const $focused = $items.eq(currentFocusIndex);
361            $focused.addClass('focused');
362
363            const dropdown = $dropdown[0];
364            const focusedElement = $focused[0];
365            if (dropdown && focusedElement) {
366                const dropdownRect = dropdown.getBoundingClientRect();
367                const focusedRect = focusedElement.getBoundingClientRect();
368
369                if (focusedRect.bottom > dropdownRect.bottom) {
370                    focusedElement.scrollIntoView(false);
371                } else if (focusedRect.top < dropdownRect.top) {
372                    focusedElement.scrollIntoView(true);
373                }
374            }
375        }
376    }
377
378    initSearchSuggestions();
379
380})(jQuery);

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.