PageSourceSearch

https://prometheus.org.ua/wp-content/plugins/courses-catalog/publi…/courses_catalog.js?ver=2.0.63.1779287618

js prometheus.org.ua collected 2026-10-01 10:28:52 UTC 31,674 bytes, 795 lines download raw bytes

1jQuery(document).ready(function($) {           //wrapper
2    var filters = [];
3    var urlPriceFilter = null;
4    var dynamic_filters_initialised = false;
5    var next_page = 2;
6    var total_pages;
7    var page_size = 15;
8    var scroll_lock = true;
9    var refresh = false;
10    var max_price = 30000;
11    var priceSliderSettings = {
12        max: max_price,
13        min: 0,
14        values: [0, max_price]
15    };
16    // var loadMoreButtonAdded = false;
17    var skeletons_html = undefined;
18    var currentPage = 1;
19    var lastRequestId = 0;
20    var selectedFiltersCount = 0;
21
22    // var allowed_popular_now = ['Англійська мова', 'IT', 'Бізнес', 'Військова служба', 'Для освітян', 'Фінанси та інвестиції'];
23    // Bussiness should be 4
24    var allowed_popular_now = ['IT', 'AI та робота з даними', 'Англійська мова', 'Військова служба', 'Для освітян'];
25
26    var helpers = {
27        obj_length: function(obj) { return Object.keys(obj).length;}
28    };
29
30    function ajax_request(request,callback) {
31        $.post(courses_catalog_ajax_obj.ajax_url, {         //POST request
32            _ajax_nonce: courses_catalog_ajax_obj.nonce,     //nonce
33            action: "courses_catalog",            //action
34            data: request                  //data
35        }, function(data) {                    //callback
36            callback(data);
37        });
38    }
39
40    function initAccordions() {
41        var accordionButtons = document.querySelectorAll('.accordion-button');
42
43        accordionButtons.forEach(function(button) {
44            button.addEventListener('click', function() {
45                var contentId = this.getAttribute('data-accordion-target');
46                var content = document.querySelector(contentId);
47
48                var isExpanded = this.getAttribute('aria-expanded') === 'true';
49                this.setAttribute('aria-expanded', !isExpanded);
50
51                if (content.classList.contains('show')) {
52                    content.classList.remove('show');
53                } else {
54                    content.classList.add('show');
55                }
56            });
57        });
58
59        function closeOtherAccordions(currentButton) {
60            accordionButtons.forEach(function(button) {
61                if (button !== currentButton) {
62                    button.setAttribute('aria-expanded', 'false');
63                    var contentId = button.getAttribute('data-accordion-target');
64                    var content = document.querySelector(contentId);
65                    content.classList.remove('show');
66                }
67            });
68        }
69    }
70
71    $.views.tags("startDate", function(val) {
72        var d = new Date(val);
73        return ('0' + d.getDate()).slice(-2) + '.'
74            + ('0' + (d.getMonth()+1)).slice(-2) + '.'
75            + d.getFullYear();
76    });
77
78    function append_results(data) {
79        var course_tmpl = $.templates("#courseTmpl"); // Get compiled template
80        var html = course_tmpl.render(data, helpers);      // Render template using data - as HTML string
81
82        if (data.count <= 0) {
83            $("#courses_catalog_results_field").html("<h1>Немає результатів</h1>")
84        } else {
85            $(html).hide().appendTo("#courses_catalog_results_field").fadeIn(1000);
86        }
87
88        // $("#result_count").html("Результати " + data.results.length);
89
90
91        if (document.getElementById('load_more_button')) {
92            document.getElementById('load_more_button').innerHTML = "<p>Показати ще</p>";
93        }
94
95        if (!document.getElementById('load_more_button')) {
96            // Creating load more button
97            const loadMoreButton = document.createElement("button");
98            loadMoreButton.id = "load_more_button";
99
100            loadMoreButton.classList.add("bg-[#050505]");
101            loadMoreButton.classList.add("text-white");
102            loadMoreButton.classList.add("py-4");
103            loadMoreButton.classList.add("px-9");
104            loadMoreButton.classList.add("rounded-[60px]");
105            loadMoreButton.classList.add("col-start-2");
106            loadMoreButton.classList.add("font-medium");
107            loadMoreButton.classList.add("flex");
108            loadMoreButton.classList.add("items-center");
109            loadMoreButton.classList.add("justify-center");
110            loadMoreButton.classList.add("w-full");
111            loadMoreButton.classList.add("md:w-auto");
112            loadMoreButton.innerHTML = "<p>Показати ще</p>";
113
114            loadMoreButton.addEventListener("click", function() {
115                if (next_page > total_pages || scroll_lock) {
116                    return false;
117                }
118                perform_search($('#catalog_search').val(), next_page, false);
119                next_page++;
120                scroll_lock = true;
121
122                loadMoreButton.innerHTML = `<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
123      <circle class="opacity-25" cx="12" cy="12" r="10" stroke="white" stroke-width="4"></circle>
124      <path class="opacity-75" fill="#f39949" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
125    </svg><p>Завантаження...</p>`;
126            });
127
128            // Creating pagination
129            // console.log("Total pages: ", total_pages);
130
131            var pagination_tmpl = $.templates("#paginationTmpl"); // Get compiled template
132            var pagination_html = pagination_tmpl.render({
133                currentPage: currentPage,
134                totalPages: total_pages,
135                pages: Array.from(Array(total_pages).keys()).map(function(i) { return i + 1; })
136            })
137
138            $("#catalog_pagination").append(loadMoreButton);
139            // $("#catalog_pagination").append(pagination_html);
140            loadMoreButtonAdded = true;
141
142            $('.pagination-page-option').on('click', (e) => {
143                currentPage = e.target.dataset.pagenum;
144                perform_search($('#catalog_search').val(), currentPage);
145            });
146        } else if (total_pages < 1 || currentPage == total_pages) {
147            $("#catalog_pagination").html("");
148        }
149
150
151        if (document.getElementById('load_more_button')) {
152            // console.log('data.results', data.results.length);
153            // console.log('page_size', page_size);
154            // if (data.results.length < page_size) {
155            if (!data.next) {
156                console.log("Hidding more button")
157                console.log("data", data);
158                document.getElementById('load_more_button').style.visibility = 'hidden';
159            } else {
160                document.getElementById('load_more_button').style.visibility = 'unset';
161            }
162        }
163    }
164
165    // Init Swiper
166    const swiper = new Swiper('.popular-now-swiper', {
167        direction: 'horizontal',
168        slidesPerView: 'auto',
169        spaceBetween: 8,
170        loop: false,
171        observer: true,
172        observeParents: true
173    });
174
175    function load_filters(data, callback=undefined) {
176        var html = "";
177        var sidebarFilterTmpl = $.templates("#sidebarFilterTmpl");
178        var mobileFilterTmpl = $.templates("#mobileFilterTmpl");
179
180        // Alphabetical ordering
181        data.dynamic_filters.forEach(item => {
182            if (item.field_name === "topics") {
183                item.filters.sort((a, b) => a.name.localeCompare(b.name));
184            }
185        });
186
187        html = sidebarFilterTmpl.render(data);
188        $(".sidebar .courses_catalog_dynamic_filters").append(html);
189
190        html = mobileFilterTmpl.render(data);
191        $el = $(html);
192        $el.find('.price').replaceWith($('.slider-drop-price'));
193        $el.find('.button').replaceWith($('.slider-drop-button'));
194        $(".filter-bar form.drop-search-form").replaceWith($el);
195
196        $("#pricerange-slider-drop, #pricerange-slider").slider(priceSliderSettings);
197        $(".price-range input.sliderValue-drop.end, .price-range input.sliderValue.end").val(max_price);
198        $(".price-range input.sliderValue-drop.start, .price-range input.sliderValue.start").val(0);
199
200        //HACKY HACK!!!!
201        /*$(".courses_catalog_filters input[type=checkbox]").change(function(e) {
202            //22 stands for "free courses" filter id
203            if($(this).attr('value')==22 && $(this).is(':checked')) {
204                $(".price-range input.sliderValue-drop.start, .price-range input.sliderValue.start").val(0);
205                $("#pricerange-slider-drop, #pricerange-slider").slider( "values", 0, 0 );
206            }
207        });*/
208
209        $("#weeks-slider").slider({
210            min: parseInt($(".weeks-range input.sliderValue.start").val()),
211            max: parseInt($(".weeks-range input.sliderValue.end").val()),
212            step: 1,
213            range: true,
214            values: [parseInt($(".weeks-range input.sliderValue.start").val()), parseInt($(".weeks-range input.sliderValue.end").val())],
215            slide: function(event, ui) {
216                for (var i = 0; i < ui.values.length; ++i) {
217                    $(".weeks-range input.sliderValue[data-index=" + i + "]").val(ui.values[i]);
218                }
219            }
220        });
221        $(".weeks-range input.sliderValue").change(function() {
222            var $this = $(this);
223            $("#weeks-slider").slider("values", $this.data("index"), $this.val());
224        });
225
226        $("#weeks-slider-sidebar").slider({
227            min: parseInt($(".weeks-range input.sliderValue.start").val()),
228            max: parseInt($(".weeks-range input.sliderValue.end").val()),
229            step: 1,
230            range: true,
231            values: [parseInt($(".weeks-range input.sliderValue.start").val()), parseInt($(".weeks-range input.sliderValue.end").val())],
232            slide: function(event, ui) {
233                for (var i = 0; i < ui.values.length; ++i) {
234                    $(".weeks-range input.sliderValue[data-index=" + i + "]").val(ui.values[i]);
235                }
236            }
237        });
238        $(".weeks-range input.sliderValue").change(function() {
239            var $this = $(this);
240            $("#weeks-slider-sidebar").slider("values", $this.data("index"), $this.val());
241        });
242
243        $(".sidebar .courses_catalog_filters input[type=checkbox]").change(function(e) {
244            apply_filters(e);
245            if ($(this).is(":checked")) {
246                selectedFiltersCount++;
247            } else {
248                selectedFiltersCount--;
249            }
250            $('#close-sidebar').html(`Застосувати фільтри (${selectedFiltersCount})`);
251        });
252
253        $(".filter-column input[type=checkbox]").change(function(e) {
254            apply_filters(e);
255        });
256
257        $( ".sidebar #pricerange-slider-drop, #pricerange-slider, #weeks-slider" ).on( "slidestop", function( e, ui ) {
258            apply_filters(e)
259        } );
260
261        if(filters != []) {
262            for (var i = filters.length - 1; i >= 0; i--) {
263                if(filters[i]['name'] == "dynamic_filters") {
264                    $(".courses_catalog_filters input[type=checkbox]#sidebar-"+filters[i]['value'].replace(':','-')).attr("checked",true);
265                    $(".courses_catalog_filters input[type=checkbox]#mobile-"+filters[i]['value'].replace(':','-')).attr("checked",true);
266                }
267            }
268        }
269
270        // Code that expands folded filters
271        // jQuery('.option').on('click', function(e) {
272        //     if ($(this).siblings()[0].style.gridTemplateRows == '1fr') {
273        //         $(this).siblings()[0].style.gridTemplateRows = '0fr'
274        // if (this.querySelector('.more-icon')) {
275        // 	this.querySelector('.more-icon').style.rotate = '0deg'
276        // }
277        //     }
278        //     else {
279        //         $(this).siblings()[0].style.gridTemplateRows = '1fr'
280        // if (this.querySelector('.more-icon')) {
281        // 	this.querySelector('.more-icon').style.rotate = '90deg'
282        // }
283        //     }
284        // });
285
286        // Render popular now filters
287        const popularNowTagsLimit = 10;
288
289        const popularFilterElement = document.createElement("div");
290        popularFilterElement.classList.add("swiper-slide");
291        popularFilterElement.classList.add("transition-colors");
292        popularFilterElement.classList.add("tag-text");
293        popularFilterElement.classList.add("py-3");
294        popularFilterElement.classList.add("px-6");
295        popularFilterElement.classList.add("cursor-pointer");
296        popularFilterElement.style.backgroundColor = "#FAE4D4";
297
298
299        // Remove skeletons when filters are loaded
300        $(".popular_now").html("");
301
302        var popular_now_elements = {};
303
304        for (let i = 0; i < data.dynamic_filters[0].filters.length; i++) {
305            let popularFilter = popularFilterElement.cloneNode(true);
306            // console.log("data", data);
307            let filterName = data.dynamic_filters[0].filters[i].name;
308
309            popularFilter.dataset.filterId = data.dynamic_filters[0].filters[i].value;
310            popularFilter.textContent = filterName;
311
312            if (!allowed_popular_now.includes(filterName)) {
313                continue
314            }
315
316            popularFilter.addEventListener("click", function(e) {
317                let filterId = e.target.dataset.filterId;
318                let filterValue = 'topics:' + filterId;
319
320                let enabled = e.target.classList.toggle("active");
321
322                if (enabled) {
323                    e.target.style.backgroundColor = "#7A00AD";
324                    e.target.classList.remove("text-black");
325                    e.target.classList.add("text-white");
326                } else {
327                    e.target.style.backgroundColor = "#FAE4D4";
328                    e.target.classList.remove("text-white");
329                    e.target.classList.add("text-black");
330                }
331
332                // Sync checkbox state in both forms without firing change events
333                $('.courses_catalog_filters input[type=checkbox][value="' + filterValue + '"]').prop('checked', enabled);
334
335                // Update filters array directly
336                if (enabled) {
337                    filters.push({ name: 'dynamic_filters', value: filterValue });
338                } else {
339                    filters = filters.filter(function(f) {
340                        return !(f.name === 'dynamic_filters' && f.value === filterValue);
341                    });
342                }
343
344                if (filters.length > 2) {
345                    $('.clear_filters').show();
346                } else {
347                    $('.clear_filters').hide();
348                }
349
350                refresh = true;
351                perform_search();
352            });
353            popular_now_elements[filterName] = popularFilter;
354        }
355
356        for (let i = 0; i < allowed_popular_now.length; i++) {
357            $(".popular_now").append(popular_now_elements[allowed_popular_now[i]]);
358        }
359
360        if (callback) {
361            callback();
362        }
363    }
364
365    function perform_search(q, page, showLoading=true) {
366        $('#courses_catalog_spinner').fadeIn();
367        if (refresh === true) {
368            $("#courses_catalog_loading").show();
369            $("#courses_catalog_results_title").hide();
370        }
371        request = {};
372        request['type'] = 'search';
373        request['q'] = (typeof q === 'undefined' ? '' : q);
374        request['page'] = (typeof page === 'undefined' ? 1 : page);
375        request['page_size'] = page_size;
376        request['filters'] = filters;
377        request['sorting'] = $(".sort-area .sortingform select#sorting").val();
378
379        // Setting loading animation in courses section
380        // If skeletons are not rendered - render them
381        if (!skeletons_html) {
382            var skeletons_tmpl = $.templates("#courseSkeletonsTmpl");
383            skeletons_html = skeletons_tmpl.render({}, helpers);
384        }
385        if (showLoading) {
386            var resultsSection = document.querySelector('#courses_catalog_results_field')
387            resultsSection.innerHTML = skeletons_html;
388            if (document.getElementById('load_more_button')) {
389                document.getElementById('load_more_button').style.visibility = 'hidden';
390            }
391        }
392
393        let currentRequestId = lastRequestId + 1;
394        lastRequestId++;
395
396        ajax_request(request, function(data) {
397            // Preventing race condinition
398            if (currentRequestId != lastRequestId) {
399                return;
400            }
401
402            if (typeof page === 'undefined' || page == 1) {
403                $("#courses_catalog_results_field").html("");
404                next_page = 2;
405            }
406            $('#courses_catalog_spinner').fadeOut();
407            if (! dynamic_filters_initialised) {
408                $(".courses_catalog_dynamic_filters").html("");
409                load_filters(data, () => {
410                    initAccordions();
411                });
412                dynamic_filters_initialised = true;
413            }
414            $("#courses_catalog_results_count").text(data["count"]);
415            total_pages = Math.ceil((parseInt(data['count'])/page_size));
416
417            append_results(data);
418
419            if (refresh === true) {
420                $("#courses_catalog_loading").hide();
421                $("#courses_catalog_results_title").show();
422                refresh = false;
423            }
424            scroll_lock = false;
425        });
426
427        let page_category = Cookies.get('a_prev_page_category') || '';
428
429        if (request['q'] != '') {
430            window.dataLayer = window.dataLayer || [];
431            dataLayer.push({
432                'event': 'search_view_result',
433                'keyword': decodeURI(request['q']),
434                'page_category': page_category
435            });
436        }
437    }
438
439    function apply_filters(e) {
440        refresh = true;
441        filters = $(e.target).parents(".filterform").serializeArray();
442
443        if (urlPriceFilter !== null) {
444            filters.push(urlPriceFilter);
445        }
446
447        if (filters.length > 2) {
448            $('.clear_filters').show();
449        } else {
450            $('.clear_filters').hide();
451        }
452
453        perform_search();
454    }
455
456    $("#open_sidebar").on('click', (e) => {
457        $("#sidebar").css('right', '0%');
458    });
459
460    $("#close-sidebar").on('click', (e) => {
461        console.log("Clicked");
462        $("#sidebar").css('right', '100%');
463    });
464
465    $(document).on('click', function(event) {
466        if (!$(event.target).closest('.courses_catalog_search_box, .catalog_search').length) {
467            jQuery(".courses_catalog_search_dropdown_menu").attr('style', 'display: none !important;').addClass("hidden");
468        }
469    });
470
471    $(".sort-area .sortingform select#sorting").on("change", function(event, ui) {
472        refresh = true;
473        perform_search();
474    });
475
476    $("a.perform_search").on('click', function(e) {
477        e.preventDefault();
478
479        apply_filters(e);
480    });
481
482    $("a.clear_filters").on('click', function(e) {
483        e.preventDefault();
484
485        filters = urlPriceFilter !== null ? [urlPriceFilter] : [];
486
487        $(".courses_catalog_filters input[type=checkbox]").prop('checked', false);
488
489        $("#pricerange-slider-drop, #pricerange-slider").slider( "values", [0, max_price] );
490        $(".price-range input.sliderValue-drop.end, .price-range input.sliderValue.end").val(max_price);
491        $(".price-range input.sliderValue-drop.start, .price-range input.sliderValue.start").val(0);
492
493        perform_search();
494    });
495
496    function updateDesktopSearchUI(el) {
497        // 1. Перевірка на видимість інпуту (ігноруємо прихований десктопний інпут на мобільних)
498        if (!el.is(':visible')) return;
499
500        var query = el.val().trim();
501        var isMobile = window.innerWidth < 1024;
502
503        // 2. УНІВЕРСАЛЬНИЙ ПОШУК КОНТЕЙНЕРА
504        // Спочатку шукаємо за атрибутом data-dropdown (як у хедері), 
505        // якщо не знайдено - беремо найближчу форму (як на сторінці)
506        var $container = el.closest("[data-dropdown]");
507        if ($container.length === 0) {
508            $container = el.closest("form");
509        }
510        
511        var $dropdown = $container.find(".courses_catalog_search_dropdown_menu, .search-dropdown__menu");
512        var $resultsContainer = $container.find(".courses_catalog_dataset_course");
513
514        if (query.length === 0) {
515            if (window.DesktopSearchHistory && typeof window.DesktopSearchHistory.renderHistoryInContainer === 'function') {
516                var hasHistory = window.DesktopSearchHistory.renderHistoryInContainer($resultsContainer);
517                if (hasHistory) {
518                    if (!isMobile) {
519                        // Важливо: для хедера ми маємо форсувати показ
520                        $dropdown.attr('style', 'display: flex !important;').removeClass("hidden");
521                    }
522                    $container.addClass("show");
523                } else {
524                    if (!isMobile) {
525                        $dropdown.attr('style', 'display: none !important;').addClass("hidden");
526                    }
527                    $container.removeClass("show");
528                }
529            }
530        } else if (query.length > 2) {
531            var request = {
532                type: 'typeahead',
533                q: query.toLowerCase()
534            };
535
536            ajax_request(request, function(data) {
537                if (el.val().trim().length > 2) {
538                    Object.assign(data, {query: query});
539                    var filterTmpl = $.templates("#searchDropdownTmpl");
540                    var html = filterTmpl.render(data, helpers);
541
542                    $resultsContainer.html(html);
543                    
544                    if (!isMobile) {
545                        $dropdown.attr('style', 'display: flex !important;').removeClass("hidden");
546                    }
547                    $container.addClass("show");
548                    $container.find(".search-history-wrapper").hide();
549                }
550            });
551        } else {
552            if (!isMobile) {
553                $dropdown.attr('style', 'display: none !important;').addClass("hidden");
554                $container.removeClass("show");
555            }
556        }
557    }
558
559    // Обробник кліку
560    $("input.catalog_search").on('click', function (e) {
561        var el = $(this);
562        var $container = el.closest("[data-dropdown]");
563        if ($container.length === 0) {
564            $container = el.closest("form");
565        }
566
567        // Зупиняємо спливання тільки якщо є батьківський data-dropdown
568        if (el.closest("[data-dropdown]").length > 0) {
569            e.stopPropagation();
570        }
571
572        var $dropdown = $container.find(".courses_catalog_search_dropdown_menu, .search-dropdown__menu");
573        var $resultsContainer = $container.find(".courses_catalog_dataset_course");
574
575        $container.addClass("show");
576
577        if (el.val().trim().length === 0) {
578            if (window.DesktopSearchHistory) {
579                window.DesktopSearchHistory.renderHistoryInContainer($resultsContainer);
580                $dropdown.attr('style', 'display: flex !important;').removeClass("hidden");
581            }
582        } else if (el.val().trim().length > 2) {
583            $dropdown.attr('style', 'display: flex !important;').removeClass("hidden");
584        }
585    });
586
587    // Update the click handler to use local context as well
588    $("input.catalog_search").on('click', function (e) {
589        e.stopPropagation();
590
591        var el = $(this);
592        // Find containers relative to this specific clicked input
593        var $container = el.closest("[data-dropdown], form");
594        var $dropdown = $container.find(".courses_catalog_search_dropdown_menu, .search-dropdown__menu");
595        var $resultsContainer = $container.find(".courses_catalog_dataset_course");
596
597        $container.addClass("show");
598
599        if (el.val().trim().length === 0) {
600            if (window.DesktopSearchHistory) {
601                window.DesktopSearchHistory.renderHistoryInContainer($resultsContainer);
602                // Apply style only to the local dropdown
603                $dropdown.attr('style', 'display: flex !important;').removeClass("hidden");
604            }
605        } else if (el.val().trim().length > 2) {
606            $dropdown.attr('style', 'display: flex !important;').removeClass("hidden");
607        }
608    });
609
610    // Обробник фокусу
611    $("input.catalog_search").on('focus', function () {
612        updateDesktopSearchUI($(this));
613    });
614
615    // Обробник натискання клавіш
616    $("input.catalog_search").on('keyup', function (e) {
617        if(e.which !== 13 && e.which !== 27){
618            updateDesktopSearchUI($(this));
619        }
620    });
621
622    // Обробник для Enter та Esc
623    $("input.catalog_search").on('keydown', function (e) {
624        var $dropdown = jQuery(".courses_catalog_search_dropdown_menu");
625        if(e.which === 13){
626            refresh = true;
627            perform_search($(this).val());
628            $dropdown.attr('style', 'display: none !important;').addClass("hidden");
629        } else if (e.which === 27) {
630            $dropdown.attr('style', 'display: none !important;').addClass("hidden");
631        }
632    });
633
634    // Очищення через хрестик в інпуті
635    $("input.catalog_search").on('search', function () {
636        updateDesktopSearchUI($(this));
637    });
638
639    $(".courses_catalog_shortcode_view_all_btn").bind( "click", function() {
640        window.location = "/courses-catalog/?q="+$('input.catalog_search').val()
641    });
642
643
644    $(document).on("click", "a", function(e) {
645        //Doctors' courses chooser
646        if (typeof($(this).attr("href")) === "undefined") return;
647        if ($(this).attr("href").includes("ILDC+DRCV101") && !$(this).hasClass("register")) {
648            e.preventDefault();
649            var modal = `
650<div class='modal fade bd-example-modal-sm' id='choose_course_modal' tabindex='-1' role='dialog' aria-labelledby='mySmallMod
650alLabel' aria-hidden='true'>
651  <div class='modal-dialog modal-sm'>
652    <div class='modal-content'>
653      <div class="modal-header">
654        <h5 class="modal-title">Чи маєте ви диплом лікаря?</h5>
655        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
656          <span aria-hidden="true">&times;</span>
657        </button>
658      </div>
659      <div class="modal-body" style="text-align:center">
660        <button type="button"  class="btn btn-primary" onclick="window.location.href='https://courses.prometheus.org.ua/courses/course-v1:ILDC+DRCV101+2019_T3_ADVANCED/about'">Так</button>
661        <button type="button" class="btn btn-secondary" onclick="window.location.href='https://courses.prometheus.org.ua/courses/course-v1:ILDC+DRCV101+2019_T3/about'">Ні</button>
662      </div>
663    </div>
664  </div>
665</div>
666`;
667            $("html").append(modal);
668            $('#choose_course_modal').modal();
669        }
670    });
671
672    function initialize() {
673        var q_str = window.location.search
674            .replace("?","")
675            .split("&")
676            .map( el => el.split("=") )
677            .reduce( (pre, cur) => {
678                if(cur[0].indexOf('[]') == -1) {
679                    pre[cur[0]] = cur[1];
680                } else {
681                    if(typeof pre[cur[0].replace('[]','')] === 'undefined') {
682                        pre[cur[0].replace('[]','')] = [];
683                    }
684                    pre[cur[0].replace('[]','')].push(cur[1]);
685                }
686                return pre;
687            }, {} );
688
689        refresh = true;
690
691        if(courses_catalog_ajax_obj.filter !== null /*|| typeof q_str['filter'] !== 'undefined'*/) {
692            filters = [{
693                name: "dynamic_filters",
694                //value: parseInt( courses_catalog_ajax_obj.filter !== null ? courses_catalog_ajax_obj.filter : q_str['filter'] )
695                value: courses_catalog_ajax_obj.filter !== null ? courses_catalog_ajax_obj.filter : ''
696            }];
697        }
698
699        let priceFilterObj = undefined;
700        let dynamic_filters = [
701            {
702                "name": "weeks_min",
703                "value": "1"
704            },
705            {
706                "name": "weeks_max",
707                "value": "20"
708            }
709        ];
710
711        if (typeof q_str['q'] !== 'undefined') {
712            perform_search(q_str['q']);
713            return
714        } else if (typeof q_str['price'] !== 'undefined') {
715            if (q_str['price'] == 0) {
716                priceFilterObj = {
717                    "name": "dynamic_filters",
718                    "value": "first_enrollable_paid_seat_price:"
719                };
720            } else if (q_str['price'] == 1) {
721                priceFilterObj = {
722                    "name": "dynamic_filters",
723                    "value": "first_enrollable_paid_seat_price:1"
724                };
725            }
726            urlPriceFilter = priceFilterObj || null;
727
728            if (priceFilterObj != undefined) {
729                dynamic_filters.push(priceFilterObj);
730            }
731            filters = dynamic_filters;
732        } else if (typeof q_str['topics'] !== 'undefined') {
733            let topicId = q_str['topics'];
734
735            dynamic_filters.push({
736                "name": "dynamic_filters",
737                "value": "topics:" + topicId
738            })
739
740            filters = dynamic_filters;
741        }
742        perform_search();
743        // 	else {
744        // 		perform_search();
745        // 	}
746    }
747
748
749    if(window.location.href.indexOf('/courses-catalog') > 0) {
750        // $(window).scroll(function(){
751        //     //if  ($(window).scrollTop() >= ($(document).height() - $(window).height() - $("footer").height() - 200 ) ){
752        //     if  ($(window).scrollTop() >= ($("#courses_catalog_results_field").height() - 200 ) ){
753        //         if (next_page > total_pages || scroll_lock){
754        //             return false;
755        //         } else {
756        //             scroll_lock = true;
757        //             perform_search($('#catalog_search').val(), next_page);
758        //             next_page++;
759        //         }
760        //     }
761        // });
762        initialize();
763    }
764
765    $.views.helpers({
766        formatDate: function(dateString) {
767            var date = new Date(dateString);
768            var day = String(date.getUTCDate()).padStart(2, '0');
769            var month = String(date.getUTCMonth() + 1).padStart(2, '0');
770            return day + '.' + month;
771        },
772        isPastDate: function(dateString) {
773            var date = new Date(dateString);
774            var now = new Date();
775            return date < now;
776        }
777    });
778
779    function highlightQuery(title, query) {
780        if (!query) return title
781        var regex = new RegExp('(' + query + ')', 'gi');
782        return title.replace(regex, '<span class="text-black">$1</span>');
783    }
784
785    $.views.helpers({
786        highlightQuery: highlightQuery,
787        truncateWords: function(text, maxWords) {
788            var wordsArray = text.split(' ');
789            if (wordsArray.length > maxWords) {
790                return wordsArray.slice(0, maxWords).join(' ') + '...';
791            }
792            return text;
793        }
794    });
795});

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.