PageSourceSearch

https://www.podjetniskisklad.si/razpisi-live-search.js

js podjetniskisklad.si collected 2026-10-02 03:42:06 UTC 10,055 bytes, 352 lines download raw bytes

1jQuery(function ($) {
2
3  if (window.__SPS_RAZPISI_MODAL_INIT__) return;
4  window.__SPS_RAZPISI_MODAL_INIT__ = true;
5
6  var $results = $('#razpisi-results');
7  var $loader  = $('#razpisi-loader');
8
9  const results = document.querySelector('#razpisi-results');
10  if (!results) return;
11
12  var $bottomLoader = $('#razpisi-bottom-loader');
13
14  if (!$results.length) {
15    console.warn('SPS razpisi: #razpisi-results ne obstaja');
16    return;
17  }
18
19  var $target = $results.children('.fusion-column-wrapper');
20  if (!$target.length) $target = $results;
21
22  var activeXhr = null;
23  var timer = null;
24
25  var page = 1;
26  var hasMore = true;
27  var isLoading = false;
28  var lastKey = '';
29
30  // ali naj trenutna serija requestov ignorira filtre (tipkanje)
31  var ignoreFiltersMode = false;
32
33  function portalToBody(){
34    var $backdrop = $('#spsBackdrop');
35    var $modal = $('#spsFilterModal');
36    if ($backdrop.length) $backdrop.appendTo('body');
37    if ($modal.length) $modal.appendTo('body');
38  }
39
40  function openFilters(){
41    portalToBody();
42    $('#spsBackdrop').prop('hidden', false);
43    $('#spsFilterModal').prop('hidden', false);
44    $('body').addClass('sps-modal-open');
45    updateCounter();
46  }
47
48  function closeFilters(){
49    $('#spsBackdrop').prop('hidden', true);
50    $('#spsFilterModal').prop('hidden', true);
51    $('body').removeClass('sps-modal-open');
52  }
53
54  function getCheckedVals(nameWithBrackets) {
55    var vals = [];
56    $('input[name="' + nameWithBrackets + '"]:checked').each(function(){
57      var v = ($(this).val() || '').trim();
58      if (v) vals.push(v);
59    });
60    vals.sort();
61    return vals;
62  }
63
64  function groupHasOnlyAll(vals){
65    return vals.length === 1 && vals[0] === '__all__';
66  }
67
68  function groupIsFiltered(vals){
69    if (!vals.length) return false;
70    if (groupHasOnlyAll(vals)) return false;
71    return vals.some(v => v !== '__all__');
72  }
73
74  // pravila za __all__ (vsi)
75  function handleAllCheckbox(groupNameWithBrackets){
76    var $all = $('input[name="' + groupNameWithBrackets + '"][value="__all__"]');
77    if (!$all.length) return;
78
79    // ko klikneš __all__ -> odkljukaj vse ostale
80    $all.on('change', function(){
81      if ($(this).is(':checked')) {
82        $('input[name="' + groupNameWithBrackets + '"]').not($all).prop('checked', false);
83      }
84    });
85
86    // ko klikneš katerikoli drug -> odkljukaj __all__
87    $(document).on('change', 'input[name="' + groupNameWithBrackets + '"]', function(){
88      var v = ($(this).val() || '').trim();
89      if (v && v !== '__all__' && $(this).is(':checked')) {
90        $all.prop('checked', false);
91      }
92    });
93  }
94
95  function updateCounter(){
96    var c = 0;
97
98    var financiranje = getCheckedVals('financiranje[]');
99    var leta = getCheckedVals('leto[]');
100    var status = getCheckedVals('status[]');
101    var kategorija = getCheckedVals('razpis__poziv[]');
102
103    if (financiranje.length) c++;
104    if (leta.length) c++;
105    if (groupIsFiltered(status)) c++;
106    if (groupIsFiltered(kategorija)) c++;
107
108    $('#spsFiltersCount').text(c);
109  }
110
111  // ključ, ki vključuje tudi "mode", da infinite scroll ne meša režimov
112  function currentKey(){
113    var term = ($('#razpisi-search').length ? ($('#razpisi-search').val() || '').trim() : '');
114
115    var financiranje = getCheckedVals('financiranje[]').join(',');
116    var leta = getCheckedVals('leto[]').join(',');
117    var status = getCheckedVals('status[]').join(',');
118    var kategorija = getCheckedVals('razpis__poziv[]').join(',');
119
120    return [
121      term,
122      financiranje,
123      leta,
124      status,
125      kategorija,
126      (ignoreFiltersMode ? 'nofilters' : 'filters')
127    ].join('|');
128  }
129
130  /**
131   * payload:
132   * - če ignoreFilters = true -> ignoriraj filtre, pošlji "vse"
133   * - če ignoreFilters = false -> pošlji filtre + vedno pošlji tudi term (če obstaja)
134   */
135  function payload(p, ignoreFilters) {
136    var term = ($('#razpisi-search').length ? ($('#razpisi-search').val() || '').trim() : '');
137
138    if (ignoreFilters) {
139      return {
140        action: 'sps_razpisi_live_search',
141        term: term,
142        financiranje: [],
143        leto: [],
144        status: ['__all__'],
145        razpis__poziv: ['__all__'],
146        page: p || 1
147      };
148    }
149
150    return {
151      action: 'sps_razpisi_live_search',
152      term: term,
153      financiranje: getCheckedVals('financiranje[]'),
154      leto:         getCheckedVals('leto[]'),
155      status:       getCheckedVals('status[]'),
156      razpis__poziv:getCheckedVals('razpis__poziv[]'),
157      page: p || 1
158    };
159  }
160
161  function setLoading(on, mode) {
162    if ($loader.length) {
163      if (on && mode === 'replace') $loader.show();
164      if (!on) $loader.hide();
165    }
166
167    if ($bottomLoader.length) {
168      if (on && mode === 'append') {
169        $bottomLoader.prop('hidden', false).attr('aria-hidden', 'false');
170      } else {
171        $bottomLoader.prop('hidden', true).attr('aria-hidden', 'true');
172      }
173    }
174  }
175
176  function request(mode, ignoreFilters) {
177    mode = mode || 'replace';
178
179    if (!window.spsRazpisi || !spsRazpisi.ajaxurl) {
180      console.error('spsRazpisi.ajaxurl manjka (wp_localize_script ni naložen ali je povozljen)');
181      return;
182    }
183
184    if (isLoading) return;
185    if (mode === 'append' && !hasMore) return;
186
187    if (activeXhr && activeXhr.readyState !== 4) {
188      activeXhr.abort();
189    }
190
191    updateCounter();
192    isLoading = true;
193    setLoading(true, mode);
194
195    activeXhr = $.post(spsRazpisi.ajaxurl, payload(page, ignoreFilters))
196      .done(function (response) {
197
198        if (!response || !response.success || !response.data || typeof response.data.html === 'undefined') {
199          console.error('Nepričakovan AJAX response', response);
200          return;
201        }
202
203        hasMore = !!response.data.has_more;
204
205        if (!hasMore && $bottomLoader.length) {
206          $bottomLoader.find('span:last').text('To je vse.');
207          $bottomLoader.prop('hidden', false).attr('aria-hidden', 'false');
208
209          setTimeout(function(){
210            $bottomLoader.prop('hidden', true).attr('aria-hidden', 'true');
211            $bottomLoader.find('span:last').text('Nalagam več…');
212          }, 1200);
213        }
214
215        if (mode === 'append') {
216          $target.append(response.data.html);
217        } else {
218          $target.html(response.data.html);
219        }
220
221        $results.find('.fusion-pagination, nav.pagination, .pagination').remove();
222
223        $(window).trigger('resize');
224        portalToBody();
225      })
226      .fail(function (xhr, status) {
227        if (status === 'abort') return;
228        console.error('AJAX fail', xhr && xhr.status, xhr && xhr.responseText);
229      })
230      .always(function(){
231        isLoading = false;
232        setLoading(false, mode);
233      });
234  }
235
236  function resetAndLoad(ignoreFilters){
237    page = 1;
238    hasMore = true;
239    ignoreFiltersMode = !!ignoreFilters;
240    lastKey = currentKey();
241    request('replace', ignoreFiltersMode);
242  }
243
244  function loadMore(){
245    if (!hasMore || isLoading) return;
246    if (currentKey() !== lastKey) return;
247
248    page++;
249    request('append', ignoreFiltersMode);
250  }
251
252  function debouncedReset(ms, ignoreFilters){
253    clearTimeout(timer);
254    timer = setTimeout(function(){ resetAndLoad(ignoreFilters); }, ms);
255  }
256
257  /* ===========================
258     HANDLERJI
259     =========================== */
260
261  // LIVE SEARCH: tipkanje ignorira filtre
262  $(document).on('input', '#razpisi-search', function(){
263    debouncedReset(250, true);
264  });
265
266  $(document).on('keydown', '#razpisi-search', function(e){
267    if (e.key === 'Enter') e.preventDefault();
268  });
269
270  // OPEN MODAL (samo click, brez pointerup)
271  $(document).on('click', '#spsFiltersBtn', function(e){
272    e.preventDefault();
273    openFilters();
274  });
275
276  // CLOSE MODAL
277  $(document).on('click', '#spsFilterClose, #spsBackdrop', function(e){
278    e.preventDefault();
279    closeFilters();
280  });
281
282  $(document).on('keydown', function(e){
283    if (e.key === 'Escape') closeFilters();
284  });
285
286  // __all__ pravila
287  handleAllCheckbox('status[]');
288  handleAllCheckbox('razpis__poziv[]');
289
290  // Counter sproti
291  $(document).on(
292    'change',
293    'input[name="leto[]"], input[name="financiranje[]"], input[name="status[]"], input[name="razpis__poziv[]"]',
294    function(){
295      updateCounter();
296    }
297  );
298
299  // APPLY: filtri + (če obstaja) search term skupaj
300  $(document).on('click', '#spsApplyFilters', function(e){
301    e.preventDefault();
302    closeFilters();
303    resetAndLoad(false);
304  });
305
306  // RESET: resetira filtre, search ostane (če je vpisan, bo potem iskal globalno)
307  $(document).on('click', '#spsResetFilters', function(e){
308    e.preventDefault();
309
310    $('input[name="leto[]"]').prop('checked', false);
311    $('input[name="financiranje[]"]').prop('checked', false);
312
313    $('input[name="status[]"]').prop('checked', false);
314    $('input[name="status[]"][value="__all__"]').prop('checked', true);
315
316    $('input[name="razpis__poziv[]"]').prop('checked', false);
317    $('input[name="razpis__poziv[]"][value="__all__"]').prop('checked', true);
318
319    updateCounter();
320
321    // če je term vpisan -> po logiki naj ignorira filtre (ki so zdaj itak resetirani)
322    var term = ($('#razpisi-search').length ? ($('#razpisi-search').val() || '').trim() : '');
323    resetAndLoad(term.length > 0);
324  });
325
326  // INFINITE SCROLL
327  $(window).on('scroll', function(){
328    if (!hasMore || isLoading) return;
329
330    var nearBottom = (window.innerHeight + window.scrollY) >= (document.body.offsetHeight - 450);
331    if (nearBottom) loadMore();
332  });
333
334  // INIT
335  portalToBody();
336  setTimeout(portalToBody, 200);
337
338  if (!$('input[name="razpis__poziv[]"]:checked').length) {
339    $('input[name="razpis__poziv[]"][value="__all__"]').prop('checked', true);
340  }
341
342  if (!$('input[name="status[]"]:checked').length) {
343    $('input[name="status[]"][value="__all__"]').prop('checked', true);
344  }
345
346  updateCounter();
347
348  // init: če je že vpisan term (npr. browser autofill) -> global search, sicer filtri
349  var initTerm = ($('#razpisi-search').length ? ($('#razpisi-search').val() || '').trim() : '');
350  resetAndLoad(initTerm.length > 0);
351
352});

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.