PageSourceSearch

https://www.quebec.ca/_assets/f8330c6d2feed73af50f38ae981823a4/JavaScript/Src/main.js?1790171122

js quebec.ca collected 2026-09-24 07:03:39 UTC 12,951 bytes, 315 lines download raw bytes

1$(function(){
2    // Configuration initiale pour les écrans larges (> 991px)
3    if($(window).width() > 991){
4        // Déploie la table des matières par défaut
5        $('.publication_html_table .parent-item').removeClass('collapsed');
6        $('#tableContent').addClass('show');
7    }
8
9    // Configure la hauteur maximale de la navigation
10    $('#tableContent .table-content-navs').css({'max-height': window.innerHeight - 300});
11
12    // Gestion du redimensionnement de la fenêtre
13    $(window).on("resize", function () {
14        if($(window).width() < 768){
15            // Format adaptatif pour mobile
16            $('#tableContent .table-content-navs').css({'max-height': 'fit-content'});
17        } else {
18            // Hauteur calculée pour desktop
19            $('.table-content-navs').css({'max-height': window.innerHeight  - 300});
20        }
21    });
22
23    // Activation automatique du parent si un enfant est actif
24    $('a.active').closest('li.parent').find('a').click();
25
26    // Configuration spécifique pour mobile (< 991px)
27    if($(window).width() < 991){
28        updateTopMobileTableOfContent();
29        // Gestion des états des éléments parents
30        if($(".parent-item").length > 0){
31            // Met à jour le texte d'accessibilité selon l'état
32            if($('.parent-item').hasClass('collapsed')){
33                $('.parent-item').find('.visuallyHidden').text($('.parent-item').data('titleOpen'))
34            }else{
35                $('.parent-item').find('.visuallyHidden').text($('.parent-item').data('titleClose'))
36            }
37        }
38    }
39
40    // Gestion du défilement pour mobile
41    $(window).scroll(function(e) {
42        e.preventDefault();
43        if($(window).width() < 991){
44            updateTopMobileTableOfContent()
45        }
46    });
47
48    // Gestion de la fermeture de la table des matières
49    $(document).on('hidden.bs.collapse', "#tableContent", function () {
50        // Mise à jour du z-index et des textes d'accessibilité
51        if($('#tableContent').length > 0 && !$('#tableContent').hasClass('show')){
52            $('.table-content').removeClass('z-index-99')
53        }
54        $('.parent-item').find('.visuallyHidden').text($('.parent-item').data('titleOpen'))
55    });
56
57    // Gestion de l'ouverture de la table des matières
58    $(document).on('show.bs.collapse', "#tableContent", function () {
59        $(this).closest('.table-of-content-div').find('.table-content').addClass('z-index-99');
60        $('.parent-item').find('.visuallyHidden').text($('.parent-item').data('titleClose'))
61    });
62
63    $(document).on('click', '.print-full-view', function (e){
64        e.preventDefault();
65        $uri = $(this).data('fullview-uri');
66        $.ajax({
67            url: $uri,
68            dataType: "html",
69            data: [],
70            success: function (data) {
71                $(data).printThis();
72            }
73        });
74    });
75
76    var parentClicked = false;
77    $(document).on('click', ".blog-link.nav-link.py-0", function () {
78        $(this).closest('.parent').find('.second-navigation').collapse('show');
79        parentClicked = true;
80    });
81
82    var clickMenu = false;
83    $(document).on('click', ".child-link", function () {
84        clickMenu = true;
85    });
86
87    // Mise à jour du titre caché pour la flèche de l'accordéon à l'ouverture
88    $('.second-navigation').on('show.bs.collapse', function (e){
89        const id = $(this).attr("id");
90        const target = $(`a[data-target="#${id}"]`);
91        $(target).find('span').text($(target).data('titleClose'));
92    })
93
94    // Mise à jour du titre caché pour la flèche de l'accordéon à la fermeture
95    $('.second-navigation').on('hide.bs.collapse', function (e){
96        const id = $(this).attr("id");
97        const target = $(`a[data-target="#${id}"]`);
98        $(target).find('span').text($(target).data('titleOpen'));
99        $('#tableContent .table-content-navs').css({'height': 'fit-content'});
100    })
101
102    // Gestion de l'affichage de la table des matières
103    $('#tableContent').on('show.bs.collapse', function (){
104        updateTableOfContent();
105        if($(window).width() > 991){
106            $('#tableContent .table-content-navs').css({'height': 'fit-content'});
107        }
108    })
109
110    // Gestion du formulaire de vue complète
111  $(document).on('click', '.submit-full-view-form', function (e){
112        e.preventDefault();
113        $(this).closest('form').submit();
114    });
115
116    // Ajoutez un écouteur d'événement qui écoute le défilement.
117    window.addEventListener("load", () => {
118      // Défilement vers la section active en vue complète
119        if($('.full-view-active-section').length > 0 ){
120            const fistFullViewSectionId = $('.full-view-active-section').data('section');
121            if($(fistFullViewSectionId).length){
122                $('html, body').animate({
123                    scrollTop: $(fistFullViewSectionId).offset().top
124                }, 150,'linear', setTimeout(function (){updateTableOfContent()}, 450));
125            }
126        }
127
128      // Récupération de toutes les sections avec ID
129        const sections = Array.from(document.querySelectorAll("section[id]"));
130
131
132      // Dès qu'un événement de défilement est détecté : parcourir tous les éléments
133      // dont la visibilité a changé et mettez en évidence leur point d'entrée de navigation
134
135        if($('.single-page-container').length>0){
136            $('.blog-link').each(function (index,element){
137                $(element).removeClass('active')
138            })
139        }
140
141        let previousY;
142
143      // Gestionnaire d'intersection pour le défilement
144        const scrollHandler = entries =>
145            entries.forEach((entry) => {
146                const currentY = entry.boundingClientRect.y
147                const currentRatio = entry.intersectionRatio
148
149                const section = entry.target;
150                const sectionId = section.id;
151                const sectionLink = document.querySelector(`a[href="#${sectionId}"]`);
152                const activeElement = $('.table-content-navs a.active');
153                const visibleSections = $('section.visible');
154                if(sectionLink != null){
155                  // Gestion des sections visibles
156                  if (entry.intersectionRatio > 0) {
157                        const sectionUri = section.dataset.uri;
158                        // Mettre à jour la variable isScrolling
159                        $("#section-view").find('a').attr('href', sectionUri);
160                        // Gestion des sous-menus
161                        if ($(sectionLink).hasClass('child-link')) {
162                            let submenuArrow = $(sectionLink).closest('.parent').find('.arrow-bottom-menu');
163                            if (!submenuArrow.hasClass('show')) {
164                                $(sectionLink).closest('.parent').find('.second-navigation').collapse('show');
165                            }
166                        }
167
168                         // Mise à jour des classes actives
169                        activeElement.removeClass("active");
170                        visibleSections.removeClass("visible");
171
172                        section.classList.add("visible");
173                        sectionLink.classList.add("active");
174
175                    // Activation du parent si nécessaire
176                        let parent = $(sectionLink).closest('.nav-item.parent').find('.blog-link.nav-link.py-0');
177                        if (parent.length > 0) {
178                            parent.addClass("active");
179                        }
180
181                        // Implémentation de l'accessibilité
182                        if($('.full-view-active-section').length > 0){
183                            $('span.visuallyHiddenCurrent').remove();
184                            var activeChapitreText = $('.static-text-table-of-content').data('chapitre'),
185                                parentItemNode = sectionLink.parentNode,
186                                mySpan = document.createElement("span");
187
188                            mySpan.innerText = activeChapitreText +" ";
189                            mySpan.classList= "visuallyHiddenCurrent";
190
191                            parentItemNode.insertBefore(mySpan, sectionLink);
192                        }
193
194                    // Gestion du debounce pour le défilement
195                        var isScrolling;
196                        window.addEventListener('scroll', function ( event ) {
197                            event.stopPropagation();
198                            // Effacer notre timeout d'attente pendant le défilement timeout
199                            window.clearTimeout( isScrolling );
200
201                            // Définissez un timeout après la fin du défilement.
202                            isScrolling = setTimeout(function() {
203                                // Jouer le callback
204                                setTimeout(updateTableOfContent(), 150);
205                            }, 66);
206                        }, false);
207                    }
208                    else {
209                        // Gestion des éléments qui sortent de la vue
210                        let lastIntersectingElement
211                        if (!clickMenu && !parentClicked && currentY > previousY) {
212                            lastIntersectingElement = entry.target.previousElementSibling;
213
214                            activeElement.removeClass("active");
215                            visibleSections.removeClass("visible");
216
217                            lastIntersectingElement.classList.add("visible");
218                            document.querySelector(`a[href="#${lastIntersectingElement.id}"]`).classList.add("active");
219                        }
220
221                        clickMenu = false;
222                        parentClicked = false;
223                    }
224
225                    previousY = currentY;
226                }
227            });
228
229        //  Création et initialisation de l'observateur de défilement
230        const observer = new IntersectionObserver(scrollHandler);
231
232      // Mise à jour initiale de la table des matières si nécessaire :
233      //noinspection JSCheckFunctionSignatures
234        sections.forEach(section => observer.observe(section));
235    });
236
237    /** Cette condition est utilisé afin de vérifier si nous sommes dans l'item existant et
238     *  que sa fonction principale est de faire défiler jusqu'à la section active dans la table
239     **/
240    if ($('.section-page-container').length) {
241        updateTableOfContent();
242    }
243})
244
245/**
246 * Cette fonction est utilisé pour rendre la table des matières sticky à top 0 en mobile
247 */
248function updateTopMobileTableOfContent(){
249    if($(window).width() < 991){
250        const vv = window.visualViewport;
251        //const currentPositionScrolling =  window.scrollY;
252       // const pivHeight = $('.piv').height();
253        /*if(currentPositionScrolling > 72){
254            $('.table-content').css({ top: '0' })
255        }else{
256            const newTop = pivHeight - currentPositionScrolling;
257            $('.table-content').css({ top: `${newTop}px` });
258        }*/
259
260      if (!vv) return; // autres navigateurs = comportement normal (top:0)
261
262      const setTop = () =>
263        document.documentElement.style.setProperty('--vv-top', vv.offsetTop + 'px');
264
265      setTop();
266      vv.addEventListener('resize', setTop);
267      vv.addEventListener('scroll', setTop);
268    }
269}
270
271/**
272 * Met à jour la position de défilement de la table des matières pour suivre l'élément actif
273 * @returns {boolean} Retourne toujours true
274 */
275function updateTableOfContent(){
276    // Initialisation de la position de décalage
277    var offsetTopItemNav = 0;
278
279    // Récupération des éléments actifs (parent et enfant)
280    let parent = document.querySelector('.blog-link.active');
281    let child = document.querySelector('.child-link.active');
282
283    // Calcul du décalage pour l'élément parent
284    if(parent !== undefined && parent != null) {
285        // Soustrait 30px pour un léger padding visuel
286        offsetTopItemNav = parent.offsetTop - 30;
287    }
288
289    // Ajout du décalage de l'élément enfant si présent
290    if(child !== undefined && child != null) {
291        offsetTopItemNav += child.offsetTop;
292    }
293
294    // Arrête toute animation en cours sur la table des matières
295    $('.table-content-navs').stop();
296
297    // Gestion différente selon le mode d'affichage (vue complète ou normale)
298    if($('.full-view-active-section').length > 0) {
299        // Animation pour la vue complète avec un décalage de 300px
300        $('#tableContent .table-content-navs').animate({
301                scrollTop: offsetTopItemNav - 300},
302            150);
303    }
304    else {
305        // Animation pour la vue normale avec un léger délai
306        setTimeout(() => {
307            $('#tableContent .table-content-navs').animate({
308                    scrollTop: offsetTopItemNav - 30},
309                150);
310        }, 100);
311    }
312
313    return true;
314}
315

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.