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.