PageSourceSearch

https://www.crous-orleans-tours.fr/wp-content/themes/crous/js/script.js?ver=1.7.2

js crous-orleans-tours.fr collected 2026-10-02 12:09:28 UTC 20,011 bytes, 462 lines download raw bytes

1jQuery(function($){
2    const slickPrevArrow = '<button class="slick-prev slick-arrow" aria-label="Précédent" type="button" style="">Précédent</button>';
3    const slickNextArrow = '<button class="slick-next slick-arrow" aria-label="Suivant" type="button" style="">Suivant</button>';
4    const slickResetDotTabindexActions = "init afterChange setPosition";
5    function slickResetDotTabIndex(e, slick) {
6        var $slider = $(this);
7        setTimeout(function () {
8            $slider.find('.slick-dots button').attr('tabindex', 0);
9        }, 0);
10    }
11    
12    function isMobile(){
13        return $(window).width() < 960;
14    };
15
16    $('.backtotop').click(function(){
17        $('.main-logo').get(0).focus({ focusVisible: true, preventScroll: true }); 
18        $("html, body").stop().animate({
19            'scrollTop':0
20        },300);
21        return false;
22    });
23
24    $('a:not([href*="'+document.location.host+'"])')
25        .filter(':not([href^="/"])')
26        .filter(':not([href^="#"])')
27        .filter(':not([href^="javascript"])')
28        .attr("target","_blank");
29    
30    $('a[href$=".pdf"],a[href$=".doc"],a[href$=".docx"],a[href$=".xls"],a[href$=".xlsx"],a[href$=".ppt"],a[href$=".pptx"]').attr("target","_blank");
31
32    $content_links = $('.wpb_text_column a,.a');
33    $content_links.filter('[target="_blank"]').append('<span class="screen-reader-text"> (S\'ouvre dans un nouvel onglet)</span>');
34    $content_links.filter('[href$=".pdf"],[href$=".doc"],[href$=".docx"],[href$=".xls"],[href$=".xlsx"],[href$=".ppt"],[href$=".pptx"]').prepend('<span class="screen-reader-text">Téléchager : </span>');
35    $content_links.filter('[href^="mailto"]').prepend('<span class="screen-reader-text">Envoyer un courriel à : </span>');
36
37    $(window).on('click', function(){
38        $('.crous_selector').removeClass('active');
39        $('.vc_crous_map .active').removeClass("active");
40    });
41    
42    /* Selecteur Crous */
43    $('a[href="#crous_selector"]').click( function(){
44        let element = $('.crous_selector').first().addClass('active');
45        $('.crous_list li:first-child a', element).get(0).focus({ focusVisible: true, preventScroll: true });
46        $("html, body").stop().animate({
47            'scrollTop':(element.offset().top - 28)
48        },300);
49        return false;
50    });
51    $('.crous_selector .selected').click( function(e){
52        let parent = $(this).closest('.crous_selector');
53        if( !parent.hasClass('active') && $('.crous_selector.active').length > 0 ) $('.crous_selector.active').removeClass('active');
54        parent.toggleClass('active');
55        e.stopPropagation();
56    });
57    $('.crous_selector .crous_list a').click( function(e){
58        let parent = $(this).closest('.crous_selector');
59        parent.toggleClass('active');
60        $('.crous_selector .selected').text( $(this).text() );
61        // return false;
62    });
63
64    
65    /* Ajoute un <span/> "Retour" pour le mobile (caché en desktop) */
66    let lis = $('.header_nav li.menu-item-has-children > .sub-menu > li:first-child');
67    lis.prepend( $('<span>' + (crous_translate.retour?crous_translate.retour:"Retour") + '</span>') );
68    function center_submenu() {
69        if (!isMobile()) {
70            $('.main_nav').removeAttr('style');
71            let offset = parseInt($(this).parent().offset().left) - parseInt($('.main_nav').css("padding-left"));
72            let max_width = $('.main_nav').outerWidth() - 2 * parseInt($('.main_nav').css("padding-left"));
73            let submenu_width = $(".sub-menu", $(this).parent()).width();
74            if (max_width < (offset + submenu_width)) $(this).parent().css('--offset', parseInt($(this).parent().offset().left) + "px");
75        }
76    }
77    $('.header_nav li.menu-item-has-children > a').hover(center_submenu).on('focus',center_submenu).click( function(){
78        if( isMobile() ){
79            $(this).parent().addClass("active");
80            $('.main_nav').height(
81                $("> .sub-menu", $(this).parent()).outerHeight()
82            );
83            return false;
84        }
85    } );
86    $('span', lis).click( function(){
87        $(this).closest('.menu-item-has-children').removeClass("active");
88        if( isMobile() ){
89            $('.main_nav').removeAttr('style');
90        }
91    } );
92
93
94    /* Widget Actualite */
95    $('.posts_slider_filters [data-filter]').click(function(){
96        $('[data-filter].active', $(this).parent()).removeClass('active').removeAttr("aria-pressed");
97        $(this).addClass('active').attr("aria-pressed","true");
98        let slider = $('.posts_slider_posts',$(this).closest('.posts_slider'));
99        slider.slick('slickUnfilter');
100        let filter = $(this).attr('data-filter');
101        if( filter == "all" ){
102            // for(let i=1;i<=4;i++){
103            //     if( filter == "all" ) filter = '#slick-slide0'+i;
104            //     else filter += ',#slick-slide0'+i;
105            // }
106            // slider.slick('slickFilter',filter);
107        }else{
108            slider.slick('slickFilter','.' + filter);
109        }
110        
111    });
112    $('.posts_slider_posts').each(function(){
113        $(this).on(slickResetDotTabindexActions, slickResetDotTabIndex).slick({
114            dots: true,
115            arrows: true,
116            variableWidth: false,
117            mobileFirst: true,
118            rows:null,
119            responsive: [
120                {
121                    breakpoint: 1540,
122                    settings: {
123                        infinite: true,
124                        slidesToShow: 3,
125                        slidesToScroll: 3,
126                    },
127                },
128                {
129                    breakpoint: 1200,
130                    settings: {
131                        slidesToShow: 2,
132                        slidesToScroll: 2,
133                        infinite:true,
134                    },
135                },
136                {
137                  breakpoint: 960,
138                  settings: {
139                    slidesToShow: 1,
140                    slidesToScroll: 1,
141                    infinite:true,
142                  },
143                }
144            ],
145            nextArrow: slickNextArrow,
146            prevArrow: slickPrevArrow
147        });
148    });
149
150    /* Widget Social Networks */
151    $('.vc_socialnetworks .network_links').each(function(){
152        $(this).on(slickResetDotTabindexActions, slickResetDotTabIndex).slick({
153            dots:true,
154            arrows: true,
155            variableWidth: true,
156            centerMode:true,
157            rows:null,
158            slideToShow:3,
159            slidesToScroll: 1,
160            nextArrow: slickNextArrow,
161            prevArrow: slickPrevArrow
162        });
163    });
164
165    /* L'etat d'ouverture du jour ("Ouvert / Fermé aujourd'hui") etait pose ici
166       a partir de l'attribut data-opening. Il est desormais calcule cote
167       serveur par crous_restaurant_ouvert() (includes/shortcuts.php) et ecrit
168       directement dans le HTML : le libelle existe sans JavaScript. */
169    $('.single-restaurant .menus').each(function(){
170        $(this).on(slickResetDotTabindexActions, slickResetDotTabIndex).slick({
171            dots:false,
172            arrows: false,
173            variableWidth: false,
174            centerMode:false,
175            slideToShow:1,
176            rows:null,
177            infinite:false,
178            nextArrow: slickNextArrow,
179            prevArrow: slickPrevArrow
180        });
181        $(this).on('click',".prev,.next",function(){
182            $(this).closest('.menus').slick( $(this).hasClass("prev")?'slickPrev':'slickNext');
183        });
184    });
185    function getSliderParams(slider){
186        return {
187            rows:slider.attr('data-rows')?1:null,
188            dots: true,
189            arrows: true,
190            variableWidth: false,
191            mobileFirst: true,
192            infinite: false,
193            responsive: [
194                {
195                    breakpoint: 1200,
196                    settings: {
197                        slidesToShow: slider.attr('data-rows')?1:parseInt(slider.attr('data-cols')),
198                        slidesToScroll: slider.attr('data-rows')?1:parseInt(slider.attr('data-cols')),
199                        slidesPerRow: parseInt(slider.attr('data-cols')),
200                        rows: slider.attr('data-rows')?parseInt(slider.attr('data-rows')):null,
201                    },
202                },
203                {
204                    breakpoint: 960,
205                    settings: {
206                        rows:slider.attr('data-rows')?1:null,
207                        slidesPerRow:slider.attr('data-rows')?1:null,
208                        slidesToShow: 2,
209                        slidesToScroll:slider.attr('data-rows')?2:1,
210                    },
211                }
212            ],
213            nextArrow: slickNextArrow,
214            prevArrow: slickPrevArrow
215        }
216    }
217    $('.vc_slider').each(function(){
218        $(this).data('childs',$('> *',$(this)));
219        $(this).on(slickResetDotTabindexActions, slickResetDotTabIndex).slick(getSliderParams($(this)));
220    });
221    $('.vc_partenaires [data-filter]').change(function(){
222        let parent = $(this).closest('.vc_partenaires');
223        let slider = $('.vc_slider', parent);
224        let slides = $.extend(true, {}, slider.data('childs'));
225        let slider_params = getSliderParams(slider)
226        let filters = $("[data-filter]",parent);
227        let filter = "";
228        filters.each( (key,filter_element) => {
229            if( $(filter_element).val() != "" ) filter = filter + "." + $(filter_element).attr("data-filter") + '-' + $(filter_element).val();
230        });
231
232        slider.slick('unslick');
233        slider.find( "> *" ).remove();
234        if( filter != "" ) slides = slides.filter(filter);
235        slider.append( slides );
236        slider.on(slickResetDotTabindexActions, slickResetDotTabIndex).slick( slider_params );
237    });
238
239
240    $('.single-restaurant #map, .single-logement #map').each( function(){
241        var map = L.map('map', {doubleClickZoom:false,zoomControl:false,scrollWheelZoom:false,dragging:false}).setView({lon: $(this).attr('data-lon'), lat: $(this).attr('data-lat')}, 16);
242        let icon_attr = {className: 'icon',popupAnchor:[0,-45],iconSize:[27,40],iconAnchor:[13,40]};
243        var icon = L.divIcon(icon_attr);
244
245        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
246            maxZoom: 19,
247            attribution: '&copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
248        }).addTo(map);
249
250        L.marker({ lon: $(this).attr('data-lon'), lat: $(this).attr('data-lat') }, {
251            icon: icon,
252            keyboard: false,
253        }).addTo(map);
254
255        $(this).attr('tabindex', '-1');
256        $('a,button', this).attr('tabindex', '-1');
257    });
258    $('.single-logement .photo:has(img:nth-child(2))').each(function () {
259        $(this).on(slickResetDotTabindexActions, slickResetDotTabIndex).slick({
260            dots: true,
261            arrows: true,
262            variableWidth: false,
263            mobileFirst: true,
264            adaptiveHeight: true,
265            rows:null,
266            centerMode: false,
267            slideToShow: 1,
268            nextArrow: slickNextArrow,
269            prevArrow: slickPrevArrow
270        });
271    });
272    
273    $('.vc_restaurants #map,.vc_logements #map').each( function(){
274        if( !points ) return;
275        let icon_attr = {className: 'icon',popupAnchor:[0,-45],iconSize:[27,40],iconAnchor:[13,40]};
276        var icon = L.divIcon(icon_attr);
277        icon_attr.className = 'icon_active';
278        var icon_active = L.divIcon(icon_attr);
279        
280        var map = L.map('map',{}
280).setView({lon: 0, lat: 0}, 16);
281        // add the OpenStreetMap tiles
282        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
283            maxZoom: 19,
284            attribution: '&copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
285        }).addTo(map);
286        
287        let markers = [];
288        let groups = {};
289        let bounds = L.latLngBounds();
290        let types = ['area', 'service','opening','type'];
291        for(var i in points ){
292            bounds.extend({lon: points[i].lon, lat: points[i].lat});
293            let content = '<div class="popup_content">';
294                content+= '<div class="popup_title">'+points[i].title+'</div>';
295            content += '<div class="popup_area">' + (points[i].adress ? points[i].adress : points[i].area)+'</div>';
296                content+= '<a class="button" href="'+points[i].link+'">En savoir plus</a>';
297            content+= "</div>";
298            markers[i] = L.marker({ lon: points[i].lon, lat: points[i].lat }, {
299                icon: icon,
300                keyboard: false,
301            });
302            markers[i].bindPopup(content)
303            markers[i].on('popupopen', function(ev) { this.setIcon(icon_active); })
304            markers[i].on('popupclose', function(ev) { this.setIcon(icon); });
305
306            types.forEach( type => {
307                if (points[i][type]) {
308                    var values = points[i][type].split(',');
309                    for( var i_value in values ){
310                        if (typeof groups[type + '-' + values[i_value]] == "undefined") groups[type + '-' + values[i_value]] = [];
311                        groups[type + '-' + values[i_value]].push(markers[i]);
312                    }
313                }
314            });
315            
316            markers[i].addTo(map);
317        }
318        let layer_groups = {};
319        
320        
321        for(var index in groups ){
322            layer_groups[index] = L.featureGroup(groups[index]);
323        }
324        
325        $('.vc_restaurants,.vc_logements').on("change",'[name="area"],[name="service"],[name="type"],[name="opening"]',function(){
326            let filters = []; let force_hide = false;
327            types.forEach(type => {
328                if (
329                    $('.vc_restaurants [name="' + type + '"],.vc_logements [name="' + type +'"]').val()
330                ){
331                    var index = type + "-" + $('.vc_restaurants [name="' + type + '"],.vc_logements [name="' + type + '"]').val();
332                    if (layer_groups[index]) filters.push(layer_groups[index]);
333                    else force_hide = true;
334                }
335            });
336            
337            for (var i in markers) {
338                let show = false;
339                if( force_hide == false ){
340                        if( filters.length == 0 ){
341                        show = true;
342                    }else{
343                        show = true;
344                        filters.forEach( group => {
345                            if( !group.hasLayer(markers[i]) ) show = false;
346                        });
347                    }
348                }
349                
350                var element = $('.vc_restaurants #item-' + i + ',.vc_logements #item-' + i);
351                if( show ){
352                    markers[i].addTo(map);
353                    element.show();
354                }
355                else{
356                    markers[i].closePopup();
357                    markers[i].remove();
358                    element.hide();
359                }
360            }
361        });
362        map.fitBounds(bounds);
363        $(this).attr('tabindex', '-1');
364        $('a,button',this).attr('tabindex', '-1');
365    });
366
367
368    if( $('.content_container .sidebar').length > 0 ){
369        $( window ).scroll(function(){
370            let top = $('.content_container').offset().top;
371            let content_padding_bottom = 34;
372            let scroll_top_space = 28;
373            if( isMobile() ){
374                let percent = ($(this).scrollTop() + $(this).outerHeight()*0.5 - top) / $('.page_content').outerHeight();
375                $('.vc_sidenav > ul:first-of-type > li:first-child').attr('style','--percent:'+(percent*100)+'%');
376                $('.content_container .sidebar').css('top','');
377            }else{
378                /* Les Sidebars follow le scroll */
379                if( $(this).scrollTop() > (top - scroll_top_space ) ){
380                    let offset = $(this).scrollTop() - top + scroll_top_space;
381                    $('.content_container .sidebar').each( function(){
382                        let height = $('.content_container').height();
383                        let elem_height = $(this).height();
384                        $(this).css("top", Math.min( offset, height - elem_height - content_padding_bottom) );
385                    });
386                }else{
387                    $('.content_container .sidebar').css('top','');
388                }
389            }
390
391            /* On "active" la bonne ancre de la left sidebar */
392            let elements = $('.page_content h1[id],.page_content h2[id],.page_content h3[id]');
393            let last_anchor_id = $(elements[0]).attr('id');
394            elements.each( (index,el) => {
395                if( $(el).offset().top < ($(this).scrollTop() + $(this).outerHeight()*0.5) ) last_anchor_id = $(el).attr('id');
396            });
397            $('.content_container .sidebar-left a.active').removeClass('active').removeAttr("aria-label");
398            $('.content_container .sidebar-left a[href="#'+last_anchor_id+'"]').addClass('active').attr("aria-label",$('.content_container .sidebar-left a[href="#'+last_anchor_id+'"]').text() + " - Lien actif");
399        });
400        $(window).trigger('scroll');
401        
402        $('.content_container .sidebar-left a').on('click', function (e) {
403            const href = $(this).attr('href');
404            if (!href || href.charAt(0) !== '#' || href === '#') return;
405
406            const $target = $(href);
407            if ($target.length === 0) return; // cible absente : on laisse le navigateur faire
408
409            e.preventDefault();
410
411            if (isMobile()) $("#sidenav_toggler").prop("checked", false);
412
413            // Une <section> ou un <div> n'est pas focusable nativement.
414            // tabindex="-1" le rend focusable par script sans l'ajouter
415            // à l'ordre de tabulation.
416            if (!$target.is('a[href], button, input, select, textarea, [tabindex]')) {
417                $target.attr('tabindex', '-1');
418            }
419
420            const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
421            const offset = $target.offset().top - (isMobile() ? 80 : 0);
422
423            $("html, body").stop().animate({ scrollTop: offset }, reduced ? 0 : 300)
424                .promise().done(function () {
425                    // preventScroll : sans lui, le focus refait défiler la page et
426                    // annule le décalage de 80px appliqué en mobile.
427                    $target[0].focus({ preventScroll: true });
428
429                    // L'URL reflète la position, et le lien devient partageable.
430                    if (window.history && history.pushState) history.pushState(null, '', href);
431                });
432        });
433    }
434
435    document.querySelectorAll('.vc_crous_map [data-dialog]').forEach(el => {
436        const dlg = document.getElementById(el.dataset.dialog);
437        if (!dlg) return;
438        const open = () => dlg.showModal();
439        el.addEventListener('click', open);
440        el.addEventListener('keydown', e => {
441            if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); open(); }
442        });
443    });
444
445    $("body:is(.archive,.post-type-archive) .filters .select").on("change", function () {
446        let params = new URLSearchParams(window.location.search);
447        let filter = $(this).attr('name');
448        if ($(this).val()) params.set(filter, $(this).val());
449        else params.delete(filter);
450        /* retour à la première page lors d'un changement de filtre */
451        params.delete("paged");
452        let path = window.location.pathname.replace(/\/page\/\d+\/?$/, "/");
453        window.location.href = path + (params.toString() ? "?" + params : "");
454    });
455
456    
457    /* Accessibility - add aria-pressed */
458    $(".vc_tta-tab").on("click", function(){
459        $(".vc_tta-tab", $(this).parent()).removeAttr("aria-pressed");
460        $(this).attr("aria-pressed","true");
461    });
462});

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.