PageSourceSearch

https://www.quebec.ca/_assets/8b5470729627060287ec80151aeaf598/JavaScript/Solr/facets.js?1790171116

js quebec.ca collected 2026-09-24 07:03:55 UTC 13,450 bytes, 339 lines download raw bytes

1$(function () {
2    //Show Filter for small screen option
3    let showFilterForSmallScreen = $("#showFilterForSmallScreen").attr('data-tr-label')
4    if(showFilterForSmallScreen === '1'){
5        $('#sm-toggable-facets-div, #reset-filters, #empty-space').collapse("show")
6    }
7
8    // Si un loading existe, on injecte le texte pour le lecteur d'écran
9    let loadingInfo = $('.tx_solr .loadingInfo');
10    if(loadingInfo.length){
11        const divLoading = loadingInfo[0];
12        const configSolr = { attributes: true, childList: true, subtree: true, characterData: true };
13        const callbackSolr = function(mutationsList, observerSolr) {
14            mutationsList.forEach(function(mutation) {
15                observerSolr.disconnect(divLoading, configSolr);
16                if(loadingInfo.hasClass("inactive")){
17                    loadingInfo.find('span').remove();
18                } else {
19                    loadingInfo.append("<span>"+$("#textLoadingMessage").text()+"</span>");
20                }
21                observerSolr.observe(divLoading, configSolr);
22            });
23        };
24
25        // Créer l'objet MutationObserver pour écouter les changements (ajouts/suppressions) dans le DOM.
26        const observerSolr = new MutationObserver(callbackSolr);
27        observerSolr.observe(divLoading, configSolr);
28    }
29
30    let facets = $('.facets-list');
31    facets.each(function(){
32        let facetName = $(this).attr('data-facet-name')
33        let hideEmptyOptions = $("#"+facetName+"-hideEmptyOptions").attr('data-hide-empty-options');
34        if(hideEmptyOptions === '1'){
35            let checkboxes = $('.'+facetName+' input');
36            checkboxes.each(function(){
37                let checkBoxId = $(this).attr('id')+'-result-count';
38                let checkBoxResultCount = $('#'+checkBoxId).text();
39                $(this)
40                    .parent()
41                    .toggleClass('d-none',checkBoxResultCount < 1 );
42            })
43        }
44    })
45
46    let parentIds = {};
47    let parentsElements = $('[data-facet-bound-to-parent] input')
48    parentsElements.each(function (item) {
49        // On récupère l'id des options de la facette parente
50        let parentInputId = $(this).attr('id')
51        let parentName = $(this).closest('fieldset').attr('id')
52        if(parentName in parentIds){
53            if(!Array.isArray(parentIds[parentName])){
54                parentIds[parentName] = [parentIds[parentName]]
55            }
56            parentIds[parentName].push(parentInputId);
57        }
58        else{
59            parentIds[parentName] = parentInputId;
60        }
61        // Ajouter l'événement quand on sélectionne une option parente
62        $(this).change(function (){
63          showAssociatedFacets(parentName)
64        })
65    })
66    let parentsName = Object.keys(parentIds);
67
68  /**
69   * Cette fonction sert à afficher les options de la facette fille
70   * @param parentName
71   */
72  function showAssociatedFacets(parentName) {
73        let checked = false;
74        // Une option parente est sélectionnée
75        // On affiche les options filles associées
76        if(parentName !== undefined && Array.isArray(parentIds[parentName])){
77          let childFacetBoundToId = [];
78           $('[parent-name='+parentName+'] .form-check').each(function(id,item ){
79             childFacetBoundToId.push($(item).attr("data-facet-bound-to"))
80           })
81          let facetsWithoutPatentId =  childFacetBoundToId.filter(item => !parentIds[parentName].includes(item));
82          parentIds[parentName].forEach((id) => {
83            let isChildChecked = $('#' + id ).is(':checked')
84            $("[data-facet-bound-to="+id+"]").toggleClass('d-none', !isChildChecked);
85              // la variable 'checked' est utilisée pour détecter s'il n'existe aucune une option parente sélectionnée.
86              if(isChildChecked){
87                  checked = true;
88              }
89            facetsWithoutPatentId.forEach(idFacet => {
90              // Ne pas afficher les options sans parente, quand on sélectionne une option de facette parente
91              let childFacetChecked = $("[data-facet-bound-to="+idFacet+"] input:checked").length > 0;
92              $("[data-facet-bound-to="+idFacet+"]").toggleClass('d-none', !childFacetChecked && checked);
93            })
94          })
95        }
96        // Gérer le cas ou l'utilisateur a décoché toutes les options de la facette parente
97        controlFacetOptionsDisplay(parentName,checked)
98    }
99
100  /**
101   * Cette fonction permet de contrôler l'affichage de toute la facette fille en fonction de la facette parente
102   * @param parentName
103   * @param isOptionParentChecked
104   */
105    function controlFacetOptionsDisplay(parentName, isOptionParentChecked){
106        let isAnyParentOptionChecked =  $("[data-facet-bound-to-parent="+parentName+"] input:checked").length === 0
107        let facet = $("[parent-name="+parentName+"]").closest('.facet')
108        let hideFacet = $(facet).find('.dropdown').attr('disableFacetByDefault')
109        // Si l'option TS 'disableFacetByDefault' est activée, on désactive toute la facette fille
110        if(hideFacet === 'true'){
111            let checked = !isOptionParentChecked && isAnyParentOptionChecked
112            $(facet).toggleClass('disabled', checked)
113                    .find('legend') .toggleClass('text-muted', checked)
114                    .find('.dropdown-toggle').toggleClass('text-muted', checked)
115        }
116        // Sinon, on affiche tous les options de la facette fille
117        else if(parentName !== undefined && isOptionParentChecked === false){
118          if(Array.isArray(parentIds[parentName])){
119            (parentIds[parentName]).forEach( (id) => {
120              $("[data-facet-bound-to="+id+"]").toggleClass('d-none', isOptionParentChecked);
121            })
122          }
123          else {
124            $("[data-facet-bound-to="+parentIds[parentName]+"]").toggleClass('d-none', isOptionParentChecked);
125          }
126        }
127    }
128
129    // Au moment de chargement de la page
130    if(Array.isArray(parentsName)){
131        parentsName.forEach(parent => {
132          showAssociatedFacets(parent)
133        })
134    }
135
136
137    $(document).on("keyup", ".search-filter", function () {
138        var value = $(this).val().toLowerCase()
139        var pattern = value
140                        .replaceAll(/e/g,'[eéèëê]')
141                        .replaceAll(/i/g,'[iíìïî]')
142                        .replaceAll(/u/g,'[uùüû]')
143                        .replaceAll(/o/g,'[oöô]')
144                        .replaceAll(/a/g,'[aäàaâ]')
145        var regExp = new RegExp(pattern, 'i');
146        var noResult = false
147        var list = $(this)
148            .closest('.facet')
149            .find('.form-check label')
150            .filter(function () {
151                var show = regExp.test($(this).text())
152                $(this)
153                    .parent('.form-check')
154                    .toggle(show)
155                noResult |= show
156            })
157        $(this)
158            .siblings('.no-result')
159            .toggle(!noResult && value != '')
160
161      // Accessibilité : informer le lecteur d'écran lorsqu'il n'y a pas de résultat.
162      if(!noResult && value !== ''){
163        var $noResult = $(this).siblings('.no-result').first();
164        var textToKeep = $noResult.text();
165        $noResult.text('').text(textToKeep);
166      }
167
168    })
169    $(document).on('submit', '#main .tx_solr form', function (e) {
170        e.preventDefault()
171        var url = '?' + $(this).serialize()
172       // console.log('Submiting search form')
173        refresh(url)
174    });
175    $('.tx_solr').on('click', '.facet-in-use', function(e) {
176        console.log("FIRED EVENT FACET IN USE")
177        e.preventDefault()
178
179        var inputId = $(e.target).closest('[data-bindto]').data('bindto')
180        var el = $(inputId);
181
182        if (el.is(':checkbox')) {
183            el.click()
184        }
185        else if (el.is('option')) {
186          // nécessaire pour détection via mutation observer dans le composant qc-select
187          el.removeAttr("selected");
188        }
189        else if (el.is(':radio')) {
190            // console.log(el)
191            // el.attr('checked', false)
192            el[0].checked = false;
193            el.change();
194        }
195        else if (el.is(':hidden')) {
196            let facet = el.parents('.facet')
197
198            if (facet.is('.facet-daterange')) {
199                facet.find(':input').val('')
200            }
201
202            if (facet.is('.facet-type-numericRange')) {
203                let slider = facet.find('.slider')
204                slider.slider('values', [slider.data("range-min"),slider.data("range-max")])
205                facet.find('.min').val(slider.data("range-min"))
206                facet.find('.max').val(slider.data("range-max"))
207                el.val('')
208            }
209
210            if(el.is('.muni-express-input')){
211                el.val('')
212                if(el.length > 0){
213                    const changeEvent = new CustomEvent('resetFilter', {
214                        detail: {
215                            reset: true
216                        },
217                        bubbles: true,
218                        cancelable: true
219                    });
220
221                    el[0].dispatchEvent(changeEvent);
222                }
223            }
224            el.change();
225        }
226
227    })
228        .on('click', '.pagination a', function(e) {
229            e.preventDefault()
230            var page = $(this).data(page).page,
231                $formSolrNews = $('.solr-custom-form');
232            if($formSolrNews.length > 0){
233                //Change value of the number of page
234                $formSolrNews.find('input[name="tx_solr[page]"]').val(page)
235                //In case of we send the resultPerPage in the form the pagination will reset to page 1
236                //In this case we decide to remove this attribute from the form request and will add again by ajax response
237                $formSolrNews.find('select[name="tx_solr[resultsPerPage]"]').removeAttr('name');
238                $formSolrNews.submit()
239            }else{
240                refresh(this.href)
241            }
242            let goToElement = document.getElementById('top-right') || document.getElementById('top-right-panel')
243            goToElement.scrollIntoView();
244        })
245    .on('click', '.suggestion', function(e) {
246        e.preventDefault()
247        var suggestion = $(e.target).text().trim(),
248            $formSolrNews = $('.solr-custom-form');
249
250        if($formSolrNews.length > 0){
251            $formSolrNews.find('input[name="tx_solr[page]"]').val(1)
252        }
253        $('#keyword-search').val(suggestion).closest('form').submit()
254    })
255
256    function refresh(url) {
257        history.pushState({},'', url)
258        $('.tx_solr .loadingInfo').removeClass('inactive')
259        $('#tx-solr-search').load( url + '&type=7382', function () {
260            $('.tx_solr .loadingInfo').addClass('inactive')
261        });
262    }
263
264    function logEvent(e) {
265        console.log('facets.js change detected', e)
266    }
267
268
269  $(document)
270        .on('change', '.tx_solr form :input[name]:not(.daterange .selector)',
271            function (e) {
272            logEvent(e)
273        var facet = $(this).closest('.facet')
274        var linkFieldset = facet.find("div.dropdownWrap div a");
275        linkFieldset.attr("aria-describedby","");
276        if (facet.length) {
277            var nb = facet.find(':checked').length;
278            if (nb) {
279                facet
280                    .find('.nb')
281                    .text(nb)
282                    .siblings('.pluriel')
283                    .toggleClass('d-none',nb < 2);
284                linkFieldset
285                    .attr("aria-describedby",facet.find("div.nb-selected").attr("id"));
286            }
287            facet.toggleClass('is-used', nb > 0)
288                .find('.nb-selected')
289                .toggleClass('d-none', nb == 0)
290        }
291        //Initialize to page 1 after each change
292        var $formSolrNews = $('.solr-custom-form');
293        if($formSolrNews.length > 0){
294            $formSolrNews.find('input[name="tx_solr[page]"]').val(1)
295        }
296        $(this).closest('form').submit()
297    })
298
299    // prevent dropdown to close when clicked inside
300    $('.facets .dropdown').on('hide.bs.dropdown', function (e) {
301        if (typeof e.clickEvent == 'undefined') {
302            // direct click on the dropdown anchor trigger
303            return;
304        }
305        var clickedElement = e.clickEvent.target,
306            dropdown = e.target;
307        // check if clicked element is inside the dropdown menu
308        if ($(dropdown)
309            .find('.dropdown-menu')
310            .find(clickedElement).length > 0) {
311            e.preventDefault()
312        }
313    })
314    $('a.sr-version-link').click(function () {
315        var searchPart = $(':input#sr').val(1).closest('form').serialize()
316        location.assign(location.pathname + '?' + searchPart)
317    }).attr('href', "#")
318
319  document.querySelectorAll("qc-select select")
320    .forEach(selectElement => {
321      let callback = () => {
322        $(selectElement).change()
323      }
324      let observerConfig = {
325        subtree: true,
326        attributes: true,
327        attributeFilter: ["selected"]
328      }
329      observer = new MutationObserver(callback);
330      observer.observe(selectElement, observerConfig);
331
332    })
333
334  $("qc-search-bar").on("click", function (e) {
335    let el = $(this).closest("qc-search-bar").find("input[type=search]")[0]
336    setTimeout(() => $(el).change(), 1)
337  })
338
339});

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.