PageSourceSearch

https://www.domaliance.fr/wp-content/plugins/demande-devis/script/script.js?ver=1.5

js domaliance.fr collected 2026-10-04 13:24:34 UTC 73,033 bytes, 2,035 lines download raw bytes

1var $ = jQuery.noConflict();
2
3let currentStep = 0;
4
5let nbStepsLastSection = 0;
6
7let url = window.location;
8const beforeUnloadHandler = (event) => {
9    // Recommended
10    event.preventDefault();
11
12    // Included for legacy support, e.g. Chrome/Edge < 119
13    event.returnValue = true;
14};
15const nameInput = document.querySelector("input");
16
17let horizontalSlider = null;
18let progressBar = null;
19let inputAddressLoaderWrapper = null;
20
21$(document).ready(function () {
22    inputAddressLoaderWrapper = document.querySelector(
23        ".devis-inputAddress-loader-wrapper"
24    );
25
26    let forbidEnter = document.querySelector("#inputAddress");
27    if (forbidEnter) {
28        forbidEnter.addEventListener("keypress", function (e) {
29            if (e.key === "Enter") {
30                e.preventDefault();
31            }
32        });
33    }
34
35    if(window.location.href.includes("demande-devis") || window.location.href.includes("/lp/devis-aide-a-domicile/") || window.location.href.includes("/devis-mandataire/")){
36        villeIntervention();
37    }
38
39    //Récupérer les paramètres GET dans l'URL
40    var getUrlParameter = function getUrlParameter(sParam) {
41        var sPageURL = decodeURIComponent(window.location.search.substring(1)),
42            sURLVariables = sPageURL.split("&"),
43            sParameterName,
44            i;
45        for (i = 0; i < sURLVariables.length; i++) {
46            sParameterName = sURLVariables[i].split("=");
47            if (sParameterName[0] === sParam) {
48                return sParameterName[1] === undefined
49                    ? true
50                    : sParameterName[1].replace(/\+/g, " ");
51            }
52        }
53    };
54    let utm_campaign = getUrlParameter("utm_campaign");
55    switch (utm_campaign) {
56        default:
57            $("#native_taboola").hide();
58            $("#ads_menage").hide();
59            break;
60        case "native_SC":
61            $("#native_taboola").show();
62            $("#ads_menage").hide();
63            break;
64        case "ads_menage":
65            $("#native_taboola").hide();
66            $("#ads_menage").show();
67            break;
68    }
69    if (sessionStorage.getItem("utm_source") != "undefined") {
70        $('input[name="utm_source"]').val(sessionStorage.getItem("utm_source"));
71    }
72    if (sessionStorage.getItem("utm_medium") != "undefined") {
73        $('input[name="utm_medium"]').val(sessionStorage.getItem("utm_medium"));
74    }
75    if (sessionStorage.getItem("utm_campaign") != "undefined") {
76        $('input[name="utm_campaign"]').val(sessionStorage.getItem("utm_campaign"));
77    }
78
79    switch (true) {
80        //DDD
81        case url.pathname.includes("/demander-votre-devis/"):
82        case url.pathname.includes("/demande-de-devis/"):
83        case url.pathname.includes("/demande-devis/"):
84        case url.pathname.includes("/devis-offre-speciale/"):
85            nameInput.addEventListener("input", (event) => {
86                if (event.target.value !== "") {
87                    //beforeunload est l'évènement qui se lance avant le changement d'url
88                    window.addEventListener("beforeunload", beforeUnloadHandler);
89                } else {
90                    window.removeEventListener("beforeunload", beforeUnloadHandler);
91                }
92            });
93            break;
94    }
95
96    /* DEVIS HORIZONTAL */
97    if (utm_campaign === "horizontal") {
98        const progressBarV1Container = document.querySelector(
99            ".progressbar-container"
100        );
101        const progressBarV2Container = document.querySelector(
102            "#progressContainerV2"
103        );
104        const elem__devisHorizontalWrapper = document.querySelector(
105            ".devis_horizontal-wrapper"
106        );
107        if (elem__devisHorizontalWrapper) {
108            horizontalSlider = new HorizontalSlider(
109                elem__devisHorizontalWrapper,
110                document.querySelector(".devis_horizontal-container"),
111                document.querySelectorAll(".devis_horizontal-items"),
112                document.querySelector(".devis_horizontal-previous-step"),
113                document.querySelector(".devis_horizontal-loader-wrapper")
114            );
115        }
116        if (progressBarV2Container) {
117            const stepsWithText = ["Localisation", "Prestation", "Contact"];
118            progressBar = new ProgressBarV2(
119                "progressContainerV2",
120                [1, 2, 3],
121                stepsWithText
122            );
123        }
124        if (progressBarV1Container) {
125            progressBarV1Container.classList.add("hide");
126        }
127    }
128    /* END DEVIS HORIZONTAL */
129
130    // Enregistrez l'URL actuelle lors du chargement de la page
131    var currentUrl = window.location.href;
132    // Écoutez l'événement popstate
133    $(window).on("popstate", function () {
134        // Comparez l'URL actuelle avec l'URL spécifique que vous ciblez
135        if (window.location.href === currentUrl) {
136            // L'utilisateur a cliqué sur le bouton "Précédent" sur l'URL spécifique
137            alert('Clic sur le bouton "Précédent" détecté sur l\'URL spécifique.');
138        }
139    });
140
141    // recherche des communes avec le cp
142
143    $("#inputAddress").on("input", function () {
144        // Toute frappe invalide la commune retenue jusque-là. Les data-* ne doivent être
145        // renseignés que par une sélection explicite dans la liste (handler .commune) ou
146        // par la pré-sélection depuis une fiche agence : sans ce reset, modifier le texte
147        // sans re-sélectionner soumet l'ancienne ville, car sendDevis() lit les data-* et
148        // non la valeur affichée. Aucun code n'écrit ce champ via un événement input
149        // (tous passent par .val()/.attr()), le reset ne peut donc pas se déclencher à tort.
150        $(this).attr("data-ville", "");
151        $(this).attr("data-code_postal", "");
152        $(this).attr("data-code_INSEE", "");
153
154        var maxChars = 4;
155
156        if ($(this).val().length >= maxChars) {
157            searchCpDemandeDevis(
158                $(this)
159                    .val()
160                    .normalize("NFD")
161                    .replace(/[\u0300-\u036f]/g, "")
162            );
163        }
164    });
165
166    //Compteur heures
167
168    $(".minus").click(function () {
169        var $input = $(this).parent().find("input");
170
171        var count = parseInt($input.val()) - 1;
172
173        count = count < 2 ? 2 : count;
174
175        $input.val(count + "h par semaine");
176
177        $input.change();
178
179        return false;
180    });
181
182    $(".plus").click(function () {
183        var $input = $(this).parent().find("input");
184
185        var count = parseInt($input.val()) + 1;
186
187        count = count > 10 ? 10 : count;
188
189        $input.val(count + "h par semaine");
190
191        $input.change();
192
193        return false;
194    });
195
196    let stepChoicesInput = [
197        "service",
198        "frequence_aide",
199        "logement",
200        "nb_pieces",
201        "surface",
202        "heures",
203        "aide",
204        "besoin",
205        "enfant",
206        "frequence",
207        "activites",
208        "missions",
209        "materiel",
210        "pour-qui",
211        "service_plus",
212        "rdv",
213        "dechetterie",
214    ];
215
216    //Fonctionnement des etapes
217
218    $('input[type="radio"]').on("change", function () {
219    // Le formulaire horizontal "devis-aidant" gère sa propre navigation.
220    if (window.isAidantForm) return;
221        let inputClicked = this;
222        if ($(this).hasClass("form-court-avec-etape")) {
223            var section = "end-form";
224            if (utm_campaign === "horizontal" && horizontalSlider) {
225                horizontalSlider.handleHorizontalSlide("right");
226            }
227        } else {
228            var section = $(this).val();
229        }
230
231        if (progressBar) {
232            progressBar.nextStep();
233        }
234
235        let nextStep = currentStep + 1;
236
237        for (const eachInput of stepChoicesInput) {
238            if (section == "Moins de 3 ans") {
239                $('label[for="aide-devoirs"]').hide();
240            } else if (section == "Plus de 3 ans") {
241                $('label[for="aide-devoirs"]').show();
242            }
243
244            if (inputClicked.name == eachInput) {
245                if (
246                    $(this)
247                        .parents(".form-etape-step" + currentStep)
248                        .siblings(".form-etape-step" + currentStep)
249                        .children(".btn-container").length == 0
250                ) {
251                    let sectionForAddclass = $(this)
252                        .attr("id")
253                        .replace(/\W+/g, "-")
254                        .toLowerCase();
255
256                    $(".frise-devis")
257                        .find(".frise-devis-step" + currentStep)
258                        .addClass(sectionForAddclass);
259                }
260
261                if (eachInput == "service") {
262                    if ($(this).parent().hasClass("open-modal")) {
263                        $(".alert-modal").modal("show");
264                    } else {
265                        $(inputClicked).closest(".form-etape-1").addClass("disable");
266
267                        $("section#" + section).addClass("intoThisServ");
268
269                        if (section != "menage-repassage") {
270                            $(".progressbar-container")
271                                .removeClass("percentage-25")
272                                .addClass("percentage-50");
273                        }
274
275                        $(".intoThisServ .form-etape-step2").show();
276                        $(".intoThisServ").show();
277
278                        $('label[for="' + section + '-plus"]').hide();
279
280                        $("html,body").animate({
281                            scrollTop: $("section#" + section).offset().top - 100,
282                        });
283
284                        currentStep++;
285
286                        $(inputClicked).parent().addClass("active-radio");
287                    }
288                } else if (
289                    $(".intoThisServ").find(".form-etape-step" + nextStep).length > 0
290                ) {
291                    $(".form-etape-step" + currentStep).addClass("disable");
292
293                    if ($(".intoThisServ").is("#menage-repassage") && currentStep == 2) {
294                        $(".progressbar-container")
295                            .removeClass("percentage-25")
296                            .addClass("percentage-50");
297                    }
298
299                    currentStep++;
300
301                    $(".intoThisServ .form-etape-step" + currentStep).show();
302
303                    $("html,body").animate({
304                        scrollTop:
305                            $(".intoThisServ .form-etape-step" + currentStep).offset().top -
306                            100,
307                    });
308
309                    $(inputClicked).parent().addClass("active-radio");
310                } else {
311                    $(".form-etape-step" + currentStep).addClass("disable");
312
313                    currentStep++;
314
315                    $("#end-form").slideDown();
316
317                    $("html,body").animate({
318                        scrollTop: $("#end-form").offset().top - 100,
319                    });
320
321                    nbStepsLastSection = currentStep;
322
323                    currentStep = 21;
324
325                    $(".form-etape-step" + currentStep).show();
326
327                    $(inputClicked).parent().addClass("active-radio");
328
329                    $(".progressbar-container")
330                        .removeClass("percentage-50")
331                        .addClass("percentage-75");
332                }
333            }
334        }
335    });
336
337    $('input[type="checkbox"]').on("change", function () {
338    if (window.isAidantForm) return;
339        let inputClicked = this;
340
341        for (const eachInput of stepChoicesInput) {
342            if (inputClicked.name == eachInput) {
343                $(inputClicked).parent().toggleClass("active-radio");
344
345                if (
346                    $(inputClicked)
347                        .parent()
348                        .siblings()
349                        .addBack()
350                        .hasClass("active-radio") &&
351                    !$(inputClicked).parents(".form-group").hasClass("custom-btn-active")
352                ) {
353                    $(inputClicked).parents(".form-group").addClass("custom-btn-active");
354                } else if (
355                    !$(inputClicked)
356                        .parent()
357                        .siblings()
358                        .addBack()
359                        .hasClass("active-radio") &&
360                    $(inputClicked).parents(".form-group").hasClass("custom-btn-active")
361                ) {
362                    $(inputClicked)
363                        .parents(".form-group")
364                        .removeClass("custom-btn-active");
365                }
366            }
367        }
368    });
369
370    $(".no-btn-plus").on("click", function (e) {
371        e.preventDefault();
372
373        $(".form-etape-step" + currentStep).addClass("disable");
374
375        $(".form-etape-step" + currentStep + " .input-radio input").prop(
376            "checked",
377            false
378        );
379
380        $(".form-etape-step" + currentStep + " .input-radio input")
381            .parent()
382            .removeClass("active-radio");
383
384        $(".form-etape-step" + currentStep).removeClass("custom-btn-active");
385
386        $(".progressbar-container")
387            .removeClass("percentage-75")
388            .addClass("percentage-100");
389
390        currentStep++;
391
392        $(".form-etape-step" + currentStep).show();
393
394        $("html,body").animate({
395            scrollTop: $(".form-etape-step" + currentStep).offset().top - 100,
396        });
397    });
398
399    $(".return-btn").on("click", function (e) {
400        e.preventDefault();
401
402        $("#end-form").slideDown();
403
404        $(".progressbar-container")
405            .removeClass("percentage-50")
406            .addClass("percentage-75");
407
408        $(".form-etape-step" + currentStep).addClass("disable");
409
410        $('input[name="nb_heures"]').val("");
411
412        $('input[name="nb_heures"]').attr("placeholder", "2h par semaine");
413
414        currentStep++;
415
416        $("html,body").animate({
417            scrollTop: $("#end-form").offset().top - 100,
418        });
419
420        nbStepsLastSection = currentStep;
421
422        currentStep = 21;
423
424        $(".form-etape-step" + currentStep).show();
425    });
426
427    $(".custom-btn-checkbox-inside").on("click", function (e) {
428        e.preventDefault();
429
430        if ($(this).parents(".form-group").hasClass("custom-btn-active")) {
431            $(".form-etape-step" + currentStep).addClass("disable");
432
433            $(this)
434                .parents(".form-etape-step" + currentStep)
435                .removeClass("custom-btn-active");
436
437            let sectionForAddclass = [];
438
439            let inputCurrentStep = $(
440                ".form-etape-step" + currentStep + " .input-radio input:checked"
441            );
442
443            $(inputCurrentStep).each(function () {
444                sectionForAddclass.push(
445                    $(this).attr("id").replace(/\W+/g, "-").toLowerCase()
446                );
447            });
448
449            $(".frise-devis")
450                .find(".frise-devis-step" + currentStep)
451                .addClass(sectionForAddclass);
452
453            let nextStep = currentStep + 1;
454
455            if (currentStep < 21) {
456                if (
457                    $(".intoThisServ").find(".form-etape-step" + nextStep).length == 0
458                ) {
459                    $("#end-form").slideDown();
460
461                    currentStep++;
462
463                    $("html,body").animate({
464                        scrollTop: $("#end-form").offset().top - 100,
465                    });
466
467                    nbStepsLastSection = currentStep;
468
469                    currentStep = 21;
470
471                    $(".form-etape-step" + currentStep).show();
472
473                    $(".progressbar-container")
474                        .removeClass("percentage-50")
475                        .addClass("percentage-75");
476                } else {
477                    currentStep++;
478
479                    $(".intoThisServ .form-etape-step" + currentStep).show();
480
481                    $("html,body").animate({
482                        scrollTop:
483                            $(".intoThisServ .form-etape-step" + currentStep).offset().top -
484                            100,
485                    });
486                }
487            } else {
488                currentStep++;
489
490                $(".progressbar-container")
491                    .removeClass("percentage-75")
492                    .addClass("percentage-100");
493
494                $("#end-form .form-etape-step" + currentStep).show();
495
496                $("html,body").animate({
497                    scrollTop:
498                        $("#end-form .form-etape-step" + currentStep).offset().top - 100,
499                });
500            }
501        }
502    });
503
504    $(".validate-btn").on("click", function (e) {
505        e.preventDefault();
506    if (window.isAidantForm) return;
507
508        let nbChoixInputLastStep = $(this)
509            .parents(".form-group")
510            .siblings(".form-etape-step" + currentStep)
511            .find($('input[type="radio"]'));
512
513        let sectionForAddclass = [];
514
515        if (nbChoixInputLastStep.length > 0) {
516            if (nbChoixInputLastStep.is(":checked")) {
517                let inputCurrentStep = $(
518                    ".form-etape-step" + currentStep + " .input-radio input:checked"
519                );
520
521                $(inputCurrentStep).each(function () {
522                    sectionForAddclass.push(
523                        $(this).attr("id").replace(/\W+/g, "-").toLowerCase()
524                    );
525                });
526
527                $(".frise-devis")
528                    .find(".frise-devis-step" + currentStep)
529                    .addClass(sectionForAddclass);
530
531                $("#end-form").slideDown();
532
533                $(".form-etape-step" + currentStep).addClass("disable");
534
535                currentStep++;
536
537                $("html,body").animate({
538                    scrollTop: $("#end-form").offset().top - 100,
539                });
540
541                nbStepsLastSection = currentStep;
542
543                currentStep = 21;
544
545                $(".progressbar-container")
546                    .removeClass("percentage-50")
547                    .addClass("percentage-75");
548
549                $(".form-etape-step" + currentStep).show();
550            }
551        }
551 else if ($(this).hasClass("validmenagerepassage")) {
552            $("#end-form").slideDown();
553
554            $(".form-etape-step" + currentStep).addClass("disable");
555
556            currentStep++;
557
558            $("html,body").animate({
559                scrollTop: $("#end-form").offset().top - 100,
560            });
561
562            nbStepsLastSection = currentStep;
563
564            currentStep = 21;
565
566            $(".progressbar-container")
567                .removeClass("percentage-50")
568                .addClass("percentage-75");
569
570            $(".form-etape-step" + currentStep).show();
571        }
572    });
573
574    $(".devis-backBtn").on("click", function (e) {
575    if (window.isAidantForm) return;
576        e.preventDefault();
577
578        if (utm_campaign === "horizontal" && horizontalSlider) {
579            horizontalSlider.handleHorizontalSlide("left");
580        }
581        if (progressBar) {
582            progressBar.prevStep();
583        }
584
585        let prevStep = currentStep - 1;
586
587        if ($(".frise-devis .frise-devis-step" + prevStep).length > 0) {
588            let inputCurrentStep = $(
589                ".form-etape-step" + prevStep + " .input-radio input:checked"
590            );
591
592            let inputChecked = [];
593
594            $(inputCurrentStep).each(function () {
595                inputChecked.push(
596                    $(this).attr("id").replace(/\W+/g, "-").toLowerCase()
597                );
598            });
599
600            $(".frise-devis .frise-devis-step" + prevStep).removeClass(inputChecked);
601        }
602
603        if (currentStep > 2) {
604            if (currentStep == 21) {
605                $("#end-form").slideUp();
606
607                currentStep = nbStepsLastSection;
608
609                let inputCurrentStep = $(
610                    ".form-etape-step" + currentStep + " .input-radio input:checked"
611                );
612
613                let inputChecked = [];
614
615                $(inputCurrentStep).each(function () {
616                    inputChecked.push($(this).val().replace(/\W+/g, "-").toLowerCase());
617                });
618
619                $(".frise-devis .frise-devis-step" + currentStep).removeClass(
620                    inputChecked
621                );
622
623                $(".progressbar-container")
624                    .removeClass("percentage-75")
625                    .addClass("percentage-50");
626            } else if (currentStep < 21) {
627                $(".intoThisServ .form-etape-step" + currentStep).hide();
628
629                if ($(".intoThisServ").is("#menage-repassage") && currentStep == 3) {
630                    $(".progressbar-container")
631                        .removeClass("percentage-50")
632                        .addClass("percentage-25");
633                }
634            } else {
635                $("#end-form .form-etape-step" + currentStep).hide();
636
637                $(".progressbar-container")
638                    .removeClass("percentage-100")
639                    .addClass("percentage-75");
640            }
641
642            $(".form-etape-step" + currentStep + " .input-radio input").prop(
643                "checked",
644                false
645            );
646
647            $(".form-etape-step" + currentStep + " .input-radio input")
648                .parent()
649                .removeClass("active-radio");
650
651            $(".form-etape-step" + currentStep).removeClass("custom-btn-active");
652
653            currentStep--;
654
655            $(".form-etape-step" + currentStep + " .input-radio input").prop(
656                "checked",
657                false
658            );
659
660            $(".form-etape-step" + currentStep + " .input-radio input")
661                .parent()
662                .removeClass("active-radio");
663
664            $(".form-etape-step" + currentStep).removeClass("disable");
665
666            $("html,body").animate({
667                scrollTop:
668                    $(".intoThisServ .form-etape-step" + currentStep).offset().top -
669                    100,
670            });
671        } else if (currentStep == 2) {
672            $(".intoThisServ .form-etape-step2").hide();
673
674            $("#end-form .input-radio").show();
675
676            if (!$(".intoThisServ").is("#menage-repassage")) {
677                $(".progressbar-container")
678                    .removeClass("percentage-50")
679                    .addClass("percentage-25");
680            }
681
682            $("section").removeClass("intoThisServ");
683
684            $(".form-etape-1").removeClass("disable");
685
686            $(".form-etape-1 .input-radio input").prop("checked", false);
687
688            $(".form-etape-1 .input-radio input")
689                .parent()
690                .removeClass("active-radio");
691
692            if (utm_campaign === "horizontal" && horizontalSlider) {
693                $(".devis_horizontal-items.step-2 .input-radio input").prop(
694                    "checked",
695                    false
696                );
697
698                $(".devis_horizontal-items.step-2 input")
699                    .parent()
700                    .removeClass("active-radio");
701            }
702
703            currentStep--;
704
705            $("html,body").animate({
706                scrollTop: $(".form-etape-1").offset().top - 100,
707            });
708        } else if (currentStep == 1) {
709            $(".right-content-img").show();
710
711            $(".input-search-container").removeClass("disable");
712
713            $(".frise-devis-step1").removeClass("jardinage");
714
715            $(".agence-container").hide();
716
717            $(".menutelmobileddd").hide();
718
719            $(".agence-container .agence-name").text("");
720
721            $(".agence-container .agence-tel .number").text("");
722
723            if (utm_campaign === "horizontal" && horizontalSlider) {
724                $(".devis_horizontal-items.step-2").find(".indispo").remove();
725                document
726                    .querySelectorAll(".devis_horizontal-items.step-2 .input-radio")
727                    .forEach((el) => {
728                        el.classList.remove("disable");
729                    });
730            } else {
731                $(".left-content .form-container").hide();
732            }
733
734            $(".form-container #id_agence").val("");
735
736            $("#inputAddress").val("");
737
738            $("#inputAddress").attr("data-code_postal", "");
739
740            $("#inputAddress").attr("data-ville", "");
741
742            $(".floating-right-section").removeClass("isFixed");
743
744            $(".form-etape-step1").find(".indispo").remove();
745
746            $(".form-etape-step21").find(".indispo").remove();
747
748            $(".progressbar-container").removeClass("percentage-25");
749
750            currentStep--;
751
752            $("html,body").animate({
753                scrollTop: $(".input-search-container").offset().top - 100,
754            });
755        }
756    });
757
758    const devisHeaderBtnExitPopup = document.querySelectorAll(
759        ".devis-btn-exit-popup"
760    );
761    if (devisHeaderBtnExitPopup) {
762        for (let i = 0; i < devisHeaderBtnExitPopup.length; i++) {
763            devisHeaderBtnExitPopup[i].addEventListener("click", function (e) {
764                e.preventDefault();
765                document.querySelector(".popup-exitddd").classList.remove("popup-none");
766            });
767        }
768    }
769
770    const devisHeaderExitPopupStayBtn = document.querySelector(".btnpopup-stay");
771    if (devisHeaderExitPopupStayBtn) {
772        devisHeaderExitPopupStayBtn.addEventListener("click", function (e) {
773            e.preventDefault();
774            document.querySelector(".popup-exitddd").classList.add("popup-none");
775        });
776    }
777
778    $(".menutelmobileddd").on("click", function (e) {
779        e.preventDefault();
780
781        $(".isFixed").toggle();
782    });
783
784    const addressInput = document.querySelector("input#email");
785    const formContainer = document.querySelector(".form-devis");
786    if (addressInput) {
787        addressInput.addEventListener("blur", function () {
788            if (this.value.includes("mrsuricate.com") || this.value.includes("556surisaas.com")) {
789                // Le widget n'est pas rendu en local/dev (cf. dd_should_render_captcha),
790                // sans ce test .remove() lèverait un TypeError et le hidden ne serait
791                // jamais ajouté.
792                const captcha = document.querySelector(".g-recaptcha");
793                if (captcha) {
794                    captcha.remove();
795                }
796                // Créer l'élément input
797                let input = document.createElement("input");
798
799                // Définir les attributs
800                input.type = "hidden";
801                input.name = "g-recaptcha-response";
802                input.value = "robot-suricate";
803
804                // Ajouter l'input au formulaire ou au body
805                formContainer.appendChild(input);
806            }
807        });
808    }
809
810    //Select option comment nous avez-vous connu
811    const elem__selectSource = document.getElementById('source');
812    const elem__inputTextSourceOther = document.getElementById('source-other');
813
814    elem__selectSource && elem__inputTextSourceOther ? handleSelectSource() : null
815
816    function handleSelectSource() {
817        elem__selectSource.addEventListener('change', function () {
818            const valeur = this.value;
819
820            if (valeur === 'autre') {
821                elem__inputTextSourceOther.classList.remove('hide')
822                setTimeout(() => {
823                    elem__selectSource.classList.add('show')
824                    elem__inputTextSourceOther.classList.add('show')
825                }, 100)
826            } else {
827                elem__inputTextSourceOther.classList.remove('show')
828                elem__selectSource.classList.remove('show')
829                setTimeout(() => {
830                    elem__inputTextSourceOther.classList.add('hide')
831                    elem__inputTextSourceOther.value = "";
832                }, 100)
833            }
834        });
835    }
836
837    //LP DDD spécial mad. Code pour cacher tous les services sauf aide à domicile
838    function hideDesiredServices(servicesAttributesArray, cardRhHide =false) {
839        const elems__servicesCards = document.querySelectorAll(".input-radio.services")
840        if (elems__servicesCards) {
841            elems__servicesCards.forEach(el => {
842                const attr = el.getAttribute('for')
843                if (!servicesAttributesArray.includes(attr)) {
844                    el.classList.add("hide")
845                }
846            })
847        }
848
849        const elem__cardRh = document.querySelector('.input-radio.card-rh-ddd')
850        if (elem__cardRh) {
851            elem__cardRh.classList.toggle('hide', cardRhHide);
852        }
853    }
854
855    if (currentUrl.includes("/lp/devis-aide-a-domicile/")) {
856        hideDesiredServices(["aide-domicile"])
857    }
858
859    if(window.location.href.includes('demande-devis') || window.location.href.includes('/lp/devis-aide-a-domicile/') || window.location.href.includes('/devis-mandataire/')){
860        villeIntervention();
861    }
862});
863
864function searchCpDemandeDevis(commune) {
865    var ajaxurl = variables.ajax_url;
866
867    var data = {
868        action: "get_communes_demande_devis",
869
870        commune: commune,
871    };
872
873    $list = $(".city-result");
874
875    $list.css("background-image", "none");
876
877    $option = $("<li>").text("Chargement...").addClass("waiting");
878
879    $list.empty();
880
881    $list.append($option);
882
883    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
884
885    jQuery.post(ajaxurl, data, function (response) {
886        var communes = JSON.parse(response);
887
888        $list.empty();
889
890        for (var i = 0; i < communes.length; i++) {
891            var text =
892                '<span class="bolder">' +
893                communes[i]["code_postal"] +
894                "</span>, " +
895                communes[i]["ville"];
896
897            $list.append(
898                $("<li>")
899                    .html(text)
900                    .attr("data-code_postal", communes[i]["code_postal"])
901                    .attr("data-ville", communes[i]["ville"])
902                    .attr("data-code_INSEE", communes[i]["code_INSEE"])
903                    .addClass("commune")
904            );
905        }
906
907        if (utm_campaign === "horizontal" && horizontalSlider) {
908            horizontalSlider.handleDynamicWidthAndHeightItems(0, -150);
909        }
910
911        //if enter is pressed on a commune, it will be selected
912        waitForElem(".commune").then((elem) => {
913            document.addEventListener("keydown", function (e) {
914                if (e.key === "Enter") {
915                    elem.click();
916                }
917            });
918        });
919
920        $(".commune").on("click", function () {
921            var ville = $(this).attr("data-ville");
922
923            var cp = $(this).attr("data-code_postal");
924
925            var code_INSEE = $(this).attr("data-code_INSEE");
926
927            $("#inputAddress").val(ville);
928
929            $("#inputAddress").attr("data-code_postal", cp);
930
931            $("#inputAddress").attr("data-ville", ville);
932
933            $("#inputAddress").attr("data-code_INSEE", code_INSEE);
934
935            $list.children().remove();
936
937            agenceSearch(ville, cp, code_INSEE);
938            if ($(".city-result").hasClass("short-form-city") == false) {
939                $(".progressbar-container").addClass("percentage-25");
940            }
941            if (inputAddressLoaderWrapper) {
942                inputAddressLoaderWrapper.classList.remove("hide");
943                $(".input-search-container").addClass("disable");
944            }
945        });
946
947        // Réafficher le menu déroulant au click de l'input
948
949        $(document).on("click", function (event) {
950            if (event.target.name == "addressInput") {
951                $list.show();
952            } else {
953                $list.hide();
954            }
955        });
956
957        if (communes.length == 0) {
958            $option = $("<li>")
959                .text(
960                    "Désolé, nous n'avons trouvé aucune commune. Vérifiez le code postal renseigné."
961                )
962                .addClass("error");
963
964            $list.append($option);
965        } else if (communes.length == 1) {
966            $list.children().css("cursor", "pointer");
967        } else {
968            $list.children().css("cursor", "pointer");
969
970            $list.css("background-image", "");
971        }
972    });
973}
974
975//Recherche de l'agence
976
977// Helper centralisé : met à jour le label "Aide à domicile" avec ou sans la mention (mandataire)
978// Utilise textContent sur le span pour ne PAS détruire le span (ce que fait jQuery .text() sur le parent)
979function updateAideDomicileMandataire(hasMandataire) {
980    var aideDomicileText = document.getElementById('aide-domicile-text');
981    if (!aideDomicileText) return;
982    aideDomicileText.textContent = hasMandataire ? 'Aide à domicile (mandataire)' : 'Aide à domicile';
983
984    if (hasMandataire) {
985        // Le service mandataire est dispo dans au moins une agence : retirer le badge "Indisponible"
986        $('label[for="aide-domicile"]').removeClass("disable");
987        $('label[for="aide-domicile"]').find(".indispo").remove();
988    }
989}
990
991function agenceSearch(ville, cp, code_INSEE) {
992    var ajaxurl = variables.ajax_url;
993
994    var data = {
995        action: "getAgenceNearCpDemandeDevis",
996
997        ville: ville,
998
999        cp: cp,
1000
1001        code_INSEE: code_INSEE,
1002    };
1003
1004    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
1005
1006    jQuery.post(ajaxurl, data, function (response) {
1007        var agence = response.data;
1008
1009        if (response.success == false) {
1010            // $('label[for="jardinage"]').addClass("open-modal");
1011            $(".devis-container .service-text").each(function (index) {
1012                $(this).parent().removeClass("disable");
1013                $(this).find(".indispo").remove();
1014            });
1015
1016            $(".alert-modal .form-title .ville").text(ville);
1017
1018            $(".alert-modal #ville").val(ville);
1019
1020            $(".alert-modal #code_postal").val(cp);
1021
1022            if($(".input-search-container").hasClass("altAgence") == false){
1023                $(".input-search-container").addClass("disable");
1024            }
1025        } else {
1026            if (agence["enseigne_devis"] == 1) {
1027                // $('label[for="jardinage"]').removeClass("open-modal");
1028
1029                if (agence[0]["tel_fixe"]) {
1030                    $(".agence-container").show();
1031                }
1032
1033                $(".agence-container .agence-name").text(agence[0]["nom"]);
1034
1035                if (agence[0]["tel_fixe"]) {
1036                    $(".agence-container .agence-tel").attr(
1037                        "href",
1038                        "tel:" + agence[0]["tel_fixe"]
1039                    ).show();
1040                    $(".agence-container .agence-tel .number").text(agence[0]["tel_fixe"]).show();
1041                } else {
1042                    $(".agence-container .agence-tel").hide();
1043                    $(".agence-container .agence-tel .number").hide();
1044                }
1045
1046                const agenceContainerEarlyBooking = document.querySelectorAll(".agence-container-early-booking");
1047
1048                if (agenceContainerEarlyBooking.length > 0) {
1049                    agenceContainerEarlyBooking.forEach(el => el.classList.remove("hide"));
1050                }
1051
1052                const bannerNewDDD = document.querySelector('.banner_new_ddd')
1053                bannerNewDDD ? bannerNewDDD.classList.add('hide') : null
1054
1055                //$('.form-etape-3 .enseigne-message').text('');
1056                if(agence[1]){
1057                    checkServiceEachAgences(agence);
1058                } else{
1059                    checkService(agence[0]["id_agence"]);
1060                }
1061
1062                // Vérifier si AU MOINS UNE agence a has_mandataire = 1 (mono ou multi-agences)
1063                var agencesArr = Object.values(agence).filter(function(a){ return a && a.id_agence; });
1064                var hasMandataireAgency = agencesArr.some(function(a){ return a.has_mandataire == 1; });
1065                updateAideDomicileMandataire(hasMandataireAgency);
1066
1067                if (window.matchMedia("(max-width:767px)").matches) {
1068                    $(".menutelmobileddd").show();
1069                }
1070            } else {
1071                //$('.form-etape-3 .enseigne-message').text(agence['message']);
1072                if (utm_campaign === "horizontal" && horizontalSlider) {
1073                    horizontalSlider.handleHorizontalSlide("right");
1074                }
1075                if (progressBar) {
1076                    progressBar.nextStep();
1077                }
1078                if (inputAddressLoaderWrapper) {
1079                    inputAddressLoaderWrapper.classList.add("hide");
1080                }
1081            }
1082            if ($(".city-result").hasClass("short-form-city") == false) {
1083                $(".right-content-img").hide();
1084
1085                if($(".input-search-container").hasClass("altAgence") == false){
1086                    $(".input-search-container").addClass("disable");
1087                }
1088                $(".floating-right-section").addClass("isFixed");
1089            }
1090            sessionStorage.setItem("agence", JSON.stringify(agence[0]));
1091
1092            // Bloc "être rappelé par un conseiller" : uniquement si l'agence a un call center (Ozone : call_center = 1)
1093            toggleRappelCallCenter(JSON.parse(sessionStorage.getItem("agence")).call_center);
1094
1095            if (agence[1]) {
1096                sessionStorage.setItem("multiple_agency", 1);
1097            } else {
1098                sessionStorage.removeItem("multiple_agency");
1099            }
1100
1101            $(".form-container #id_agence").val(agence[0]["id_agence"]);
1102        }
1103
1104        if (utm_campaign !== "horizontal" && !horizontalSlider) {
1105            $(".form-container").slideDown();
1106        }
1107
1108        if($(".input-search-container").hasClass("altAgence") == false){
1109            currentStep++;
1110        }
1111
1112        autoService([
1113            { urls: ["offre-menage", "bon-plan-menage"], labelFor: "menage-repassage" },
1114            //{ urls: ["devis-aide-a-domicile"], labelFor: "aide-domicile" }
1115        ], currentStep);
1116    });
1117}
1118
1119//Envoi du devis
1120
1121function sendDevis() {
1122    var ajaxurl = variables.ajax_url;
1123    window.removeEventListener("beforeunload", beforeUnloadHandler);
1124
1125      const submitBtn = document.querySelector(".submit-devis");
1126      if (submitBtn && typeof btnLoader === "function") {
1127        btnLoader(submitBtn, "start", "Envoi en cours...");
1128      }
1129
1130    const devis = {};
1131
1132    devis["civilite"] = "";
1133
1134    devis["besoin"] = "";
1135
1136    devis["code_postal"] = "";
1137
1138    devis["ville"] = "";
1139
1140    devis["missions"] = "";
1141
1142    devis["activites"] = "";
1143
1144    devis["rgpd"] = "";
1145
1146    devis["service_plus"] = "";
1147
1148    // Initialisé à vide : le select peut ne jamais être affiché (agence sans call center)
1149    devis["rappel_creneau"] = "";
1150
1151    var i = 0;
1152
1153    var name = "";
1154
1155    $(
1156        ".devis-container input, .devis-container textarea, .devis-container select"
1157    ).each(function (index) {
1158        var input = $(this);
1159
1160        if (
1161            (input.attr("type") == "radio" && input.is(":checked")) ||
1162            input.attr("type") == "text" ||
1163            input.attr("type") == "email" ||
1164            input.attr("type") == "tel" ||
1165            input.attr("type") == "hidden" ||
1166            input.attr("type") == undefined
1167        ) {
1168            devis[input.attr("name")] = "";
1169
1170            // jQuery .val() renvoie null - et non "" - sur un <select> dont la seule
1171            // option selected est disabled (nos placeholders "Choisissez une option").
1172            // Sans ce repli, la concaténation produit la chaîne "null", stockée telle quelle.
1173            devis[input.attr("name")] += input.val() ?? "";
1174        }
1175
1176        if (input.attr("type") == "search") {
1177            devis["code_postal"] += input.attr("data-code_postal");
1178
1179            devis["ville"] += input.attr("data-ville");
1180        }
1181
1182        if (input.attr("type") == "checkbox" && input.is(":checked")) {
1183            if (i == 0 || name != input.attr("name")) {
1184                devis[input.attr("name")] += input.val();
1185            } else {
1186                devis[input.attr("name")] += ", " + input.val();
1187            }
1188
1189            i = input.attr("data-index");
1190
1191            name = input.attr("name");
1192        }
1193    });
1194    var data = {
1195        action: "sendDevis",
1196        devis: devis,
1197    };
1198
1199    var getUrlParameter = function getUrlParameter(sParam) {
1200        var sPageURL = decodeURIComponent(window.location.search.substring(1)),
1201            sURLVariables = sPageURL.split("&"),
1202            sParameterName,
1203            i;
1204        for (i = 0; i < sURLVariables.length; i++) {
1205            sParameterName = sURLVariables[i].split("=");
1206            if (sParameterName[0] === sParam) {
1207                return sParameterName[1] === undefined
1208                    ? true
1209                    : sParameterName[1].replace(/\+/g, " ");
1210            }
1211        }
1212    };
1213
1214    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
1215
1216    jQuery.post(ajaxurl, data, function (response) {
1217        var devis_data = response.data;
1218        if (
1219            devis_data["data-ville"] == undefined &&
1220            devis_data["data-code_postal"] == undefined
1221        ) {
1222            $(".short-input-service").append(
1223                "<p class='error'>" + devis_data["message"] + "</p>"
1224            );
1225        }
1226
1227        if (response.success == true) {
1228            var phoneRaw = devis["telephone"] || "";
1229            var phoneE164 = phoneRaw.replace(/^0/, "+33");
1230            window.dataLayer = window.dataLayer || [];
1231            let dataLayerEvent = "";
1232            switch (window.location.pathname) {
1233            case "/lp/devis-aide-personne/":
1234                dataLayerEvent = "quote-form-senior-success";
1235                break;
1236            case "/lp/devis-aidant/":
1237                dataLayerEvent = "quote-form-carer-success";
1238                break;
1239            }
1240            if (dataLayerEvent) {
1241                window.dataLayer.push({
1242                    event: dataLayerEvent,
1243                    step_number: currentStep,
1244                    user_status: undefined,
1245                    user_email: devis["email"],
1246                    user_phone: phoneE164,
1247                    user_firstname: devis["prenom"],
1248                    user_lastname: devis["nom"],
1249                    user_address: undefined,
1250                    user_city: devis["ville"],
1251                    user_zipcode: devis["code_postal"],
1252                    user_country: "France",
1253                });
1254            }
1255            $("#inputAddress").val("");
1256            $(".form-devis").trigger("reset");
1257
1258            sessionStorage.setItem("devis", JSON.stringify(devis_data));
1259            sessionStorage.setItem("frise", $(".frise-devis").parent().html());
1260
1261      if (
1262        window.location.pathname == "/demande-de-devis/" ||
1263        window.location.pathname == "/demande-devis/"
1264      ) {
1265                if (getUrlParameter("utm_campaign")) {
1266                    window.location =
1267                        window.location.origin +
1268                        "/merci-demande-de-devis/?IDDEVISAZAE=" +
1269                        devis_data["ID"] +
1270                        "&utm_campaign=" +
1271                        getUrlParameter("utm_campaign");
1272                } else {
1273                    window.location =
1274                        window.location.origin +
1275                        "/merci-demande-de-devis/?IDDEVISAZAE=" +
1276                        devis_data["ID"];
1277                }
1278      } else if (
1279        window.location.pathname == "/lp/devis-aidant/" ||
1280        window.location.pathname == "/lp/devis-aidant/"
1281      ) {
1282        if (getUrlParameter("utm_campaign")) {
1283          window.location =
1284            window.location.origin +
1285            "/merci-devis-aidant/?IDDEVISAZAE=" +
1286            devis_data["ID"] +
1287            "&utm_campaign=" +
1288            getUrlParameter("utm_campaign");
1289        } else {
1290          window.location =
1291            window.location.origin +
1292            "/merci-devis-aidant/?IDDEVISAZAE=" +
1293            devis_data["ID"];
1294        }
1295      } else if (
1296        window.location.pathname == "/lp/devis-aide-personne/" ||
1297        window.location.pathname == "/lp/devis-aide-personne/"
1298      ) {
1299        if (getUrlParameter("utm_campaign")) {
1300          window.location =
1301            window.location.origin +
1302            "/merci-devis-aide-personne/?IDDEVISAZAE=" +
1303            devis_data["ID"] +
1304            "&utm_campaign=" +
1305            getUrlParameter("utm_campaign");
1306        } else {
1307          window.location =
1308            window.location.origin +
1309            "/merci-devis-aide-personne/?IDDEVISAZAE=" +
1310            devis_data["ID"];
1311        }
1312            } else if (window.location.pathname == "/devis-mandataire/") {
1313                if (getUrlParameter("utm_campaign")) {
1314                    window.location =
1315                        window.location.origin +
1316                        "/merci-devis-mandataire/?IDDEVISAZAE=" +
1317                        devis_data["ID"] +
1318                        "&utm_campaign=" +
1319                        getUrlParameter("utm_campaign");
1320                } else {
1321                    window.location =
1322                        window.location.origin +
1323                        "/merci-devis-mandataire/?IDDEVISAZAE=" +
1324                        devis_data["ID"];
1325                }
1326            } else if (window.location.href.includes("bon-plan-menage")) {
1327                if (getUrlParameter("utm_campaign")) {
1328                    window.location =
1329                        window.location.origin +
1330                        "/merci-devis-bon-plan-menage/?IDDEVISAZAE=" +
1331                        devis_data["ID"] +
1332                        "&utm_campaign=" +
1333                        getUrlParameter("utm_campaign");
1334                } else {
1335                    window.location =
1336                        window.location.origin +
1337                        "/merci-devis-bon-plan-menage/?IDDEVISAZAE=" +
1338                        devis_data["ID"];
1339                }
1340            } else {
1341                if (getUrlParameter("utm_campaign")) {
1342                    window.location =
1343                        window.location.origin +
1344                        "/merci-devis-offre-speciale/?IDDEVISAZAE=" +
1345                        devis_data["ID"] +
1346                        "&utm_campaign=" +
1347                        getUrlParameter("utm_campaign");
1348                } else {
1349                    window.location =
1350                        window.location.origin +
1351                        "/merci-devis-offre-speciale/?IDDEVISAZAE=" +
1352                        devis_data["ID"];
1353                }
1354            }
1355
1356            $(".error-devis").remove();
1357        } else {
1358            if (submitBtn && typeof btnLoader === "function") {
1359                btnLoader(submitBtn, "stop");
1360            }
1361            $(".next-step").after(
1362                '<p class="error-devis">' + devis_data["message-error"] + "</p>"
1363            );
1364            $(".error-devis").html(devis_data["message-captcha"]);
1365        }
1366    });
1367}
1368
1369// Enregistrement de l'adresse mail pour prévenir le client
1370
1371function saveAlert() {
1372    var ajaxurl = variables.ajax_url;
1373
1374    var ville = $(".alert-modal #ville").val();
1375
1376    var code_postal = $(".alert-modal #code_postal").val();
1377
1378    var mail = $(".alert-modal #emailAlert").val();
1379
1380    var data = {
1381        action: "insertAlert",
1382
1383        ville: ville,
1384
1385        code_postal: code_postal,
1386
1387        mail: mail,
1388    };
1389
1390    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
1391
1392    jQuery.post(ajaxurl, data, function (response) {
1393        if (response.success == false) {
1394            $(".alert-modal .form-container #message-container .error-message").text(
1395                response.data
1396            );
1397        } else {
1398            $(
1399                ".alert-modal .form-container #message-container .success-message"
1400            ).text(response.data);
1401
1402            $("#alertForm").hide();
1403
1404            setTimeout(function () {
1405                $(".alert-modal").modal("hide");
1406            }, 1000);
1407        }
1408    });
1409}
1410
1411// Retourne true si `value` est présent dans `services`. Cas particulier :
1412// "Aide à domicile" est considéré comme matchant "Aide à domicile (mandataire)"
1413// (et vice-versa), pour que le choix utilisateur ne soit pas marqué indispo.
1414function serviceMatchesAgency(value, services) {
1415    if (!Array.isArray(services)) return false;
1416    if (services.indexOf(value) !== -1) return true;
1417    if (value === 'Aide à domicile') {
1418        return services.some(s => typeof s === 'string' && s.indexOf('Aide à domicile') === 0);
1419    }
1420    if (typeof value === 'string' && value.indexOf('Aide à domicile') === 0) {
1421        return services.indexOf('Aide à domicile') !== -1;
1422    }
1423    return false;
1424}
1425
1426//Vérifier sur l'agence trouvée fais tous les services ou non 
1427function checkService(id_agence) {
1428    var ajaxurl = variables.ajax_url;
1429    var agenceSession = sessionStorage.getItem("agence");
1430    var mandataire = agenceSession
1431        ? JSON.parse(agenceSession).has_mandataire
1432        : null;
1433
1434    var data = {
1435        action: "checkService",
1436
1437        id_agence: id_agence,
1438    };
1439
1440    // Prévient si une agence avec un service indisponible avait été choisi puis changement d'agence : rendre les bons services cliquables
1441    $(".devis-container .service-text").each(function (index) {
1442        $(this).parent().removeClass("disable");
1443        $(this).find(".indispo").remove();
1444    })
1445
1446    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
1447
1448    jQuery.post(ajaxurl, data, function (response) {
1449        var services = jQuery.parseJSON(response);
1450
1451        $(".devis-container .service-text").each(function (index) {
1452            var value = $(this).text().trim();
1453
1454            if (!serviceMatchesAgency(value, services)) {
1455                $(this).append(
1456                    '<div class="indispo"><span>Indisponible dans cette agence</span></div>'
1457                );
1458
1459                $(this).parent().addClass("disable");
1460            }
1461        });
1462
1463        // Si l'agence est mandataire, on s'assure qu'aide-domicile reste actif
1464        if (mandataire == 1) {
1465            updateAideDomicileMandataire(true);
1466        }
1467
1468        if (utm_campaign === "horizontal" && horizontalSlider) {
1469            horizontalSlider.handleHorizontalSlide("right");
1470        }
1471        if (progressBar) {
1472            progressBar.nextStep();
1473        }
1474        if (inputAddressLoaderWrapper) {
1475            inputAddressLoaderWrapper.classList.add("hide");
1476        }
1477    });
1478}
1479
1480//Vérifier sur les agences trouvées si elles font tous les services ou non 
1481function checkServiceEachAgences(agences) {
1482    var ajaxurl = variables.ajax_url;
1483    let allServices = [];
1484    const promises = [];
1485
1486    // Prévient si une agence avec un service indisponible avait été choisi puis changement d'agence : rendre les bons services cliquables
1487    $(".devis-container .service-text").each(function (index) {
1488        $(this).parent().removeClass("disable");
1489        $(this).find(".indispo").remove();
1490    });
1491
1492    if (!Array.isArray(agences)) {
1493        agences = Object.values(agences).filter(a => a && a.id_agence);
1494    }
1495
1496    // Tableau de tous les services des agences (sans doublon)
1497    agences.forEach(agence => {
1498        const req = $.post(ajaxurl, {
1499            action: "checkService",
1500            id_agence: agence.id_agence
1501        }).done(response => {
1502            try {
1503                var services = $.parseJSON(response);
1504                services.forEach(service => {
1505                    if ($.inArray(service, allServices) === -1) {
1506                    allServices.push(service);
1507                    }
1508                });
1509            } catch (e) {
1510            console.error("Erreur parsing agence", agence.id_agence, e);
1511            }
1512        });
1513
1514      promises.push(req); // on stocke la promesse pour $.when plus tard
1515    });
1516
1517    // Quand toutes les requêtes sont terminées
1518    $.when.apply($, promises).done(function () {
1519        // Vérifier si au moins une des agences a has_mandataire = 1 et mettre à jour le texte "Aide à domicile"
1520        const hasMandataire = agences.some(agence => agence && agence.has_mandataire == 1);
1521        updateAideDomicileMandataire(hasMandataire);
1522
1523        $(".devis-container .service-text").each(function () {
1524            var value = $(this).text().trim();
1525            if (!serviceMatchesAgency(value, allServices)) {
1526                $(this).append('<div class="indispo"><span>Indisponible dans cette agence</span></div>');
1527                $(this).parent().addClass("disable");
1528            }
1529        });
1530
1531        if (utm_campaign === "horizontal" && horizontalSlider) {
1532            horizontalSlider.handleHorizontalSlide("right");
1533        }
1534        if (progressBar) {
1535            progressBar.nextStep();
1536        }
1537        if (inputAddressLoaderWrapper) {
1538            inputAddressLoaderWrapper.classList.add("hide");
1539        }
1540    });
1541}
1542
1543//Prendre en compte uniquement les chiffres dans l'input 
1544
1545function onlyNumberKey(evt) {
1546    // Only ASCII character in that range allowed
1547
1548    var ASCIICode = evt.which ? evt.which : evt.keyCode;
1549
1550    if (ASCIICode > 31 && (ASCIICode < 48 || ASCIICode > 57)) return false;
1551
1552    return true;
1553}
1554
1555function waitForElem(selector, parent = document) {
1556    return new Promise((resolve) => {
1557        if (parent) {
1558            const target = parent.querySelector(selector);
1559            if (target) {
1560                return resolve(target);
1561            }
1562            const observer = new MutationObserver((mutations) => {
1563                const target = parent.querySelector(selector);
1564                if (target) {
1565                    resolve(target);
1566                    observer.disconnect();
1567                }
1568            });
1569            observer.observe(parent, {
1570                childList: true,
1571                subtree: true,
1572            });
1573        }
1574    });
1575}
1576
1577/* DEVIS HORIZONTAL */
1578class HorizontalSlider {
1579    constructor(wrapper, container, items, previousStepBtn, loader) {
1580        this.wrapper = wrapper;
1581        this.container = container;
1582        this.items = Array.from(items);
1583        this.previousStepBtn = previousStepBtn;
1584        this.loader = loader;
1585
1586        this.currentItem = 0;
1587        this.currentTranslateX = 0;
1588        this.currentItemsWidth = 0;
1589        this.previousSteps = []; // Tableau pour enregistrer les étapes précédentes
1590
1591        this.init();
1592    }
1593
1594    init() {
1595        this.handleDynamicWidthAndHeightItems();
1596        setTimeout(() => {
1597            this.handleDynamicWidthAndHeightItems();
1598            this.handleLoader("desactivation");
1599        }, 100);
1600        window.addEventListener("resize", () => {
1601            this.handleDynamicWidthAndHeightItems();
1602            this.handleTranslateOnResize();
1603        });
1604    }
1605
1606    handleLoader(directive) {
1607        if (directive === "activation") {
1608            this.loader.classList.remove("hide");
1609        } else if (directive === "desactivation") {
1610            this.loader.classList.add("hide");
1611        }
1612    }
1613
1614    handleItemActive(direction) {
1615        let newIndex = this.currentItem;
1616
1617        if (direction === "right") {
1618            if (newIndex < this.items.length - 1) {
1619                this.previousSteps.push(newIndex);
1620                newIndex++;
1621            }
1622        } else if (direction === "left") {
1623            if (this.previousSteps.length > 0) {
1624                newIndex = this.previousSteps.pop();
1625            }
1626        }
1627
1628        if (newIndex >= 0 && newIndex < this.items.length) {
1629            this.currentItem = newIndex;
1630        }
1631    }
1632
1633    handleDynamicWidthAndHeightItems(widthToAdd, heightToAdd) {
1634        const itemsWidth = widthToAdd
1635            ? this.wrapper.clientWidth + widthToAdd
1636            : this.wrapper.clientWidth;
1637        this.currentItemsWidth = itemsWidth;
1638
1639        this.items.forEach((el) => {
1640            el.style.minWidth = itemsWidth + "px";
1641            el.style.maxWidth = itemsWidth + "px";
1642        });
1643
1644        const itemActive = this.items[this.currentItem];
1645        itemActive.style.height = null;
1646        let itemsHeight = null;
1647        let itemOneExtraHeight = 150;
1648        if (this.currentItem === 0) {
1649            itemsHeight = heightToAdd
1650                ? itemActive.clientHeight + heightToAdd + itemOneExtraHeight
1651                : itemActive.clientHeight + itemOneExtraHeight;
1652        } else {
1653            itemsHeight = heightToAdd
1654                ? itemActive.clientHeight + heightToAdd
1655                : itemActive.clientHeight;
1656        }
1657
1658        this.items.forEach((el) => {
1659            el.style.height = itemsHeight + "px";
1660        });
1661    }
1662
1663    handleHorizontalSlide(direction) {
1664        const itemsWidth = this.wrapper.clientWidth;
1665        this.handleItemActive(direction);
1666        this.handleDynamicWidthAndHeightItems();
1667        this.currentTranslateX = this.currentItem * itemsWidth;
1668        this.updateTranslateX();
1669        if (this.currentItem > 0) {
1670            this.previousStepBtn.classList.remove("hide");
1671        } else if (this.currentItem === 0) {
1672            this.previousStepBtn.classList.add("hide");
1673        }
1674    }
1675
1676    updateTranslateX() {
1677        this.container.style.transform = `translateX(-${this.currentTranslateX}px)`;
1678    }
1679
1680    handleTranslateOnResize() {
1681        const itemsWidth = this.wrapper.clientWidth;
1682        const newTranslateX = this.currentItem * itemsWidth;
1683        this.currentTranslateX = newTranslateX;
1684        this.updateTranslateX();
1685    }
1686
1687    handleSlideTo(elem) {
1688        const targetIndex = this.items.indexOf(elem);
1689        if (targetIndex !== -1) {
1690            this.previousSteps.push(this.currentItem);
1691            this.currentItem = targetIndex;
1692            this.currentTranslateX = this.currentItem * this.wrapper.clientWidth;
1693            this.handleDynamicWidthAndHeightItems();
1694            this.updateTranslateX();
1695        }
1696    }
1697}
1698
1699/* END DEVIS HORIZONTAL */
1700
1701/* PROGRESS BAR V2 */
1702class ProgressBarV2 {
1703    constructor(containerId, steps, descriptions = null) {
1704        this.container = document.getElementById(containerId);
1705        this.stepsContainer = this.container.querySelector(
1706            ".progress_bar_v2-steps"
1707        );
1708        this.progressBarInner = this.container.querySelector(
1709            ".progress_bar_v2-progress-bar-inner"
1710        );
1711        this.steps = steps;
1712        this.descriptions = descriptions;
1713        this.currentStep = 0;
1714        this.initSteps();
1715    }
1716
1717    initSteps() {
1718        this.steps.forEach((step, index) => {
1719            const stepContainer = document.createElement("div");
1720            stepContainer.classList.add("progress_bar_v2-step-container");
1721
1722            const stepElement = document.createElement("div");
1723            stepElement.classList.add("progress_bar_v2-step");
1724            stepElement.innerHTML = `<p>${index + 1}</p>`;
1725
1726            stepContainer.appendChild(stepElement);
1727
1728            if (this.descriptions && this.descriptions[index]) {
1729                const stepText = document.createElement("div");
1730                stepText.classList.add("progress_bar_v2-step-text");
1731                stepText.textContent = this.descriptions[index];
1732                stepContainer.appendChild(stepText);
1733            }
1734
1735            this.stepsContainer.appendChild(stepContainer);
1736        });
1737        this.updateSteps(0);
1738    }
1739
1740    updateProgress(percentage) {
1741        if (percentage < 0) percentage = 0;
1742        if (percentage > 100) percentage = 100;
1743        this.progressBarInner.style.width = `${percentage}%`;
1744
1745        const stepIndex = Math.floor((percentage / 100) * this.steps.length);
1746        this.updateSteps(stepIndex);
1747    }
1748
1749    updateSteps(activeIndex) {
1750        const stepContainers = this.stepsContainer.querySelectorAll(
1751            ".progress_bar_v2-step-container"
1752        );
1753        stepContainers.forEach((container, index) => {
1754            if (index <= activeIndex) {
1755                container.classList.add("progress_bar_v2-active");
1756            } else {
1757                container.classList.remove("progress_bar_v2-active");
1758            }
1759        });
1760    }
1761
1762    nextStep() {
1763        if (this.currentStep < this.steps.length - 1) {
1764            this.currentStep++;
1765            const percentage = (this.currentStep / (this.steps.length - 1)) * 100;
1766            this.updateProgress(percentage);
1767        }
1768    }
1769
1770    prevStep() {
1771        if (this.currentStep > 0) {
1772            this.currentStep--;
1773            const percentage = (this.currentStep / (this.steps.length - 1)) * 100;
1774            this.updateProgress(percentage);
1775        }
1776    }
1777}
1778
1779/* END PROGRESS BAR V2 */
1780
1781function autoService(services, currentStep) {
1782  if (window.isAidantForm) return;
1783    const actualUrl = window.location.href;
1784    let matchedService = null;
1785
1786    // Cherche si l'URL correspond à l'une des conditions
1787    for (const service of services) {
1788        if (service.urls.some(include => actualUrl.includes(include))) {
1789            matchedService = service;
1790            break;
1791        }
1792    }
1793
1794    if (matchedService) {
1795        setTimeout(() => {
1796            waitForElem(`label[for="${matchedService.labelFor}"]`).then((e) => {
1797                e.click();
1798            });
1799        }, 200);
1800    } else {
1801        const element = document.querySelector(".form-etape-step" + currentStep);
1802        if (element) {
1803            const offsetTop = element.getBoundingClientRect().top + window.scrollY - 100;
1804            window.scrollTo({ top: offsetTop, behavior: "smooth" });
1805        }
1806    }
1807}
1808
1809window.addEventListener("DOMContentLoaded", () => {
1810    waitForElem('.txt-asterisque a').then(() => {
1811        document
1812            .querySelector(".txt-asterisque a")
1813            .addEventListener("click", function (event) {
1814                event.preventDefault();
1815            });
1816    });
1817});
1818
1819//Gere la provenance des fiches agences pour le parcours prospect
1820function villeIntervention() {
1821    jQuery.post(variables.ajax_url, {action: "ville_intervention"}, function (response) {
1822        console.log("Réponse AJAX reçue :", response);
1823
1824        function infoAgenceBanner(){
1825            const agenceContainer = document.querySelectorAll(".agence-container");
1826
1827            agenceContainer.forEach((container) => {
1828                if (response.data){
1829                    container.classList.remove("hide");
1830                }
1831                const agenceName = container.querySelector(".agence-name");
1832                if(agenceName){
1833                    agenceName.textContent = response.data.nom;
1834                }
1835
1836                const agenceTel = container.querySelector(".agence-tel");
1837                if(agenceTel){
1838                    agenceTel.href = "tel:" + response.data.tel_fixe;
1839                }
1840
1841                const agenceTelNumber = container.querySelector(".agence-tel .number");
1842                if (agenceTelNumber) {
1843                    agenceTelNumber.textContent = response.data.tel_fixe;
1844                }
1845            })
1846        }
1847
1848        // Le visiteur arrive d'une fiche agence : l'agence est déjà connue, lui redemander
1849        // sa ville est une friction inutile. On renseigne les attributs data-* et pas
1850        // seulement la valeur visible, car c'est eux que lit sendDevis() pour construire
1851        // le payload (cf. devis["ville"] / devis["code_postal"]).
1852        // Le champ reste éditable : la ville du bureau n'est pas forcément celle du client,
1853        // on ne pré-remplit donc que s'il est encore vide.
1854        function prefillVilleAgence(){
1855            const input = document.querySelector("#inputAddress");
1856            if (!input || input.value !== "") {
1857                return;
1858            }
1859            const ville = response.data.ville_bureau;
1860            const cp = response.data.cp_bureau;
1861            if (!ville || !cp) {
1862                return;
1863            }
1864            input.value = ville;
1865            input.setAttribute("data-ville", ville);
1866            input.setAttribute("data-code_postal", cp);
1867            // Si le visiteur retouche le champ, le handler input partagé repurge les
1868            // data-*, sur ce parcours comme sur les autres.
1869        }
1870
1871        function rightIcon(){
1872            const icon1 = document.querySelector(".form-etape-1 .form-header div");
1873            if(icon1){
1874                icon1.classList.remove("form-header-number")
1875                icon1.classList.add("parcours-prospect-icone1");
1876            }
1877            const icon2 = document.querySelector(".form-etape-2 .form-header div");
1878            if(icon2){
1879                icon2.classList.remove("form-header-number")
1880                icon2.classList.add("parcours-prospect-icone2");
1881            }
1882        }
1883
1884        if (response.success) {
1885            rightIcon();
1886            infoAgenceBanner();
1887            prefillVilleAgence();
1888
1889            // Sur ce parcours l'agence vient du cookie id_agence, pas d'une recherche de
1890            // commune : agenceSearch() n'est jamais jouée, donc c'est ici qu'il faut
1891            // décider de l'affichage du créneau de rappel. response.data est un AgenceDTO,
1892            // qui porte call_center au même titre que les agences d'agences_coord_social.
1893            toggleRappelCallCenter(response.data.call_center);
1894
1895            const searchInputMargin = document.querySelector(".devis-container .left-content .input-search-container .input-search");
1896            if (searchInputMargin) {
1897                searchInputMargin.style.marginLeft = '0';
1898            }
1899
1900            const remerciementAgenceSection = document.querySelector(".agence-container");
1901            remerciementAgenceSection.style.flexDirection = "column";
1902
1903            if (currentStep === 0) {
1904                console.log(currentStep);
1905                const formContainer = document.querySelector(".left-content .form-container");
1906                checkService(response.data.id_agence)
1907                if (formContainer) {
1908                    formContainer.style.display = 'block';
1909                }
1910
1911                const etape1ToShow = document.querySelector(".form-etape-1");
1912                if (etape1ToShow) {
1913                    etape1ToShow.style.display = 'block';
1914                }
1915
1916                const backBtn = document.querySelector(".back-btn");
1917                if(backBtn && currentStep === 0){
1918                    currentStep--;
1919                }
1920                currentStep++;
1921            }
1922
1923            waitForElem('.input-search-container.disable').then((communeContainer) => {
1924                const container = communeContainer;
1925                const removeDisable = () => {
1926                    if (container.classList.contains('disable')) {
1927                        container.classList.remove('disable');
1928                    }
1929                };
1930                removeDisable();
1931                const observer = new MutationObserver(() => {
1932                    removeDisable();
1933                });
1934                observer.observe(container, {attributes: true, attributeFilter: ['class']});
1935            });
1936
1937            waitForElem('.form-etape-step1').then((step1Element) => {
1938                const backBtn = document.querySelector(".devis-backBtn");
1939                const updateBtn = (target) =>{
1940                    if(target.classList.contains('disable')) {
1941                        backBtn.classList.remove('hide');
1942                    }else{
1943                        backBtn.classList.add('hide');
1944                    }
1945                }
1946                updateBtn(step1Element);
1947                const handleMutation = (mutationsList) => {
1948                    for (const mutation of mutationsList) {
1949                        if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
1950                            updateBtn(mutation.target);
1951                        }
1952                    }
1953                };
1954                const observer = new MutationObserver(handleMutation);
1955                observer.observe(step1Element, {attributes: true, attributeFilter: ['class']});
1956            });
1957        }
1958    });
1959}
1960
1961// Limite le comportement "isFixed" de .floating-right-section à la section .devis-container :
1962// retire la classe quand on scrolle hors de la section, la remet quand on revient dedans.
1963$(document).ready(function () {
1964    const floating = document.querySelector('.floating-right-section');
1965    const devisContainer = document.querySelector('.devis-container');
1966    if (!floating || !devisContainer) return;
1967
1968    let shouldFix = floating.classList.contains('isFixed');
1969    let updating = false;
1970
1971    const getOffset = () => (window.matchMedia('(max-width:767px)').matches ? 58 : 181);
1972
1973    const isContainerInFixedZone = () => {
1974        const rect = devisContainer.getBoundingClientRect();
1975        const offset = getOffset();
1976        // Fixé uniquement quand la ligne de fix (offset depuis le haut du viewport)
1977        // est à l'intérieur de .devis-container :
1978        // - rect.top < offset  -> on a scrollé sous le haut de la section
1979        // - rect.bottom > offset -> on n'est pas encore passé sous la section
1980        return rect.top < offset && rect.bottom > offset;
1981    };
1982
1983    // Garde shouldFix synchro avec les addClass/removeClass faits ailleurs dans le code
1984    const classObserver = new MutationObserver(() => {
1985        if (updating) return;
1986        if (floating.classList.contains('isFixed')) {
1987            shouldFix = true;
1988        } else if (isContainerInFixedZone()) {
1989            // classe retirée alors que la section est visible -> vraie remise à zéro
1990            shouldFix = false;
1991        }
1992    });
1993    classObserver.observe(floating, { attributes: true, attributeFilter: ['class'] });
1994
1995    const update = () => {
1996        if (!shouldFix) return;
1997        const inZone = isContainerInFixedZone();
1998        console.log(inZone);
1999        const hasClass = floating.classList.contains('isFixed');
2000        if (inZone && !hasClass) {
2001            updating = true;
2002            floating.classList.add('isFixed');
2003            updating = false;
2004        } else if (!inZone && hasClass) {
2005            updating = true;
2006            floating.classList.remove('isFixed');
2007            updating = false;
2008        }
2009    };
2010
2011    window.addEventListener('scroll', update, { passive: true });
2012    window.addEventListener('resize', update);
2013});
2014
2015/**
2016 * Affiche ou masque le select "Quel est le meilleur moment pour vous contacter ?".
2017 * Le flag vient d'Ozone avec l'agence (call_center = 1).
2018 * Quand le select est masqué, on le remet à zéro pour ne pas envoyer
2019 * une préférence de rappel à une agence qui n'a pas de call center.
2020 */
2021function toggleRappelCallCenter(callCenter) {
2022    var $bloc = $(".rappel-call-center");
2023
2024    if (!$bloc.length) {
2025        return;
2026    }
2027
2028    if (callCenter == 1) {
2029        $bloc.removeClass("hide");
2030        return;
2031    }
2032
2033    $bloc.addClass("hide");
2034    $bloc.find('select[name="rappel_creneau"]').val("");
2035}

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.