PageSourceSearch

https://causses-gorgesaveyron.com/wp-content/plugins/plugin-sit/pu…/js/bridge-moteur.js?ver=7.1.3

js causses-gorgesaveyron.com collected 2026-10-10 00:45:11 UTC 51,129 bytes, 1,073 lines download raw bytes

1/**
2 *
3 *          Librairie de gestion des moteurs bridge
4 *
5 *
6 */
7
8window.bridgeMoteur = function(moteurId) {
9    this.eventsHandlers = {
10        beforeItemChange: [],
11        afterItemChange: [],
12        beforeCalcMoteur: [],
13        afterCalcMoteur: [],
14        beforeSubmit: [],
15        afterSubmit: []
16    };
17
18    this.options = {
19        submitOnChange: true,
20        lang: 'fr',
21        bridgeAjaxUrl: '',
22        bridgeAjaxListUrl: '',
23        // Libellés traduisibles, alimentés par init-moteur.php côté CMS.
24        labels: {
25            removeFilter: 'Retirer le filtre'
26        }
27    };
28
29    this.onSubmitFunction = null;
30    this.id = moteurId;
31    this.currentURL = '';
32    this.activeFilters = [];
33    this.activeFiltersLabels = [];
34    this.activeItems = [];
35    this.urlParams = [];
36    this.filters = [] ;
37
38    // élément HTML <datalist> qui contiendra les options du filtre citycombodyn
39    this.datalist = null;
40    // liste des options du filtre
41    this.cityComboDynList = null;
42
43    // paramètres des tris
44    this.activeSorts = [];
45    this.sortDirections = [];
46
47    // pour différencier une modification des filtres et un simple tri
48    this.filterHasChanged = false;
49
50
51    this.addEventHandler = function(handlerName, func)
52    {
53        if (Object.prototype.hasOwnProperty.call(this.eventsHandlers, handlerName) ) {
54            this.eventsHandlers[handlerName].push(func);
55        }
56    };
57
58
59    this.addFilter = function(obj) {
60        this.filters.push(obj);
61    };
62
63
64    this.findFilterProp = function(key, prop) {
65        var tabIds = key.split('-');
66
67        if (tabIds.length < 2) {
68            return '';
69        }
70
71        var temp = this.getFilter(tabIds[1]);
72
73        if (temp != false && temp[prop] != undefined) {
74            return temp[prop];
75        } else {
76            return '';
77        }
78    };
79
80
81    this.getFilter = function(filterId) {
82        var trouve = false;
83
84        for (var i = 0 ; i < this.filters.length && !trouve ; i++) {
85            if (this.filters[i].id == filterId) {
86                return this.filters[i] ;
87                trouve = true;
88            }
89        }
90        return trouve;
91    }
92
93
94    this.deactivateWholeFilter = function(filterId) {
95        var trouve = false;
96
97        this.filterHasChanged = true;
98
99        for (var i = 0 ; i < this.filters.length && !trouve ; i++) {
100            if (this.filters[i].id == filterId) {
101                this.filters[i].active = false;
102                this.filters[i].value = '';
103                this.filters[i].dateFrom = '';
104                this.filters[i].dateTo = '';
105                this.filters[i].hourFrom = '';
106                this.filters[i].hourTo = '';
107                this.filters[i].lat = '';
108                this.filters[i].lon = '';
109                // FIX TG 26 sept 2023 : On n'enlève pas la distance pour pas casser les filtres, on lui remet juste sa valeur par défaut
110                // this.filters[i].dist = '';
111                this.filters[i].dist = '5000';
112                if(this.filters[i].city) {
113                    this.filters[i].city = '';
114                }
115
116                for (var j = 0 ; j < this.filters[i].items.length && !trouve ; j++) {
117                    this.filters[i].items[j].active = false;
118                    this.filters[i].items[j].min = this.filters[i].items[j].baseMin;
119                    this.filters[i].items[j].max = this.filters[i].items[j].baseMax;
120                }
121                // ND 28/06/21 : effacer également les inputs text visibles
122                jQuery("input[data-bridge-filter-id='" + this.filters[i].id + "'][data-bridge-filter-field='" + this.filters[i].field + "']").val('').change();
123                trouve = true;
124            }
125        }
126        return trouve;
127    }
128
129
130    this.setFilterProp = function (filterId, prop, value, triggerChange) {
131        var trouve = false;
132
133        for (var i = 0 ; i < this.filters.length && !trouve ; i++) {
134            if (this.filters[i].id == filterId) {
135                this.filters[i][prop] = value;
136                for (var j = 0 ; j < this.filters[i].items.length && !trouve ; j++) {
137                    this.filters[i].items[j].active = false;
138                }
139                trouve = true;
140            }
141        }
142
143        if (trouve) {
144            this.calcMoteur(triggerChange);
145        }
146        return trouve;
147    }
148
149
150    this.addItem = function(filterId, obj) {
151        var trouve = false;
152        for (var i = 0 ; i < this.filters.length && !trouve ; i++) {
153            if (this.filters[i].id == filterId) {
154                this.filters[i].items.push(obj);
155                trouve = true;
156            }
157        }
158    };
159
160
161    this.setItem = function(filterId, itemId, obj) {
162        var trouve = false;
163        var x = 0;
164        var self = this;
165
166        for (var i = 0 ; i < this.filters.length && !trouve ; i++) {
167            if (this.filters[i].id == filterId) {
168                for (var j = 0 ; j < this.filters[i].items.length && !trouve ; j++) {
169                    if (this.filters[i].items[j].id == itemId) {
170                        for (x=0; x<self.eventsHandlers.beforeFilterChange.length; x++)
171                            self.eventsHandlers.beforeFilterChange[x](this.filters[i].id, this.filters[i]);
172                        for (x=0; x<self.eventsHandlers.beforeItemChange.length; x++)
173                            self.eventsHandlers.beforeItemChange[x](this.filters[i].id, this.filters[i].items[j].id, obj, this.filters[i].items[j]);
174
175                        this.filters[i].items[j] = obj;
176                        for (x=0; x<self.eventsHandlers.afterItemChange.length; x++)
177                            self.eventsHandlers.afterItemChange[x](this.filters[i].id, this.filters[i].items[j].id, obj);
178
179                        trouve = true;
180                    }
181                }
182            }
183        }
184
185        if (trouve)
186            this.calcMoteur(true);
187        return trouve;
188    }
189
190
191    this.findItemProp = function(key, prop) {
192        var tabIds = key.split('-');
193        if (tabIds.length < 3)
194            return '';
195        var temp = this.getItem(tabIds[1], tabIds[2]);
196        return temp[prop];
197    };
198
199
200    this.getItem = function(filterId, itemId) {
201        var trouve = false;
202        for (var i = 0 ; i < this.filters.length && !trouve ; i++) {
203            if (this.filters[i].id == filterId) {
204                for (var j = 0 ; j < this.filters[i].items.length && !trouve ; j++) {
205                    if (this.filters[i].items[j].id == itemId) {
206                        return this.filters[i].items[j] ;
207                        trouve = true;
208                    }
209                }
210            }
211        }
212        return trouve;
213    }
214
215
216    this.setItemProp = function(filterId, itemId, prop, value) {
217        var trouve = false;
218        var x = 0;
219        var self = this;
220
221        for (var i = 0 ; i < this.filters.length && !trouve ; i++) {
222            if (this.filters[i].id == filterId) {
223                for (var j = 0 ; j < this.filters[i].items.length && !trouve ; j++) {
224                    if (this.filters[i].items[j].id == itemId) {
225                        for (x=0; x<self.eventsHandlers.beforeItemChange.length; x++)
226                            self.eventsHandlers.beforeItemChange[x](this.filters[i].id, this.filters[i].items[j].id, obj, this.filters[i].items[j]);
227
228                        this.filters[i].items[j][prop] = value;
229                        trouve = true;
230
231                        for (x=0; x<self.eventsHandlers.afterItemChange.length; x++)
232                            self.eventsHandlers.afterItemChange[x](this.filters[i].id, this.filters[i].items[j].id, obj);
233                    }
234                }
235            }
236        }
237        // Patch 20/11/2019 : on ne fait pas de calc pour éviter les appels en cascade, c'est aux inputs de lancer leur calc
238        /*
239        if(trouve) {
240            this.calcMoteur(true);
241        }
242        */
243
244        return trouve;
245    }
246
247    /**
248     * Appelée par js-tris.php à l'activation, la modification ou la désactivation d'un tri dans l'interface
249     * Transmet les informations sur les tris pour l'appel AJAX (this.searchAjax) de mise à jour de la liste
250     * @param {Array} activeSorts : tris activés
251     * @param {Array} sortDirections : directions choisies pour les tris activés
252     */
253    this.setSortsAndSortDirections = function(activeSorts, sortDirections) {
254        this.activeSorts = activeSorts;
255        this.sortDirections = sortDirections;
256    }
257
258    /**
259     * Appelée par js-select-dropdown.php au chargement ou au rechargement d'une webliste contenant un filtre de type cityComboDyn
260     * (chargement initial de la page ou actualisation après application d'un filtre)
261     * Affiche la liste des communes des fiches de la webliste dans un combo box
262     * @param {String} cityComboDynList : liste des communes à afficher comme options pour le filtre
263     * @param {Object} datalist : élément HTML <datalist> qui contiendra les options à afficher
264     */
265    this.displayCityComboDynList = function(cityComboDynList, datalist) {
266
267        if (cityComboDynList == '') {
268            cityComboDynList = 'Aucune ville à afficher';
269        }
270
271        this.datalist = datalist;
272
273        // on efface la liste qui existait déjà
274        while (datalist.children.length > 0) {
275            datalist.removeChild(datalist.lastChild);
276        }
277
278        let cityList = [];
279
280        this.cityComboDynList = cityComboDynList;
281
282        cityList = cityComboDynList.split(',');
283
284        for (let city of cityList) {
285            let option = document.createElement("option");
286            option.text = city;
287            option.value = city;
288            option.id = "opt_<?= $moteurEnDouble ?><?= $moteur->id ?>-<?= $filter->id ?>-" + city;
289
290            datalist.appendChild(option);
291        }
292    }
293
294    /**
295     * Remplace certains caractères spéciaux par les entités HTML correspondantes pour éviter les problèmes avec les saisies utilisateur
296     * @param {String} text : string à modifier
297     * @returns String : string modifiée
298     */
299    this.escapeHtml = function(text) {
300        var map = {
301            '&': '&amp;',
302            '<': '&lt;',
303            '>': '&gt;',
304            '"': '&quot;',
305            "'": '&#039;',
306            "`": '&grave;',
307            "+": '&plus;'
308        };
309
310        return text.replace(/[&<>"'`+]/g, function(m) {return map[m];});
311    }
312
313    /**
314     * Texte lisible d'une étiquette de filtre actif : intitulé du filtre et valeurs
315     * retenues, débarrassés des balises (un item peut porter une <img>). Sert de nom
316     * accessible au bouton qui retire ce filtre.
317     * @param {Object} activeFilterLabel : une entrée de this.activeFiltersLabels
318     * @returns String
319     */
320    this.activeFilterText = function(activeFilterLabel) {
321        var parts = [];
322        if (activeFilterLabel.label != undefined && activeFilterLabel.label !== '') {
323            parts.push(activeFilterLabel.label);
324        }
325        if (activeFilterLabel.items && activeFilterLabel.items.length) {
326            parts.push(activeFilterLabel.items.join(', '));
327        }
328        return parts.join(' : ').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
329    }
330
331    this.calcMoteur = function(isChanged) {
332
333        var self = this;
334        var tmpActive;
335        var activeFilters = [];
336        var activeFiltersLabels = [];
337        var activeItems = [];
338        var urlParams = {};
339        var tmpFilter;
340        var i;
341        var j;
342        var x;
343        var cmpt;
344        var label;
345        var image;
346        var tmpObj;
347        var tmpItems = [];
348        var tempStr = '';
349        var section = '';
350        var activeItemIdx = 0;
351
352        // on garde juste les filter_lat, filter_lon et filter_rayon s'ils existent déjà
353        if (this.urlParams.filter_lat) {
354            urlParams.filter_lat = this.urlParams.filter_lat;
355        }
356
357        if (this.urlParams.filter_lon) {
358            urlParams.filter_lon = this.urlParams.filter_lon;
359        }
360
361        if (this.urlParams.filter_rayon) {
362            urlParams.filter_rayon = this.urlParams.filter_rayon;
363        }
364
365        var tmpActiveFilters = this.activeFilters;
366        var tmpActiveItems = this.activeItems;
367
368        for (x=0; x<self.eventsHandlers.beforeCalcMoteur.length; x++) {
369            self.eventsHandlers.beforeCalcMoteur[x](this);
370        }
371
372        for (i = 0 ; i < this.filters.length ; i++) {
373            tmpActive = false;
374
375            switch (this.filters[i].displayType) {
376                case 'slidedoubleminmax':
377                    if(this.filters[i].items.length == 0) {
378                        console.error('ERREUR DE PARAMETRAGE BRIDGE : un element slide double min/max n\'a pas d\'item renseigné : filtre n° ' + this.filters[i].id);
379                    } else {
380                        if (this.filters[i].items[0].min != this.filters[i].items[0].baseMin || this.filters[i].items[0].max != this.filters[i].items[0].baseMax) {
381                            this.filters[i].active = true;
382                            activeFilters.push(this.id + '-' + this.filters[i].id );
383                            activeItems.push(this.id + '-' + this.filters[i].id + '-' + this.filters[i].items[0].id );
384                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_min'] = this.filters[i].items[0].min;
385                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_max'] = this.filters[i].items[0].max;
386                        } else {
387                            // Important : effacer le statut actif
388                            this.filters[i].active = false;
389                        }
390                    }
391                    break;
392                case 'checkbox':
393                case 'boutonbox':
394                case 'boutonboxdyn':
395                case 'checkboxdyn':
396                case 'citycombo':
397                case 'combo':
398                case 'combodyn':
399                case 'listemulti':
400                case 'onoff':
401                case 'option':
402                case 'optionbutton':
403                case 'optiondyb':
404                case 'slidedouble':
405                case 'slidesimple':
406                case 'slidesimpledyn':
407                    isActive = false;
408                    activeItemIdx = 0;
409                    for (j = 0; j < this.filters[i].items.length ; j++) {
410                        if (this.filters[i].items[j].active) {
411                            isActive = true;
412                            activeItemIdx = j;
413                            activeItems.push(this.id + '-' + this.filters[i].id + '-' + this.filters[i].items[j].id);
414                            // Patch 18/04/23 : tenir compte des min max enregistrés dans les filtres
415                            // Patch 17/02/2024 : on essaie de déplacer pour pouvoir cumuler un critère avec valeur prédéfinie avec une autre mais ça pourra avoir des effets de bords
416                            // Mais de toute façon il y en avait déjà lorsqu'on mélange les chèvres et les choux dans un même filtre
417                            if (this.filters[i].items[activeItemIdx].baseMin !== undefined && this.filters[i].items[activeItemIdx].baseMin !== '' && this.filters[i].items[activeItemIdx].baseMin !== null) {
418                                if (
419                                    !urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_min'] ||
420                                    urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_min'] > this.filters[i].items[activeItemIdx].baseMin
421                                ) {
422                                    urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_min'] = this.filters[i].items[activeItemIdx].baseMin;
423                                }
424                            }
425                            if (this.filters[i].items[activeItemIdx].baseMax !== undefined && this.filters[i].items[activeItemIdx].baseMax !== '' && this.filters[i].items[activeItemIdx].baseMax !== null) {
426                                if (
427                                    !urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_max'] ||
428                                    urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_max'] < this.filters[i].items[activeItemIdx].baseMax
429                                ) {
430                                    urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_max'] = this.filters[i].items[activeItemIdx].baseMax;
431                                }
432                            }
433                        }
434                    }
435                    this.filters[i].active = isActive
436                    if (isActive) {
437                        activeFilters.push(this.id + '-' + this.filters[i].id);
438                    }
439                    break;
440
441
442                case 'calendar':
443                case 'dateRangePicker':
444                case 'calendarhours':
445                case 'prochainesperiodes':
446                case 'disponibilites':
447                    isActive = false;
448                    if ((this.filters[i].dateFrom && this.filters[i].dateFrom !='') || (this.filters[i].dateTo && this.filters[i].dateTo !='')) {
449                        isActive = true;
450                        if (this.filters[i].dateFrom)
451                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_dateFrom'] = this.filters[i].dateFrom;
452                        if (this.filters[i].dateTo)
453                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_dateTo'] = this.filters[i].dateTo;
454                        if (this.filters[i].hourFrom)
455                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_hourFrom'] = this.filters[i].hourFrom;
456                        if (this.filters[i].hourTo)
457                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_hourTo'] = this.filters[i].hourTo;
458
459                    }
460
461                    this.filters[i].active = isActive
462                    if (isActive)
463                        activeFilters.push(this.id + '-' + this.filters[i].id);
464
465                    break;
466                case 'cityprox':
467                case 'cityproxdyn':
468                case 'gps':
469                    isActive = false;
470                    if ((this.filters[i].lat && this.filters[i].lat !='') && (this.filters[i].lon && this.filters[i].lon !='') && (this.filters[i].dist && this.filters[i].dist !='')) {
471                        isActive = true;
472                        if(this.filters[i].lat)
473                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_lat'] = this.filters[i].lat;
474                        if(this.filters[i].lon)
475                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_lon'] = this.filters[i].lon;
476                        if(this.filters[i].dist)
477                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_dist'] = this.filters[i].dist;
478                        if(this.filters[i].city)
479                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_city'] = encodeURI(this.filters[i].city);
480                    }
481
482                    this.filters[i].active = isActive
483                    if (isActive)
484                        activeFilters.push(this.id + '-' + this.filters[i].id);
485
486                    break;
487                case 'citycombodyn':
488                case 'cityinput':
489                case 'input':
490                case 'hidden':
491                    isActive = false;
492
493                    if ((this.filters[i].value && this.filters[i].value !== '')) {
494                        isActive = true;
495                        if (this.filters[i].value) {
496                            // Patch ND 13/01/22 : les accents et espaces ne sont pas encodés
497                            urlParams['brflt_' + this.id + '-' + this.filters[i].id + '_value'] = encodeURI(this.filters[i].value);
498                        }
499                    }
500
501                    this.filters[i].active = isActive
502                    if (isActive)
503                        activeFilters.push(this.id + '-' + this.filters[i].id);
504                    break;
505            }
506        }
507
508        this.activeFilters = activeFilters;
509        this.activeItems = activeItems;
510
511        var activeFiltersComp = this.activeFilters;
512        var activeItemsComp = this.activeItems;
513
514        if (JSON.stringify(tmpActiveFilters) !== JSON.stringify(activeFiltersComp) || JSON.stringify(tmpActiveItems) !== JSON.stringify(activeItemsComp)) {
515            this.filterHasChanged = true;
516        }
517
518        this.urlParams = urlParams;
519
520        for (i = 0 ; i < activeFilters.length ; i++) {
521            tmpFilter = activeFilters[i];
522            label = this.findFilterProp(activeFilters[i], 'label');
523            section = this.findFilterProp(activeFilters[i], 'sectionId');
524            tmpObj = {
525                sectionId: section,
526                key: tmpFilter,
527                label: label,
528                items:[]
529            };
530
531            // Pour les items prédéfinis, on va chercher leur label
532            for (cmpt = 0; cmpt < activeItems.length; cmpt++) {
533                if (activeItems[cmpt].indexOf(tmpFilter) == 0) {
534                    label = this.findItemProp(activeItems[cmpt], 'label');
535                    image = this.findItemProp(activeItems[cmpt], 'image');
536                    if (image != undefined && image !== '') {
537                        label = '<img src="' + image  + '" class="bridge-engine-image"/>' + label;
538                    }
539                    tmpObj.items.push(label);
540
541                    // Cas particulier du slidedoubleminmax qui a des items mais sans valeurs prédéfinies : on veut afficher les valeurs et le label de l'item et non ceux du filtre lui-même
542                    let typeCtrl = this.findFilterProp(activeFilters[i],'displayType');
543                    let slideDoubleMin = this.findItemProp(activeItems[cmpt], 'min');
544                    let slideDoubleMax = this.findItemProp(activeItems[cmpt], 'max');
545
546                    if (typeCtrl === 'slidedoubleminmax' && slideDoubleMin != null && slideDoubleMax != null) {
547                        tmpObj.label = tmpObj.items[0];
548                        let slideDoubleMinMax = slideDoubleMin + '-' + slideDoubleMax;
549                        tmpObj.items.splice(0, 1, slideDoubleMinMax);
550                    }
551                }
552            }
553
554            // Pour les valeurs, on les met dans un item
555            var tmpValue = this.findFilterProp(activeFilters[i], 'value');
556            if (tmpValue != '') {
557                tmpObj.items.push(tmpValue);
558            }
559
560            var tmpDateFrom = this.findFilterProp(activeFilters[i], 'dateFrom');
561            var tmpDateTo = this.findFilterProp(activeFilters[i], 'dateTo');
562            if (tmpDateFrom != '' && tmpDateTo != '') {
563                tmpObj.items.push(tmpDateFrom + '-' + tmpDateTo);
564            } else {
565                if (tmpDateFrom != '') {
566                    tmpObj.items.push(tmpDateFrom);
567                }
568                if (tmpDateTo != '') {
569                    tmpObj.items.push(tmpDateTo);
570                }
571            }
572
573            // Pour la distance, on la ville et la distance en km
574            var tmpCity = this.findFilterProp(activeFilters[i], 'city');
575            var tmpDist = this.findFilterProp(activeFilters[i], 'dist');
576            if (tmpCity != null && tmpCity != '' && tmpDist != null && tmpDist != '') {
577                tmpDist = (parseInt(tmpDist) / 1000) + ' km';
578                tmpObj.items.push(tmpCity + ' : ' + tmpDist);
579            }
580
581            activeFiltersLabels.push(tmpObj);
582        }
583
584        this.activeFiltersLabels = activeFiltersLabels;
585
586        var tabAllActiveFiltersString = [];
587        var tabSectionsActiveFiltersString = {};
588
589        for (i=0 ; i < activeFiltersLabels.length ; i++) {
590            tempStr = '';
591            tempStr += '<div class="bridgeActiveFilter uk-label">';
592            tempStr += '<span class="bridgeActiveFilterLabel">'
593
594            if ((activeFiltersLabels[i].label != undefined && activeFiltersLabels[i].label != '') || (activeFiltersLabels[i].image != undefined && activeFiltersLabels[i].image != '')) {
595
596                if (activeFiltersLabels[i].label != undefined && activeFiltersLabels[i].label != '') {
597                    tempStr += activeFiltersLabels[i].label;
598                }
599                tempStr += ': ';
600            }
601
602            tempStr += activeFiltersLabels[i].items.join(', ');
603            tempStr += '</span>';
604            // La croix était un <span> : ni focusable, ni actionnable au clavier, et sans
605            // intitulé (RGAA 7.3 / WCAG 2.1.1, 4.1.2). C'est désormais un <button> nommé
606            // « Retirer le filtre » suivi du libellé du filtre, pour distinguer les étiquettes
607            // entre elles. Le libellé peut contenir du HTML (image d'item) : on le nettoie.
608            tempStr += '<button type="button" class="bridgeActiveFilterRemove far fa fa-times"';
609            tempStr += ' aria-label="' + this.escapeHtml(((this.options.labels && this.options.labels.removeFilter) || 'Retirer le filtre') + ' ' + this.activeFilterText(activeFiltersLabels[i])) + '"';
610            tempStr += ' data-filter-key="' + activeFiltersLabels[i].key + '" data-moteur-id="' + this.id + '">';
611            tempStr += '</button>';
612            tempStr += '</div>';
613
614            if (i + 1 === activeFiltersLabels.length) {
615                //  tempStr += '<a class="bridgeActiveFilterRemoveAll">Tout effacer</a>';
616            }
617            tabAllActiveFiltersString.push(tempStr);
618            if(tabSectionsActiveFiltersString[activeFiltersLabels[i].sectionId] == undefined) {
619                tabSectionsActiveFiltersString[activeFiltersLabels[i].sectionId] = []
620            }
621
622            tabSectionsActiveFiltersString[activeFiltersLabels[i].sectionId].push(tempStr)
623        }
624
625        if(activeFiltersLabels.length > 0) {
626            jQuery('.bridgeActiveFilterRemoveAll').css('display', 'inline');
627            jQuery('.bridgeActiveFilterRemoveAll').show();
628        } else {
629            jQuery('.bridgeActiveFilterRemoveAll').css('display', 'none');
630            jQuery('.bridgeActiveFilterRemoveAll').hide();
631        }
632        jQuery(".bridgeActiveFiltersDiv").html(tabAllActiveFiltersString.join(' '));
633
634
635        for (var prop in tabSectionsActiveFiltersString) {
636            if (Object.prototype.hasOwnProperty.call(tabSectionsActiveFiltersString, prop) && tabSectionsActiveFiltersString[prop].length > 0) {
637                jQuery(".bridgeActiveFiltersDivSection" + prop).html(tabSectionsActiveFiltersString[prop].join(' '));
638            }
639        }
640        jQuery("*[class^='bridgeActiveFiltersDivSection']").each(function(e) {
641
642            var sectionId = jQuery(this).attr('data-section-id');
643            if (Object.prototype.hasOwnProperty.call(tabSectionsActiveFiltersString, sectionId) && tabSectionsActiveFiltersString[sectionId].length > 0) {
644                jQuery(this).show(500);
645            } else {
646                jQuery(this).hide(500);
647            }
648        });
649
650        jQuery(".bridgeActiveFilterRemove").click(function(e) {
651            var key = jQuery(this).attr('data-filter-key');
652            var tabTemp = key.split('-');
653
654            if (tabTemp.length == 2 && window['bridgeMoteur' + tabTemp[0]] != undefined) {
655                window['bridgeMoteur' + tabTemp[0]].deactivateWholeFilter(tabTemp[1]);
656                window['bridgeMoteur' + tabTemp[0]].calcMoteur(true);
657            }
658        });
659
660
661        // lien qui supprime tout les filtres
662        jQuery(".bridgeActiveFilterRemoveAll").click(function (e) {
663            var nummoteur = '';
664            jQuery(".bridgeActiveFilterRemove").each(function() {
665                // Trop minimaliste
666                // jQuery(this).click();
667                var key = jQuery(this).attr('data-filter-key');
668                var tabTemp = key.split('-');
669                nummoteur = tabTemp[0];
670
671                if (tabTemp.length == 2 && window['bridgeMoteur' + tabTemp[0]] != undefined) {
672                    window['bridgeMoteur' + tabTemp[0]].deactivateWholeFilter(tabTemp[1]);
673                }
674            });
675            window['bridgeMoteur' + nummoteur].calcMoteur(true);
676        }) ;
677        /*  WTF
678          e => {
679          for (const key of Object.keys(window)) {
680              if (!key.startsWith("bridgeMoteur")) {
681                  continue;
682              }
683
684              if (typeof window[key] === "function") {
685                  continue;
686              }
687
688              const filterIds = window[key].activeFilters.map(id => id.replace("6-", ""));
689
690              filterIds.forEach(id => window[key].deactivateWholeFilter(id));
691
692              window[key].calcMoteur(true);
693          }
694      });
695      */
696        for (x=0; x<self.eventsHandlers.afterCalcMoteur.length; x++)
697            self.eventsHandlers.afterCalcMoteur[x](this);
698
699        if (isChanged && this.options.submitOnChange) {
700            var stateObj = JSON.parse(JSON.stringify(this.getUrlState()));
701            var url = "?" + this.getUrlParams();
702            // 07/06/2025 : conserver également les paramètres d'URL supplémentaires
703            var attributesUrlParams = this.getAttributesUrlParams(true);
704            if(attributesUrlParams !== '') {
705                url += attributesUrlParams;
706            }
707            history.pushState(stateObj, jQuery(document).find("title").text(), url);
708            this.submit();
709        }
710        else if (isChanged) {
711            // ND 27/08/2024 : j'ajoute cette instruction pour que lorsuq'on met un moteur seul
712            // En shortcode avec nb de résultats visibles mais pas de submit auto
713            // le nb de résultats bouge quand on coche une case
714            this.searchAjax();
715        }
716
717    }
718
719    this.getUrlParams = function() {
720        var self = this ;
721        var urlParams = '';
722        if(this.activeFilters !== null) {
723            urlParams += 'braf=' + this.activeFilters.join(',');
724        }
725        if(this.activeItems !== null) {
726            urlParams += '&brai=' + this.activeItems.join(',');
727        }
728
729        if (this.activeSorts.length > 0) {
730            urlParams += '&bras=' + this.activeSorts.join(',');
731            urlParams += '&brsd=' + this.sortDirections.join(',');
732        }
733
734        Object.keys(this.urlParams).forEach(function(key,index) {
735            urlParams += '&' + key + '=' + self.urlParams[key] ;
736        });
737
738        return urlParams;
739        // location.hash = "parameter1=987&parameter2=zyx";
740    }
741
742    // Construit une partie de chaine de paramètres d'URL poru le service Bridge getForDisplay
743    // A partir des attributs d'origine de la liste (filtres supplémentaires ou en override)
744    this.getAttributesUrlParams = function(onlyForWordpress) {
745        var self = this ;
746        var urlParams = '';
747        var urlParamsForWordpress = '';
748        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('item_template') && this.options.item_template !== '') {
749            urlParams += '&item_template=' + this.options.item_template;
750        }
751
752        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('productCodes') && this.options.productCodes !== '') {
753            urlParams += '&product_codes=' + this.options.productCodes;
754        }
755        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('filter_city') && this.options.filter_city !== '') {
756            urlParams += '&filter_city=' + this.options.filter_city;
757        }
758        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('filter_lat') && this.options.filter_lat !== '') {
759            urlParams += '&filter_lat=' + this.options.filter_lat;
760        }
761        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('filter_lon') && this.options.filter_lon !== '') {
762            urlParams += '&filter_lon=' + this.options.filter_lon;
763        }
764        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('filter_rayon') && this.options.filter_rayon !== '') {
765            urlParams += '&filter_rayon=' + this.options.filter_rayon;
766        }
767        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('selection_id') && this.options.selection_id !== '') {
768            urlParams += '&selection_id=' + this.options.selection_id;
769            urlParamsForWordpress += '&selection_id=' + this.options.selection_id;
770        }
771        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('filter_criterions') && this.options.filter_criterions !== '') {
772            urlParams += '&filter_criterions=' + escape(this.options.filter_criterions);
773        }
774        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('scoring') && this.options.scoring !== '') {
775            urlParams += '&scoring=' + this.options.scoring;
776            urlParamsForWordpress += '&scoring=' + this.options.scoring;
777        }
778        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('minscore') && this.options.minscore !== '') {
779            urlParams += '&minscore=' + this.options.minscore;
780            urlParamsForWordpress += '&minscore=' + this.options.minscore;
781        }
782        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('excluded_codes') && this.options.excluded_codes !== '') {
783            urlParams += '&excluded_codes=' + this.options.excluded_codes;
784        }
785        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('sort_one') && this.options.sort_one !== '') {
786            urlParams += '&sort_one=' + this.options.sort_one;
787        }
788        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('sort_two') && this.options.sort_two !== '') {
789            urlParams += '&sort_two=' + this.options.sort_two;
790        }
791        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('sort_three') && this.options.sort_three !== '') {
792            urlParams += '&sort_three=' + this.options.sort_three;
793        }
794        if(this.options !== null && typeof this.options === 'object' && this.options.hasOwnProperty('duplicate_by') && this.options.duplicate_by !== '') {
795            urlParams += '&duplicate_by=' + this.options.duplicate_by;
796        }
797
798        if(onlyForWordpress) {
799            return urlParamsForWordpress;
800        } else {
801            return urlParams;
802        }
803
804        // location.hash = "parameter1=987&parameter2=zyx";
805    }
806
807    this.getUrlState = function() {
808
809        if(this.activeFilters === null) {
810            this.activeFilters = [];
811        }
812        var urlParams = { braf: this.activeFilters.join(','), brai: this.activeItems, bras: this.activeSorts, brsd: this.sortDirections };
813        var self = this ;
814        var toto;
815
816        Object.keys(this.urlParams).forEach(function(key,index) {
817            urlParams[key] = self.urlParams[key];
818            // toto = self.urlParams[key] ;
819        });
820
821
822        return urlParams;
823        // location.hash = "parameter1=987&parameter2=zyx";
824    }
825
826    this.submit = function() {
827
828        var self = this;
829        for (x=0; x<self.eventsHandlers.beforeSubmit.length; x++)
830            self.eventsHandlers.beforeSubmit[x](this);
831
832        var url = this.currentURL ; // + '?braf=' + this.activeFilters.join(',');
833        var urlParams = this.getUrlParams();
834
835        if (this.onSubmitFunction != null) {
836            this.onSubmitFunction(url, urlParams);
837        } else {
838            this.searchAjax();
839        }
840        //window.location = url + '?' + urlParams;
841        //this.searchAjax();
842        // window.location = url + '?' + urlParams;
843    }
844
845    this.searchAjax = function() {
846        var context = this;
847        var urlParams = this.getUrlParams();
848        var attributesUrlParams = this.getAttributesUrlParams();
849        if (urlParams != '')
850            urlParams = '&' + urlParams;
851        var self = this;
852        var change = 1;
853        // si on change un filtre plutôt qu'un tri, on a besoin de recharger le filtre cityComboDyn
854        if (this.filterHasChanged) {
855            change = 1;
856        }
857        jQuery('.bridge-loader').fadeIn(100);
858        jQuery.ajax ({
859            type: "GET",
860            dataType: "json",
861            beforeSend: function(xhr) {
862                xhr.setRequestHeader('X-GT-Translate-Keys', 'html->html');
863            },
864            headers: {
865                'X-GT-Translate-Keys': 'html->html'
866            },
867            url: this.options.bridgeAjaxListUrl,
868            // data: 'action=brListe&id=' + this.options.webListId + '&product_codes=' + this.options.productCodes + '&first=1&max=' + this.options.limitPerPage + urlParams + '&change=' + change,
869            data: 'action=brListe&id=' + this.options.webListId + attributesUrlParams + '&first=1' + urlParams + '&change=' + change + '&lang=' + this.options.lang,
870            success: function (response) {
871                jQuery('.bridge-loader').fadeOut({ duration: 500 });
872                if (true || response.html) { // response.total &&  response.total !== 0
873                    var uniqueID = jQuery('.bridge-liste[data-moteur-id=' + self.id + ']').attr('data-bridge-identifier');
874
875                    // On désactive l'infinite scroll car on le remet de toute manière plus loin
876                    if(window['bridgeInfiniteScroll_' + uniqueID] !== undefined) {
877                        window['bridgeInfiniteScroll_' + uniqueID].unbind();
878                    }
879
880                    if (response.moteur) {
881                        const moteurId = response.moteur.id;
882                        // pour chaque moteur.section
883                        for (const section of response.moteur.sections) {
884                            if (!section.subSections || section.subSections.length === 0) continue;
885
886                            for (const subsection of section.subSections) {
887                                if (!subsection.filters || subsection.filters.length === 0) continue;
888
889                                for (const filter of subsection.filters) {
890                                    if (!filter.parameters || !filter.parameters.display_results) continue;
891
892                                    if (!filter.items || filter.items.length === 0) continue;
893
894                                    for (const item of filter.items) {
895                                        const countComposants = jQuery(document).find(`.bridge-count[data-item-id=${item.id}]`);
896
897                                        countComposants.each(function () {
898                                            const countComposant = jQuery(this);
899                                            countComposant.text(`(${item.count})`);
900
901                                            if (item.count === 0) {
902                                                if (filter.parameters.hasOwnProperty('disable_if_empty') && filter.parameters.disable_if_empty === true) {
903                                                    jQuery(document).find(`input[data-item-id=${item.id}]`).each(function () {
904                                                        // on disable pas si la case est coché, pour pouvoir la décocher
905                                                        if (!jQuery(this).prop("checked")) {
906                                                            jQuery(this).prop("disabled", true)
907                                                            jQuery(this).addClass('bridge-disabled')
908                                                            jQuery(this).closest('label').addClass('bridge-disabled')
909                                                        }
910                                                    });
911                                                }
912                                                if (filter.parameters.hasOwnProperty('hide_if_empty') && filter.parameters.hide_if_empty === true) {
913                                                    jQuery(document).find(`input[data-item-id=${item.id}]`).each(function () {
914                                                        // on masque pas si la case est coché, pour pouvoir la décocher
915                                                        if (!jQuery(this).prop("checked")) {
916                                                            jQuery(this).addClass('bridge-hidden')
917                                                            jQuery(this).closest('label').addClass('bridge-hidden')
918                                                        }
919                                                    });
920                                                }
921                                            } else {
922                                                jQuery(document).find(`input[data-item-id=${item.id}]`).each(function () {
923                                                    jQuery(this).prop("disabled", false).removeClass('bridge-disabled').removeClass('bridge-hidden');
924                                                    jQuery(this).closest('label').removeClass('bridge-disabled').removeClass('bridge-hidden');
925                                                });
926                                            }
927                                        });
928                                    }
929                                }
930                            }
931                        }
932                    }
933
934                    jQuery('*[data-moteur-id=' + self.id + ']').find(".listeSITCount").html(response.total);
935                    if(response.total !== 0) {
936                        var $items = jQuery(response.html);
937                        jQuery('*[data-moteur-id=' + self.id + ']').find(".listeSIT").html($items);
938
939                        $items.find('.zoom-on-hover').hover( function() {
940                            var idfiche = jQuery(this).attr('data-dnc-produit');
941                            if(idfiche !== '') {
942                                window.mapService.activatemarker(idfiche, true, true); // window.mapService.defaultIconOptions
943                                window.mapService.centeronmarker(idfiche, "15");
944                                // tricherie obligatoire pour forcer le point à s'afficher la premiere fois
945                                setTimeout(function() {
946                                    window.mapService.setZoom(15);
947                                },500);
948                                window.mapService.reDraw();
949
950                            }
951                        });
952
953                        // setTimeout(function () {
954                        $items.find('.zoom-on-click').click(function() {
955                            var idfiche = jQuery(this).attr('data-dnc-produit');
956                            if(idfiche !== '') {
957                                window.mapService.activatemarker(idfiche, true, true); // window.mapService.defaultIconOptions
958                                window.mapService.centeronmarker(idfiche, "15");
959                                // tricherie obligatoire pour forcer le point à s'afficher la premiere fois
960                                setTimeout(function() {
961                                    window.mapService.setZoom(15);
962                                },500);
963                                window.mapService.reDraw();
964                            }
965                        });
966
967
968
969                    } else {
970                        // aucun résultat
971                        jQuery('.bridge-liste[data-moteur-id=' + self.id + ']').find(".listeSIT").html('<div>' + response.message + '</div>');
972                    }
973                    window.bridgeTotalResults = response.total;
974
975                    for (x=0; x<self.eventsHandlers.afterSubmit.length; x++)
976                        self.eventsHandlers.afterSubmit[x](this);
977
978                    var currentURL = window.location.href.split('?')[0] ;
979                    var nbLinks = 1;
980                    var start      =  1;
981                    var end        =  parseInt(response.lastPage);
982                    var attributesUrlParams = self.getAttributesUrlParams();
983
984                    /* PATCH CLEMENT : 27/07/2023 - Bizarre qu'on ajoute ça...
985                    if ( ( 1 + nbLinks ) < parseInt(response.lastPage) ) {
986                        end = 1 + nbLinks
987                    }*/
988
989                    // Ici on met à jour la pagination en repartant la page 1
990                    var pagination = '<ul class="bridge-pagination uk-pagination uk-flex-center" uk-margin>';
991                    pagination +='    <li class="uk-disabled""><a class="bridge-pagination-link" data-page="1" href="#nogo">&nbsp;<span uk-pagination-previous></span></a></li>' ;
992                    var tmpdisable = '';
993                    for (var i = start ; i <= end ; i++) {
994                        if(i === 1) {
995                            pagination += '    <li class="uk-active"><a class="bridge-pagination-link" data-page="' + i + '" href="#nogo">' + i + '</a></li>';
996                        } else {
997                            pagination += '    <li class=""><a class="bridge-pagination-link" data-page="' + i + '" href="' + currentURL + '?brpa=' + i + urlParam
997s + '">' + i + '</a></li>';
998                        }
999                    }
1000                    if ( end < parseInt(response.lastPage) ) {
1001                        pagination += '<li class="uk-disabled nolink"><span>...</span></li>';
1002                        pagination += '    <li class=""><a class="bridge-pagination-link" data-page="' + response.lastPage + '" href="' + currentURL + '?brpa=' + response.lastPage + urlParams + '">' + response.lastPage + '</a></li>';
1003                    }
1004
1005                    if ( parseInt(response.lastPage) > 1 ) {
1006                        pagination += '<li class="">';
1007                        pagination += '<a class="bridge-pagination-link bridge-next" id="bridge_next_' + uniqueID + '" data-page="2" href="' + currentURL + ((currentURL.indexOf('?') > -1)?'&':'?') +  'brpa=2' +  urlParams + '"><span uk-pagination-next></span>&nbsp;</a>';
1008                        pagination += '<a class="bridge-pagination-link bridge-next-ajax" id="bridge_next_ajax_' + uniqueID + '" data-page="2" href="' + self.options.bridgeAjaxListUrl + ((self.options.bridgeAjaxListUrl.indexOf('?') > -1)?'&':'?') + 'tt=1&action=brListeInfinite&id=' + self.options.webListId + attributesUrlParams + '&brpa=2' +  urlParams + '" style="display:none;"><span uk-pagination-next></span>&nbsp;</a>';
1009                        pagination += '</li>';
1010                    } else {
1011                        pagination += '<li class="uk-disabled">';
1012                        pagination += '<a class="bridge-pagination-link bridge-next" id="bridge_next_' + uniqueID + '" data-page="2" href="#nogo"><span uk-pagination-next></span>&nbsp;</a>';
1013                        // pagination += '<a class="bridge-pagination-link bridge-next-ajax" id="bridge_next_ajax_' + uniqueID + '" data-page="2" href="#nogo" style="display:none;"><span uk-pagination-next></span>&nbsp;</a>';
1014                        pagination += '</li>';
1015                    }
1016
1017                    jQuery('#bridge-pagination-container-' + uniqueID).html('');
1018                    jQuery('#bridge-pagination-container-' + uniqueID).append(jQuery(pagination));
1019
1020                    // Patch 03/06/22 : On active l'infinite scroll uniquement s'il y a plus d'une page de résultats et qu'on a pas fini
1021                    if(end > 1) {
1022                        if (window['bridgeActivateInfiniteScroll_' + uniqueID] != undefined) {
1023                            window['bridgeActivateInfiniteScroll_' + uniqueID](response.total);
1024                        }
1025                    } else {
1026                        // En mode infinite scroll, comme il est désactivé quand il n'y a pas plus d'une page on doit masquer la pagination
1027                        if (window['bridgeActivateInfiniteScroll_' + uniqueID] != undefined) {
1028                            jQuery('.bridge-liste[data-moteur-id=' + self.id + ']').find('.bridge-pagination-container').hide();
1029                        }
1030                    }
1031                    /*
1032                                        // affichage des options du filtre citycombodyn, s'il est présent sur la liste
1033                                        if (context.datalist && response.cityComboDynList && response.cityComboDynList !== '0') {
1034                                            context.displayCityComboDynList(response.cityComboDynList, context.datalist);
1035                                        } else if (context.datalist && response.cityComboDynList && response.cityComboDynList === '0') {
1036                                            // s'il y en a un dans la liste mais qu'on ne reçoit rien du contrôleur, on réutilise le précédent (cas d'un tri sans modif du moteur)
1037                                            context.displayCityComboDynList(context.cityComboDynList, context.datalist);
1038                                        }
1039                    */
1040                } else if ((!response.total && (response.message === 'Une erreur est survenue')) ) { // || response.total === 0
1041
1042                    jQuery('*[data-moteur-id=' + self.id + ']').find(".listeSITCount").html(response.total);
1043                    jQuery('.bridge-liste[data-moteur-id=' + self.id + ']').find(".listeSIT").html('<div>' + response.message + '</div>');
1044
1045                    /*if (context.datalist) {
1046                        context.displayCityComboDynList('', context.datalist);
1047                    }*/
1048
1049                } else {
1050                    jQuery('.bridge-liste[data-moteur-id=' + self.id + ']').find(".listeSIT").html('<div>Une erreur est survenue.</div>');
1051
1052                    /*if (context.datalist) {
1053                        context.displayCityComboDynList('', context.datalist);
1054                    }*/
1055                    console.error('Erreur : ', response);
1056                }
1057
1058                // on réinitialise le booléen
1059                context.filterHasChanged = false;
1060            },
1061            error: function(response) {
1062                jQuery('.bridge-loader').fadeOut({ duration: 500 });
1063                jQuery('.bridge-liste[data-moteur-id=' + self.id + ']').find(".listeSIT").html('<div>Une erreur est survenue.</div>');
1064                console.error('data error', response);
1065            }
1066        }).done(function( msg ) {
1067            jQuery('.bridge-loader').fadeOut({ duration: 500 });
1068            // alert( "Data Saved: " + msg );
1069        });
1070
1071    }
1072
1073}

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.