1// Populate hidden fields with URL parameters 2 // const urlParams = new URLSearchParams(window.location.search); 3 // $('#utm-source').val(urlParams.get('utm_source') || ''); 4 // $('#utm-medium').val(urlParams.get('utm_medium') || ''); 5 // $('#utm-campaign').val(urlParams.get('utm_campaign') || ''); 6 7(function($, FW) { 8 'use strict'; 9 10 window.DonationFormData = window.DonationFormData || {}; 11 let nonceManagerInitialized = false; 12 13 FW.InteractionManager = (function() { 14 15 function initializeNonceManager() { 16 const config = window.DonationFormData || {}; 17 const ajaxUrl = config.ajaxUrl; 18 const formType = config.formType; 19 const $form = $('#donation-form'); 20 const $nonceField = $('#dfp-nonce'); 21 22 if (!$form.length || !$nonceField.length || !ajaxUrl || !formType) { 23 return; 24 } 25 26 if (nonceManagerInitialized) { 27 return; 28 } 29 nonceManagerInitialized = true; 30 31 const refreshIntervalSeconds = Number(config.nonceRefreshInterval); 32 const refreshIntervalMs = !Number.isNaN(refreshIntervalSeconds) && refreshIntervalSeconds > 0 33 ? refreshIntervalSeconds * 1000 34 : 180000; 35 36 let inFlightRequest = null; 37 let refreshTimer = null; 38 let pendingSubmit = false; 39 let allowSubmit = false; 40 41 function hasNonce() { 42 return Boolean($nonceField.val()); 43 } 44 45 function resumePendingSubmit() { 46 if (!pendingSubmit || !hasNonce()) { 47 return; 48 } 49 pendingSubmit = false; 50 allowSubmit = true; 51 $form.trigger('submit'); 52 } 53 54 function scheduleRefresh(successful) { 55 clearTimeout(refreshTimer); 56 if (refreshIntervalMs <= 0) { 57 return; 58 } 59 const retryDelay = Math.min(60000, refreshIntervalMs); 60 const delay = successful ? refreshIntervalMs : retryDelay; 61 refreshTimer = setTimeout(function () { 62 fetchNonce('interval'); 63 }, delay); 64 } 65 66 function fetchNonce(reason) { 67 if (inFlightRequest) { 68 return inFlightRequest; 69 } 70 71 inFlightRequest = $.ajax({ 72 url: ajaxUrl, 73 method: 'GET', 74 dataType: 'json', 75 cache: false, 76 data: { 77 action: 'dfp_get_nonce', 78 form_type: formType 79 } 80 }).done(function (response) { 81 if (response && response.success && response.data && response.data.nonce) { 82 $nonceField.val(response.data.nonce); 83 scheduleRefresh(true); 84 resumePendingSubmit(); 85 } else { 86 console.error('Réponse inattendue lors du chargement du nonce.', response); 87 scheduleRefresh(false); 88 if (reason === 'submit') { 89 pendingSubmit = false; 90 window.alert('Nous n\'avons pas pu préparer le formulaire. Veuillez réessayer.'); 91 } 92 } 93 }).fail(function (jqXHR, textStatus) { 94 console.error('Impossible de récupérer un nonce frais :', textStatus); 95 scheduleRefresh(false); 96 if (reason === 'submit') { 97 pendingSubmit = false; 98 window.alert('Nous n\'avons pas pu préparer le formulaire. Veuillez vérifier votre connexion et réessayer.'); 99 } 100 }).always(function () { 101 inFlightRequest = null; 102 }); 103 104 return inFlightRequest; 105 } 106 107 $form.on('submit.dfpNonce', function (event) { 108 if (allowSubmit) { 109 allowSubmit = false;
110 return; 111 } 112 113 if (hasNonce()) { 114 return; 115 } 116 117 event.preventDefault(); 118 pendingSubmit = true; 119 fetchNonce('submit'); 120 }); 121 122 function onVisibilityChange() { 123 if (document.visibilityState === 'visible') { 124 fetchNonce('visibility'); 125 } 126 } 127 128 function onWindowFocus() { 129 fetchNonce('focus'); 130 } 131 132 document.addEventListener('visibilitychange', onVisibilityChange); 133 $(window).on('focus.dfpNonce', onWindowFocus); 134 $(window).on('beforeunload.dfpNonce', function () { 135 clearTimeout(refreshTimer); 136 if (inFlightRequest && typeof inFlightRequest.abort === 'function') { 137 inFlightRequest.abort(); 138 } 139 }); 140 141 fetchNonce('initial'); 142 } 143 144 function init() { 145 initializeNonceManager(); 146 147 const FormType = (window.DonationFormData && window.DonationFormData.formType) ? window.DonationFormData.formType : ''; 148 if (FormType == "general") { 149 handleRecurrenceButtons(); 150 handleOneTimeAmountButtons(); 151 handleMonthlyButtons(); 152 handleConvertMonthlyButtons(); 153 handleTributeTypeInteractions(); 154 handleEcardSection(); 155 handleEcardImageSelection(); 156 handleGeneralFeeCovering(); 157 handleDonationTypeInteractions(); 158 } 159 if (FormType == "monthly") { 160 handleRecurrenceButtons(); 161 handleOneTimeAmountButtons(); 162 handleMonthlyButtons(); 163 handleConvertMonthlyButtons(); 164 handleTributeTypeInteractions(); 165 handleEcardSection(); 166 handleEcardImageSelection(); 167 handleGeneralFeeCovering(); 168 handleDonationTypeInteractions(); 169 } 170 if (FormType == "one-time") { 171 handleRecurrenceButtons(); 172 handleOneTimeAmountButtons(); 173 handleMonthlyButtons(); 174 handleConvertMonthlyButtons(); 175 handleTributeTypeInteractions(); 176 handleEcardSection(); 177 handleEcardImageSelection(); 178 handleGeneralFeeCovering(); 179 handleDonationTypeInteractions(); 180 } 181 if (FormType == "golf") { 182 handleGolfSelections(); 183 handleGolfFeeCovering(); 184 handleDonationTypeInteractions(); 185 } 186 if (FormType == "loto") { 187 handleProductSelections(); 188 handleLotoFeeCovering(); 189 handleDonationTypeInteractions(); 190 } 191 if (FormType == "paulee") { 192 handlePauleeSelections(); 193 handlePauleeFeeCovering(); 194 handleDonationTypeInteractions(); 195 } 196 if (FormType == "invoice") { 197 handleInvoiceSelections(); 198 handleInvoiceFeeCovering(); 199 handleDonationTypeInteractions(); 200 } 201 if (FormType == "admin") { 202 203 } 204 if (FormType == "encrypted") { 205 handleEncOneTimeAmountButtons(); 206 handleGeneralFeeCovering(); 207 handleEncChangeInfo(); 208 } 209 handleCommentSection(); 210 } 211 212 function syncAmount(amount, $targetElement, $inputField = null) { 213 const parsedAmount = parseFloat(amount); 214 if (isNaN(parsedAmount) || parsedAmount < 0) { 215 $targetElement.text('0'); 216 if ($inputField) { 217 $inputField.addClass('input-error'); 218 } 219 } else { 220 $targetElement.text(parseFloat(parsedAmount.toFixed(2))); 221 if ($inputField) { 222 $inputField.removeClass('input-error'); 223 } 224 } 225 } 226 227 function calculateSuggestedMonthly(oneTimeAmount, tiers = null) { 228 const defaultDonationTiers = [ 229 { min: 0, max: 100, suggestedMonthly: 10 }, 230 { min: 100, max: 200, suggestedMonthly: 20 }, 231 { min: 200, max: Infinity, suggestedMonthly: 50 } 232 ]; 233 const donationTiers = (tiers && Array.isArray(tiers) && tiers.length > 0) ? tiers : defaultDonationTiers; 234 235 if (typeof oneTimeAmount !== 'number' || isNaN(oneTimeAmount) || oneTimeAmount <= 0) { 236 console.warn(`Montant de don ponctuel invalide: ${oneTimeAmount}`); 237 return 0; 238 } 239 240 for (let tier of donationTiers) { 241 if (oneTimeAmount >= tier.min && oneTimeAmount < tier.max) { 242 if (typeof tier.suggestedMonthly !== 'number' || isNaN(tier.suggestedMonthly)) { 243 console.error(`Valeur suggérée invalide dans le tier: ${JSON.stringify(tier)}`); 244 continue; 245 } 246 return parseFloat(tier.suggestedMonthly.toFixed(2)); 247 } 248 } 249 console.warn(`Aucun tier correspondant pour le montant: ${oneTimeAmount}. Suggestion par défaut: 10.`); 250 return 10; 251 } 252 253 function calculateProductTotalPrice(itemPrice, itemNumber) { 254 var price = parseFloat(itemPrice); 255 var number = parseFloat(itemNumber); 256 if (isNaN(price) || price <= 0) { 257 console.warn('Invalid product price:', price); 258 return 0; 259 } 260 if (isNaN(number) || number < 0) { // Allow zero tickets. 261 console.warn('Invalid product number:', number); 262 return 0; 263 } 264 return parseFloat((price * number).toFixed(2)); 265 } 266 267 function sprintf(template /*, ...args */) { 268 var args = Array.prototype.slice.call(arguments, 1); 269 return template.replace(/%(\d+)\$s/g, function(match, index) { 270 return typeof args[index - 1] !== 'undefined' ? args[index - 1] : match; 271 }); 272 } 273 274 function handleRecurrenceButtons() { 275 const $recurrenceButtons = $('.recurrence-btn'); 276 const $recurrenceInput = $('#recurrence'); 277 const $monthlyContainer = $('#monthly-amount-container'); 278 const $oneTimeContainer = $('#one-time-amount-container'); 279 const $oneTimeDescription = $('.recurrence-description--one-time'); 280 const $monthlyDescription = $('.recurrence-description--monthly'); 281 const $confirmationMessage = $('#recurrence-confirmation');
282 const $oneTimeDonationSummary = $('.one-time-donation-summary'); 283 const $monthlyDonationSummary = $('.monthly-donation-summary'); 284 285 function updateUI(recurrenceType) { 286 if (recurrenceType === 'one-time') { 287 $monthlyContainer.hide(); 288 $oneTimeContainer.show(); 289 $monthlyDescription.hide(); 290 $oneTimeDescription.show(); 291 $oneTimeDonationSummary.show(); 292 $monthlyDonationSummary.hide(); 293 showConfirmation('Vous avez sélectionné un don ponctuel.'); 294 FW.StepManager.updateNavigation('step-giftChoice'); 295 } else if (recurrenceType === 'monthly') { 296 $oneTimeContainer.hide(); 297 $monthlyContainer.show(); 298 $oneTimeDescription.hide(); 299 $monthlyDescription.show(); 300 $oneTimeDonationSummary.hide(); 301 $monthlyDonationSummary.show(); 302 showConfirmation('Vous avez sélectionné un don mensuel.'); 303 FW.StepManager.updateNavigation('step-giftChoice'); 304 } else { 305 console.warn(`Type de don non géré: ${recurrenceType}`); 306 showConfirmation('Type de don non reconnu.'); 307 } 308 } 309 310 function setActiveButton($activeButton) { 311 $recurrenceButtons.removeClass('recurrence-btn--active').attr('aria-pressed', 'false'); 312 $activeButton.addClass('recurrence-btn--active').attr('aria-pressed', 'true'); 313 } 314 315 function showConfirmation(message) { 316 $confirmationMessage.text(message).fadeIn().delay(3000).fadeOut(); 317 } 318 319 $recurrenceButtons.each(function () { 320 const $button = $(this); 321 const isActive = $button.hasClass('recurrence-btn--active'); 322 $button.attr('aria-pressed', isActive ? 'true' : 'false'); 323 }); 324 325 $recurrenceButtons.on('click', function () { 326 const $button = $(this); 327 const recurrenceType = $button.data('recurrence'); 328 329 if (!recurrenceType) { 330 console.error('Type de don non défini pour ce bouton.'); 331 showConfirmation('Erreur: Type de don non défini.'); 332 return; 333 } 334 335 $recurrenceInput.val(recurrenceType);
336 setActiveButton($button); 337 updateUI(recurrenceType); 338 }); 339 340 $recurrenceButtons.on('keypress', function (e) { 341 if (e.key === 'Enter' || e.key === ' ') { 342 e.preventDefault(); 343 $(this).click(); 344 } 345 }); 346 347 const $defaultActiveButton = $recurrenceButtons.filter('.recurrence-btn--active').first(); 348 if ($defaultActiveButton.length) { 349 updateUI($defaultActiveButton.data('recurrence')); 350 } else { 351 const defaultRecurrence = 'monthly'; 352 $recurrenceButtons.filter(`[data-recurrence="${defaultRecurrence}"]`).addClass('recurrence-btn--active').attr('aria-pressed', 'true'); 353 $recurrenceInput.val(defaultRecurrence); 354 updateUI(defaultRecurrence); 355 } 356 } 357 358 function handleOneTimeAmountButtons() { 359 const $oneTimeButtons = $('.amount-option--one-time'); 360 const $oneTimeInput = $('#one-time-amount'); 361 const $convertMonthlySuggestedAmount = $('.convert-monthly-suggested-amount'); 362 const $confirmMonthly = $('#confirm-monthly'); 363 364 if (!$oneTimeButtons.length || !$oneTimeInput.length || !$convertMonthlySuggestedAmount.length || !$confirmMonthly.length) { 365 console.warn('Eléments requis pour les boutons de don ponctuel manquants.'); 366 return; 367 } 368 369 function updateActiveState($activeButton) { 370 $oneTimeButtons.attr('aria-pressed', 'false').removeClass('amount-option--active'); 371 $activeButton.attr('aria-pressed', 'true').addClass('amount-option--active'); 372 } 373 374 function validateAmount(amount) { 375 const parsedAmount = parseFloat(amount); 376 return !isNaN(parsedAmount) && parsedAmount > 0; 377 } 378 379 function debounce(func, delay) { 380 let debounceTimer; 381 return function () { 382 const context = this; 383 const args = arguments; 384 clearTimeout(debounceTimer); 385 debounceTimer = setTimeout(() => func.apply(context, args), delay); 386 }; 387 } 388 389 $oneTimeButtons.on('click', function () { 390 const $button = $(this); 391 const oneTimeValue = $button.data('amount'); 392 393 if (!validateAmount(oneTimeValue)) { 394 alert('Veuillez sélectionner un montant de don valide.'); 395 return; 396 } 397 398 const suggestedMonthlyAmount = calculateSuggestedMonthly(Number(oneTimeValue)); 399 $oneTimeInput.val(oneTimeValue).removeClass('input-error'); 400 syncAmount(oneTimeValue, $('.sync-one-time-amount'), $button); 401 $convertMonthlySuggestedAmount.text(suggestedMonthlyAmount); 402 $confirmMonthly.attr('data-amount', suggestedMonthlyAmount); 403 updateActiveState($button); 404 }); 405 406 $oneTimeInput.on('input', debounce(function () { 407 const inputVal = $(this).val(); 408 409 if (!validateAmount(inputVal)) { 410 syncAmount(0, $('.sync-one-time-amount'), $(this)); 411 $convertMonthlySuggestedAmount.text('0'); 412 $confirmMonthly.attr('data-amount', '0'); 413 $oneTimeButtons.removeClass('amount-option--active'); 414 $(this).addClass('input-error'); 415 return; 416 } 417 418 const suggestedMonthlyAmount = calculateSuggestedMonthly(Number(inputVal)); 419 syncAmount(inputVal, $('.sync-one-time-amount'), $(this)); 420 $convertMonthlySuggestedAmount.text(suggestedMonthlyAmount); 421 $confirmMonthly.attr('data-amount', suggestedMonthlyAmount); 422 $oneTimeButtons.removeClass('amount-option--active'); 423 $(this).removeClass('input-error'); 424 }, 300)); 425 426 $oneTimeInput.on('blur', function () { 427 const inputVal = $(this).val(); 428 if (!validateAmount(inputVal)) { 429 $(this).val(''); 430 syncAmount(0, $('.sync-one-time-amount'), $(this)); 431 $convertMonthlySuggestedAmount.text('0'); 432 $confirmMonthly.attr('data-amount', '0'); 433 $oneTimeButtons.removeClass('amount-option--active'); 434 } 435 }); 436 437 $oneTimeButtons.on('keypress', function (e) { 438 if (e.key === 'Enter' || e.key === ' ') { 439 e.preventDefault(); 440 $(this).click(); 441 } 442 }); 443 } 444 445 function handleEncOneTimeAmountButtons() { 446 const $oneTimeInput = $('#one-time-amount'); 447 448 function validateAmount(amount) { 449 const parsedAmount = parseFloat(amount); 450 return !isNaN(parsedAmount) && parsedAmount > 0; 451 } 452 453 function debounce(func, delay) { 454 let debounceTimer; 455 return function () { 456 const context = this; 457 const args = arguments; 458 clearTimeout(debounceTimer); 459 debounceTimer = setTimeout(() =>
459 func.apply(context, args), delay); 460 }; 461 } 462 463 $oneTimeInput.on('input', debounce(function () { 464 const inputVal = $(this).val(); 465 466 if (!validateAmount(inputVal)) { 467 syncAmount(0, $('.sync-one-time-amount'), $(this)); 468 $(this).addClass('input-error'); 469 return; 470 } 471 472 syncAmount(inputVal, $('.sync-one-time-amount'), $(this)); 473 474 }, 300)); 475 476 $oneTimeInput.on('blur', function () { 477 const inputVal = $(this).val(); 478 if (!validateAmount(inputVal)) { 479 $(this).val(''); 480 syncAmount(0, $('.sync-one-time-amount'), $(this)); 481 } 482 }); 483 } 484 485 function handleEncChangeInfo() { 486 const $changeEmail = $('#change-email'); 487 const $changeAddress = $('#change-address'); 488 const $newEmail = $('.new-email'); 489 const $newAddress = $('.new-address'); 490 491 const $donorEmail = $('#donor-email'); 492 const $donorAddress = $('#donor-address'); 493 const $donorAddressCity = $('#donor-address-city'); 494 const $donorAddressZip = $('#donor-address-zip'); 495 const $donorAddressState = $('#donor_address_state'); 496 497 $changeEmail.on('change', function () { 498 if ($changeEmail.is(':checked')) { 499 $newEmail.show(); 500 $donorEmail.attr('required', 'True'); 501 } else { 502 $newEmail.hide(); 503 $donorEmail.removeAttr('required'); 504 } 505 }); 506 507 $changeAddress.on('change', function () { 508 if ($changeAddress.is(':checked')) { 509 $newAddress.show(); 510 $donorAddress.attr('required', 'True'); 511 $donorAddressCity.attr('required', 'True'); 512 $donorAddressZip.attr('required', 'True'); 513 $donorAddressState.attr('required', 'True'); 514 } else { 515 $newAddress.hide(); 516 $donorAddress.removeAttr('required'); 517 $donorAddressCity.removeAttr('required'); 518 $donorAddressZip.removeAttr('required'); 519 $donorAddressState.removeAttr('required'); 520 } 521 }); 522 523 } 524 525 function handleMonthlyButtons() { 526 const $monthlyButtons = $('.amount-option--monthly'); 527 const $monthlyInput = $('#monthly-amount'); 528 const $syncMonthlyAmount = $('.sync-monthly-amount'); 529 const $confirmMonthly = $('#confirm-monthly'); 530 531 function setActiveButton($activeButton) { 532 $monthlyButtons.removeClass('amount-option--active').attr('aria-pressed', 'false'); 533 $activeButton.addClass('amount-option--active').attr('aria-pressed', 'true'); 534 } 535 536 function validateAmount(amount) { 537 const parsedAmount = parseFloat(amount); 538 return !isNaN(parsedAmount) && parsedAmount > 0 && parsedAmount <= 10000; 539 } 540 541 function onMonthlyButtonClick() { 542 const $button = $(this); 543 const monthlyAmount = $button.data('amount'); 544 545 if (!validateAmount(monthlyAmount)) { 546 alert('Veuillez sélectionner un montant de don valide.'); 547 return; 548 } 549 550 $monthlyInput.val(monthlyAmount); 551 syncAmount(monthlyAmount, $syncMonthlyAmount, $(this)); 552 $confirmMonthly.attr('data-amount', monthlyAmount);
553 setActiveButton($button); 554 } 555 556 function onMonthlyInputChange() { 557 const inputVal = $(this).val(); 558 if (!validateAmount(inputVal)) { 559 syncAmount('0', $syncMonthlyAmount, $(this)); 560 $confirmMonthly.attr('data-amount', '0'); 561 $monthlyButtons.removeClass('amount-option--active'); 562 return; 563 } 564 syncAmount(inputVal, $syncMonthlyAmount, $(this)); 565 $confirmMonthly.attr('data-amount', inputVal); 566 $monthlyButtons.removeClass('amount-option--active'); 567 } 568 569 function onMonthlyInputBlur() { 570 const inputVal = $(this).val(); 571 if (!validateAmount(inputVal)) { 572 $(this).val(''); 573 syncAmount('0', $syncMonthlyAmount, $(this)); 574 $confirmMonthly.attr('data-amount', '0'); 575 $monthlyButtons.removeClass('amount-option--active'); 576 } 577 } 578 579 function onMonthlyButtonKeyPress(e) { 580 if (e.key === 'Enter' || e.key === ' ') { 581 e.preventDefault(); 582 $(this).click(); 583 } 584 } 585 586 $monthlyButtons.each(function () { 587 const $button = $(this); 588 $button.attr('aria-pressed', $button.hasClass('amount-option--active') ? 'true' : 'false'); 589 }); 590 591 $monthlyButtons.on('click', onMonthlyButtonClick); 592 $monthlyButtons.on('keypress', onMonthlyButtonKeyPress); 593 $monthlyInput.on('input', onMonthlyInputChange); 594 $monthlyInput.on('blur', onMonthlyInputBlur); 595 596 syncAmount($monthlyInput.val() || '0', $syncMonthlyAmount); 597 } 598 599 function handleConvertMonthlyButtons() { 600 const $confirmMonthly = $('#confirm-monthly'); 601 const $recurrenceButtons = $('.recurrence-btn'); 602 const $recurrenceInput = $('#recurrence'); 603 const $monthlyButtons = $('.amount-option--monthly'); 604 const $monthlyInput = $('#monthly-amount'); 605 const $monthlyContainer = $('#monthly-amount-container'); 606 const $oneTimeContainer = $('#one-time-amount-container'); 607 const $monthlyButton = $('#monthly-btn'); 608 const $monthlyConfirmation = $('#monthly-confirmation'); 609 const $oneTimeDonationSummary = $('.one-time-donation-summary'); 610 const $monthlyDonationSummary = $('.monthly-donation-summary'); 611 const $syncMonthlyAmount = $('.sync-monthly-amount'); 612 613 function validateAmount(amount) { 614 const parsedAmount = parseFloat(amount); 615 return !isNaN(parsedAmount) && parsedAmount > 0; 616 } 617 618 function setActiveButton($button) { 619 $recurrenceButtons.removeClass('recurrence-btn--active').attr('aria-pressed', 'false'); 620 $monthlyButtons.removeClass('amount-option--active').attr('aria-pressed', 'false'); 621 $button.addClass('amount-option--active').attr('aria-pressed', 'true'); 622 } 623 624 function showConfirmation(message) { 625 if ($monthlyConfirmation.length) { 626 $monthlyConfirmation.text(message).fadeIn().delay(3000).fadeOut(); 627 } else { 628 console.warn('Conteneur de confirmation introuvable.'); 629 } 630 } 631 632 function onConfirmMonthlyClick() { 633 const suggestedAmount = $confirmMonthly.attr('data-amount'); 634 if (!validateAmount(suggestedAmount)) { 635 alert('Montant suggéré invalide. Veuillez réessayer.'); 636 return; 637 } 638 $recurrenceInput.val('monthly'); 639 $monthlyInput.val(suggestedAmount); 640 syncAmount(suggestedAmount, $syncMonthlyAmount);
641 setActiveButton($monthlyButton); 642 $oneTimeContainer.hide(); 643 $monthlyContainer.show(); 644 $oneTimeDonationSummary.hide(); 645 $monthlyDonationSummary.show(); 646 showConfirmation(`Vous avez sélectionné un don mensuel de ${parseFloat(suggestedAmount).toFixed(2)} $.`); 647 648 if (FW && FW.ValidationManager && FW.StepManager) { 649 FW.ValidationManager.validateCurrentStep(FW.StepManager.goToNextStep); 650 } else { 651 console.error('FW.ValidationManager ou FW.StepManager non défini.'); 652 } 653 } 654 655 function onMonthlyInputClick() { 656 $monthlyButtons.removeClass('amount-option--active').attr('aria-pressed', 'false'); 657 } 658 659 function onConfirmMonthlyKeyPress(e) { 660 if (e.key === 'Enter' || e.key === ' ') { 661 e.preventDefault(); 662 $(this).click(); 663 } 664 } 665 666 $confirmMonthly.on('click', onConfirmMonthlyClick); 667 $confirmMonthly.on('keypress', onConfirmMonthlyKeyPress); 668 $monthlyInput.on('click', onMonthlyInputClick); 669 } 670 671 function handleTributeTypeInteractions() { 672 const $dedicatedCheckbox = $('#dedicated-gift-checkbox'); 673 const $honorCheckbox = $('#celebration-gift-checkbox'); 674 const $memoriamCheckbox = $('#memoriam-gift-checkbox'); 675 const $gratitudeCheckbox = $('#gratitude-gift-checkbox'); 676 const $tributeOptions = $('.tribute-options'); 677 const $tributeInfo = $('.tribute-info'); 678 const $deptSelect = $('#tribute-dept-select'); 679 const $honorDescription = $('.tribute-description--celebration'); 680 const $memoriamDescription = $('.tribute-description--memoriam'); 681 const $gratitudeDescription = $('.tribute-description--gratitude'); 682 const $addEcardBtn = $('#addEcardBtn'); 683 const $tributeNameInput = $('#tribute-name'); 684 const $tributeDeptInput = $('#tribute-dept'); 685 686 687 function updateTributeChoiceUI($selectedCheckbox, $showOptions) { 688 if ($selectedCheckbox.is(':checked')) { 689 $showOptions.show(); 690 $honorCheckbox.prop('checked', false).attr('aria-checked', 'false'); 691 $memoriamCheckbox.prop('checked', false).attr('aria-checked', 'false'); 692 $gratitudeCheckbox.prop('checked', false).attr('aria-checked', 'false'); 693 $tributeNameInput.val(''); 694 } else { 695 $showOptions.hide(); 696 $tributeInfo.hide(); 697 } 698 } 699 700 // This function now handles all three options. 701 function updateTributeOptionUI($selectedCheckbox) { 702 if ($selectedCheckbox.is(':checked')) { 703 // Uncheck the other checkboxes and update their aria attributes. 704 [$honorCheckbox, $memoriamCheckbox, $gratitudeCheckbox].forEach(function($checkbox) { 705 if ($checkbox.get(0) !== $selectedCheckbox.get(0)) { 706 $checkbox.prop('checked', false) 707 .attr('aria-checked', 'false'); 708 } else { 709 $checkbox.attr('aria-checked', 'true'); 710 } 711 }); 712 // Show tribute info and ensure only the selected description is visible. 713 $tributeInfo.show(); 714 // $honorDescription.hide(); 715 // $memoriamDescription.hide(); 716 // $gratitudeDescription.hide(); 717 if ($selectedCheckbox.is($honorCheckbox)) { 718 // $honorDescription.show(); 719 $addEcardBtn.show(); 720 $deptSelect.hide(); 721 $tributeNameInput.val(''); 722 $tributeDeptInput.val('autre'); 723 } else if ($selectedCheckbox.is($memoriamCheckbox)) { 724 // $memoriamDescription.show(); 725 $addEcardBtn.show(); 726 $deptSelect.hide(); 727 $tributeNameInput.val(''); 728 $tributeDeptInput.val('autre'); 729 } else if ($selectedCheckbox.is($gratitudeCheckbox)) { 730 // $gratitudeDescription.show(); 731 $addEcardBtn.hide(); 732 $tributeNameInput.val(''); 733 $deptSelect.show(); 734 } 735 } else { 736 // If unchecked, update aria and hide the info container and related description. 737 $selectedCheckbox.attr('aria-checked', 'false'); 738 $tributeInfo.hide(); 739 $tributeNameInput.val(''); 740 $tributeDeptInput.val('autre'); 741 // if ($selectedCheckbox.is($honorCheckbox)) { 742 // $honorDescription.hide(); 743 // } else if ($selectedCheckbox.is($memoriamCheckbox)) { 744 // $memoriamDescription.hide(); 745 // } else if ($selectedCheckbox.is($gratitudeCheckbox)) { 746 // $gratitudeDescription.hide(); 747 // } 748 } 749 } 750 751 function initializeARIA() { 752 $dedicatedCheckbox.attr('aria-checked', $dedicatedCheckbox.is(':checked') ? 'true' : 'false'); 753 $honorCheckbox.attr('aria-checked', $honorCheckbox.is(':checked') ? 'true' : 'false'); 754 $memoriamCheckbox.attr('aria-checked', $memoriamCheckbox.is(':checked') ? 'true' : 'false'); 755 $gratitudeCheckbox.attr('aria-checked', $gratitudeCheckbox.is(':checked') ? 'true' : 'false'); 756 } 757 758 $dedicatedCheckbox.on('change', function () { 759 updateTributeChoiceUI($dedicatedCheckbox, $tributeOptions); 760 }); 761 762 $honorCheckbox.on('change', function () { 763 updateTributeOptionUI($honorCheckbox); 764 }); 765 766 $memoriamCheckbox.on('change', function () { 767 updateTributeOptionUI($memoriamCheckbox); 768 }); 769 770 $gratitudeCheckbox.on('change', function () { 771 updateTributeOptionUI($gratitudeCheckbox); 772 }); 773 774 initializeARIA(); 775 } 776 777 function handleDonationTypeInteractions() { 778 const $donationTypeButtons = $('.donation-type-btn'); 779 const $donationTypeInput = $('#donation-type'); 780 const $personalDonationFields = $('#personal-donation-fields'); 781 const $companyDonationFields = $('#company-donation-fields'); 782 const $companyNameFields = $('#company-name'); 783 const $companyEmailFields = $('#company-email'); 784 785 function updateUI(donationType) { 786 if (donationType === 'personal') { 787 $companyDonationFields.hide(); 788 $companyNameFields.removeAttr('required'); 789 $companyEmailFields.removeAttr('required'); 790 } else if (donationType === 'company') { 791 $companyDonationFields.show(); 792 $companyNameFields.attr('required', 'True'); 793 $companyEmailFields.attr('required', 'True'); 794 } else { 795 console.warn(`Type de don non géré: ${donationType}`); 796 797 } 798 } 799 800 function setActiveButton($activeButton) { 801 $donationTypeButtons.removeClass('donation-type-btn--active').attr('aria-pressed', 'false'); 802 $activeButton.addClass('donation-type-btn--active').attr('aria-pressed', 'true'); 803 } 804 805 $donationTypeButtons.each(function () { 806 const $button = $(this); 807 const isActive = $button.hasClass('donation-type-btn--active'); 808 $button.attr('aria-pressed', isActive ? 'true' : 'false'); 809 }); 810 811 $donationTypeButtons.on('click', function () { 812 const $button = $(this); 813 const donationType = $button.data('donation-type'); 814 815 if (!donationType) { 816 console.error('Type de don non défini pour ce bouton.'); 817 818 return; 819 } 820 821 $donationTypeInput.val(donationType);
822 setActiveButton($button); 823 updateUI(donationType); 824 }); 825 826 $donationTypeButtons.on('keypress', function (e) { 827 if (e.key === 'Enter' || e.key === ' ') { 828 e.preventDefault(); 829 $(this).click(); 830 } 831 }); 832 833 const $defaultActiveButton = $donationTypeButtons.filter('.donation-type-btn--active').first(); 834 if ($defaultActiveButton.length) { 835 updateUI($defaultActiveButton.data('donation-type')); 836 } else { 837 const defaultDonationType = 'personal'; 838 $recurrenceButtons.filter(`[data-donation-type="${defaultDonationType}"]`).addClass('donation-type-btn--active').attr('aria-pressed', 'true'); 839 $recurrenceInput.val(defaultDonationType); 840 updateUI(defaultDonationType); 841 } 842 } 843 844 function handleGeneralFeeCovering() { 845 const $coverFeeCheckbox = $('#cover-transaction-fee'); 846 if (!$coverFeeCheckbox.length) { 847 // If doesn't exist, exit the function. 848 return; 849 } 850 const $recurrenceInput = $('#recurrence'); 851 const $donationTotal = $('#donation-total'); 852 const $oneTimeAmountInput = $('#one-time-amount'); 853 const $monthlyAmountInput = $('#monthly-amount'); 854 const $oneTimeAmountPlusFee = $('#one-time-amount-plus-fee'); 855 const $monthlyAmountPlusFee = $('#monthly-amount-plus-fee'); 856 const $donationWithFees = $('.donation-with-fees'); 857 const TRANSACTION_FEE_PERCENTAGE = 3; 858 const TRANSACTION_FEE_CAP = 20; 859 860 function calculateTransactionFee(amount) { 861 const fee = Math.round(((amount * TRANSACTION_FEE_PERCENTAGE) / 100) * 100) / 100; 862 return fee <= TRANSACTION_FEE_CAP ? fee : TRANSACTION_FEE_CAP; 863 } 864 865 function updateDonationTotal() { 866 const isChecked = $coverFeeCheckbox.is(':checked'); 867 const donationType = $recurrenceInput.val(); 868 if (isChecked) { 869 let donationAmount = 0; 870 if (donationType === 'one-time') { 871 donationAmount = parseFloat($oneTimeAmountInput.val()) || 0; 872 } else if (donationType === 'monthly') { 873 donationAmount = parseFloat($monthlyAmountInput.val()) || 0; 874 } 875 const fee = calculateTransactionFee(donationAmount); 876 const totalAmount = donationAmount + fee; 877 $donationWithFees.text(totalAmount.toFixed(2)); 878 $donationTotal.show(); 879 if (donationType === 'one-time') { 880 $oneTimeAmountPlusFee.val(totalAmount.toFixed(2)); 881 $monthlyAmountPlusFee.val(''); 882 } else if (donationType === 'monthly') { 883 $oneTimeAmountPlusFee.val(''); 884 $monthlyAmountPlusFee.val(totalAmount.toFixed(2)); 885 } 886 } else { 887 $donationTotal.hide(); 888 $oneTimeAmountPlusFee.val(''); 889 $monthlyAmountPlusFee.val(''); 890 } 891 } 892 893 function initializeARIA() { 894 $coverFeeCheckbox.attr('aria-checked', $coverFeeCheckbox.is(':checked') ? 'true' : 'false'); 895 } 896 897 $coverFeeCheckbox.on('change', function () { 898 updateDonationTotal(); 899 $(this).attr('aria-checked', this.checked ? 'true' : 'false'); 900 }); 901 902 $oneTimeAmountInput.on('input', function () { 903 if ($coverFeeCheckbox.is(':checked')) { 904 updateDonationTotal(); 905 } 906 }); 907 908 $monthlyAmountInput.on('input', function () { 909 if ($coverFeeCheckbox.is(':checked')) { 910 updateDonationTotal(); 911 } 912 }); 913 914 $recurrenceInput.on('change', function () { 915 if ($coverFeeCheckbox.is(':checked')) { 916 updateDonationTotal(); 917 } 918 }); 919 920 initializeARIA(); 921 updateDonationTotal(); 922 } 923 924 function handleLotoFeeCovering() { 925 const $coverFeeCheckbox = $('#cover-transaction-fee'); 926 if (!$coverFeeCheckbox.length) { 927 // If doesn't exist, exit the function. 928 return; 929 } 930 const $lotoTotalField = $('#product-total--loto'); // Make sure this exists in your HTML 931 const $donationTotal = $('#donation-total'); 932 const $lotoAmountPlusFee = $('#loto-plus-fee'); // Hidden field to store loto total + fee 933 const $donationWithFees = $('.donation-with-fees'); // Or a dedicated display for loto total if needed 934 const TRANSACTION_FEE_PERCENTAGE = 3; 935 const TRANSACTION_FEE_CAP = 20; 936 937 function calculateTransactionFee(amount) { 938 const fee = Math.round(((amount * TRANSACTION_FEE_PERCENTAGE) / 100) * 100) / 100; 939 return fee <= TRANSACTION_FEE_CAP ? fee : TRANSACTION_FEE_CAP; 940 } 941 942 function updateLotoDonationTotal() { 943 if ($coverFeeCheckbox.is(':checked')) { 944 const donationAmount = parseFloat($lotoTotalField.val()) || 0; 945 const fee = calculateTransactionFee(donationAmount); 946 const totalAmount = donationAmount + fee; 947 $donationWithFees.text(totalAmount.toFixed(2)); 948 $lotoAmountPlusFee.val(totalAmount.toFixed(2)); 949 $donationTotal.show(); 950 } else { 951 $lotoAmountPlusFee.val(''); 952 } 953 } 954 955 $lotoTotalField.on('change', updateLotoDonationTotal); 956 $coverFeeCheckbox.on('change', updateLotoDonationTotal); 957 updateLotoDonationTotal(); 958 } 959 960 function handleGolfSelections() { 961 const $fivesomeQty = $('#golf-fivesome-quantity'); 962 const $fivesomeTotalDisplay = $('.sync-golf-total--fivesome'); 963 const $saveFivesome = $('#product-number--golf-fivesome'); 964 const $saveTotal = $('#product-total--golf'); 965 const $golfSummary = $('.golf-summary'); 966 const $golfSummaryText = $('.golf-summary .donation-summary'); 967 968 function updateGolfTotals() { 969 const fivesomeQty = parseInt($fivesomeQty.val(), 10) || 0; 970 const fivesomeTotal = 8000 * fivesomeQty;
971 const allTotal = fivesomeTotal; 972 973 $fivesomeTotalDisplay.text(fivesomeTotal.toFixed(2)); 974 975 $saveFivesome.val(fivesomeQty); 976 $saveTotal.val(allTotal.toFixed(2)); 977 $saveTotal.trigger('change'); 978 979 if (allTotal > 0) { 980 $golfSummaryText.html(sprintf(DonationFormData.golfTemplate, 'Fivesome', fivesomeQty, fivesomeTotal.toFixed(2))); 981 $golfSummary.show(); 982 } else { 983 $golfSummary.hide(); 984 $golfSummaryText.html(''); 985 } 986 } 987 988 $fivesomeQty.on('change', updateGolfTotals); 989 updateGolfTotals(); 990 } 991 992 function handleGolfFeeCovering() { 993 const $coverFeeCheckbox = $('#cover-transaction-fee'); 994 if (!$coverFeeCheckbox.length) { 995 return; 996 } 997 const $golfTotalField = $('#product-total--golf'); 998 const $donationTotal = $('#donation-total'); 999 const $golfAmountPlusFee = $('#golf-plus-fee'); 1000 const $donationWithFees = $('.donation-with-fees'); 1001 const TRANSACTION_FEE_PERCENTAGE = 3; 1002 1003 function calculateTransactionFee(amount) { 1004 return Math.round(((amount * TRANSACTION_FEE_PERCENTAGE) / 100) * 100) / 100; 1005 } 1006 1007 function updateGolfDonationTotal() { 1008 if ($coverFeeCheckbox.is(':checked')) { 1009 const donationAmount = parseFloat($golfTotalField.val()) || 0; 1010 const fee = calculateTransactionFee(donationAmount); 1011 const totalAmount = donationAmount + fee; 1012 $donationWithFees.text(totalAmount.toFixed(2)); 1013 $golfAmountPlusFee.val(totalAmount.toFixed(2)); 1014 $donationTotal.show(); 1015 } else { 1016 $golfAmountPlusFee.val(''); 1017 $donationWithFees.text(''); 1018 $donationTotal.hide(); 1019 } 1020 } 1021 1022 $golfTotalField.on('change', updateGolfDonationTotal); 1023 $coverFeeCheckbox.on('change', updateGolfDonationTotal); 1024 updateGolfDonationTotal(); 1025 } 1026 1027 function handlePauleeSelections() { 1028 const $ticketQty = $('#paulee-ticket-quantity'); 1029 const $ticketTotalDisplay = $('.sync-paulee-total'); 1030 const $saveTicketQty = $('#product-number--paulee-ticket'); 1031 const $saveTotal = $('#product-total--paulee'); 1032 const $pauleeSummary = $('.paulee-summary'); 1033 const $pauleeSummaryText = $('.paulee-summary .donation-summary'); 1034 1035 function updatePauleeTotals() { 1036 const ticketQty = parseInt($ticketQty.val(), 10) || 0; 1037 const ticketTotal = 5000 * ticketQty; 1038 1039 $ticketTotalDisplay.text(ticketTotal.toFixed(2)); 1040 $saveTicketQty.val(ticketQty); 1041 $saveTotal.val(ticketTotal.toFixed(2)); 1042 $saveTotal.trigger('change'); 1043 1044 if (ticketTotal > 0) { 1045 $pauleeSummaryText.html(sprintf(DonationFormData.golfTemplate, 'Billet la Paulée', ticketQty, ticketTotal.toFixed(2))); 1046 $pauleeSummary.show(); 1047 } else { 1048 $pauleeSummary.hide(); 1049 $pauleeSummaryText.html(''); 1050 } 1051 } 1052 1053 $ticketQty.on('change', updatePauleeTotals); 1054 updatePauleeTotals(); 1055 } 1056 1057 function handlePauleeFeeCovering() { 1058 const $coverFeeCheckbox = $('#cover-transaction-fee'); 1059 if (!$coverFeeCheckbox.length) { 1060 return; 1061 } 1062 const $pauleeTotalField = $('#product-total--paulee'); 1063 const $donationTotal = $('#donation-total'); 1064 const $pauleeAmountPlusFee = $('#paulee-plus-fee'); 1065 const $donationWithFees = $('.donation-with-fees'); 1066 const TRANSACTION_FEE_PERCENTAGE = 3; 1067 1068 function calculateTransactionFee(amount) { 1069 return Math.round(((amount * TRANSACTION_FEE_PERCENTAGE) / 100) * 100) / 100; 1070 } 1071 1072 function updatePauleeDonationTotal() { 1073 if ($coverFeeCheckbox.is(':checked')) { 1074 const donationAmount = parseFloat($pauleeTotalField.val()) || 0; 1075 const fee = calculateTransactionFee(donationAmount); 1076 const totalAmount = donationAmount + fee; 1077 $donationWithFees.text(totalAmount.toFixed(2)); 1078 $pauleeAmountPlusFee.val(totalAmount.toFixed(2)); 1079 $donationTotal.show(); 1080 } else { 1081 $pauleeAmountPlusFee.val(''); 1082 $donationWithFees.text(''); 1083 $donationTotal.hide(); 1084 } 1085 } 1086 1087 $pauleeTotalField.on('change', updatePauleeDonationTotal); 1088 $coverFeeCheckbox.on('change', updatePauleeDonationTotal); 1089 updatePauleeDonationTotal(); 1090 } 1091 1092 function handleInvoiceSelections() {
1093 const $invoiceAmount = $('#invoice-amount'); 1094 const $invoiceNumber = $('#invoice-number'); 1095 const $invoiceSummary = $('.invoice-summary'); 1096 const $invoiceSummaryText = $('.invoice-summary .donation-summary'); 1097 const $invoiceAmountPlusFee = $('#invoice-amount-plus-fee'); 1098 1099 function updateInvoiceSummary() { 1100 const amount = parseFloat($invoiceAmount.val()) || 0; 1101 const invoiceNumber = ($invoiceNumber.val() || '').trim(); 1102 1103 if (amount > 0 && invoiceNumber) { 1104 $invoiceSummaryText.html(`Paiement de facture ${invoiceNumber} : ${amount.toFixed(2)} $`); 1105 $invoiceSummary.show(); 1106 } else { 1107 $invoiceSummaryText.html(''); 1108 $invoiceSummary.hide(); 1109 } 1110 1111 if (!$('#cover-transaction-fee').is(':checked')) { 1112 $invoiceAmountPlusFee.val(''); 1113 } 1114 } 1115 1116 $invoiceAmount.on('input blur', updateInvoiceSummary); 1117 $invoiceNumber.on('input blur', updateInvoiceSummary); 1118 updateInvoiceSummary(); 1119 } 1120 1121 function handleInvoiceFeeCovering() { 1122 const $coverFeeCheckbox = $('#cover-transaction-fee'); 1123 if (!$coverFeeCheckbox.length) { 1124 return; 1125 } 1126 const $invoiceAmount = $('#invoice-amount'); 1127 const $donationTotal = $('#donation-total'); 1128 const $invoiceAmountPlusFee = $('#invoice-amount-plus-fee'); 1129 const $donationWithFees = $('.donation-with-fees'); 1130 const TRANSACTION_FEE_PERCENTAGE = 3; 1131 1132 function calculateTransactionFee(amount) { 1133 return Math.round(((amount * TRANSACTION_FEE_PERCENTAGE) / 100) * 100) / 100; 1134 } 1135 1136 function updateInvoiceDonationTotal() { 1137 const invoiceAmount = parseFloat($invoiceAmount.val()) || 0; 1138 1139 if ($coverFeeCheckbox.is(':checked') && invoiceAmount > 0) { 1140 const fee = calculateTransactionFee(invoiceAmount); 1141 const totalAmount = invoiceAmount + fee; 1142 $donationWithFees.text(totalAmount.toFixed(2)); 1143 $invoiceAmountPlusFee.val(totalAmount.toFixed(2)); 1144 $donationTotal.show(); 1145 } else { 1146 $invoiceAmountPlusFee.val(''); 1147 $donationWithFees.text(''); 1148 $donationTotal.hide(); 1149 } 1150 } 1151 1152 $invoiceAmount.on('input blur', updateInvoiceDonationTotal); 1153 $coverFeeCheckbox.on('change', updateInvoiceDonationTotal); 1154 updateInvoiceDonationTotal(); 1155 } 1156 1157 function handleCommentSection() { 1158 const $addCommentBtn = $('#addCommentBtn'); 1159 const $stepsSection = $('#stepsSection'); 1160 1161 const $commentSection = $('#commentSection'); 1162 const $backCommentBtn = $('#commentSection-backBtn'); 1163 const $saveCommentBtn = $('#commentSection-saveCommentBtn'); 1164 1165 const $userComment = $('#commentSection-userComment'); 1166 const $sharingConsentInputs = $('input[name="sharingConsent"]'); 1167 1168 const $savedUserComment = $('#commentSection-savedUserComment'); 1169 const $savedSharingConsent = $('#commentSection-savedSharingConsent'); 1170 1171 // const $commentExist = $('#hiddenUserComment'); 1172 1173 const MAX_COMMENT_DISPLAY_LENGTH = 20; 1174 1175 const $errorConsentOptions = $('#error-consent-options'); 1176 const $errorUserComment = $('#error-user-comment'); 1177 1178 function initializeARIA() { 1179 $addCommentBtn.attr('aria-expanded', 'false'); 1180 $backCommentBtn.attr('aria-label', 'Retour à la section précédente'); 1181 $saveCommentBtn.attr('aria-label', 'Sauvegarder le message'); 1182 } 1183 1184 function showCommentSection() { 1185 clearErrors(); 1186 $stepsSection.hide(); 1187 $commentSection.show(); 1188 $addCommentBtn.attr('aria-expanded', 'true'); 1189 $userComment.val($savedUserComment.val()); 1190 if ($savedSharingConsent.val()) { 1191 $("input[name=sharingConsent][value=" + $savedSharingConsent.val() + "]").prop('checked', true); 1192 } 1193 1194 } 1195 1196 function hideCommentSection() { 1197 clearErrors(); 1198 $commentSection.hide(); 1199 $stepsSection.show(); 1200 $addCommentBtn.attr('aria-expanded', 'false'); 1201 const commentText = $userComment.val().trim(); 1202 if (commentText === '') { 1203 $addCommentBtn.text('Ajoutez un message'); 1204 // $commentExist.val(false); 1205 $sharingConsentInputs.prop('checked', false); 1206 $savedUserComment.val("") 1207 $savedSharingConsent.val("") 1208 } 1209 } 1210 1211 // function displayError($element, message) { 1212 // // $('.error-message').remove(); 1213 // $('.error-message').val(""); 1214 // const $error = $('.error-message').text(message); 1215 // $element.after($error); 1216 // } 1217 1218 function showError($field, message) { 1219 $field.addClass('error'); 1220 $field.next('.error-message').show(); 1221 $field.next('.error-message').text(message); 1222 } 1223 1224 function clearErrors() { 1225 $('.error-message').hide(); 1226 $('.error-message').text(""); 1227 } 1228 1229 function updateAddCommentBtnText(comment) { 1230 const truncatedComment = comment.length > MAX_COMMENT_DISPLAY_LENGTH 1231 ? comment.slice(0, MAX_COMMENT_DISPLAY_LENGTH) + '...' 1232 : comment; 1233 $addCommentBtn.text(`Votre message : ${truncatedComment}`); 1234 } 1235 1236 $addCommentBtn.on('click', function () { 1237 showCommentSection(); 1238 }); 1239 1240 $backCommentBtn.on('click', function () { 1241 hideCommentSection(); 1242 }); 1243 1244 $saveCommentBtn.on('click', function () { 1245 clearErrors(); 1246 const commentText = $userComment.val().trim(); 1247 const commentConsent = $sharingConsentInputs.filter(':checked').val(); 1248 let hasError = false;
1249 if (commentText === '') { 1250 showError($userComment, 'Entrez un message avant de sauvegarder.'); 1251 hasError = true; 1252 } 1253 if (!commentConsent) { 1254 showError($('#consent-options-group'), 'Choisissez votre type de consentement.'); 1255 hasError = true; 1256 } 1257 if (hasError) { 1258 return; 1259 } 1260 // $commentExist.val(true); 1261 updateAddCommentBtnText(commentText); 1262 $savedUserComment.val(commentText); 1263 $savedSharingConsent.val(commentConsent) 1264 hideCommentSection(); 1265 }); 1266 1267 function init() { 1268 initializeARIA(); 1269 } 1270 1271 init(); 1272 } 1273 1274 function handleEcardSection() { 1275 const $addEcardBtn = $('#addEcardBtn'); 1276 const $stepsSection = $('#stepsSection'); 1277 const $ecardSection = $('#ecardSection'); 1278 const $backEcardBtn = $('#ecardSection-backBtn'); 1279 const $saveEcardBtn = $('#ecardSection-saveEcardBtn'); 1280 const $ecardFrom = $('#ecardSection-from'); 1281 const $ecardUserComment = $('#ecardSection-userMessage'); 1282 const $ecardHideAmount = $('#ecardSection-hide-amount'); 1283 const $ecardRecipientFirstName = $('#ecardSection-recipient-first-name'); 1284 const $ecardRecipientLastName = $('#ecardSection-recipient-last-name'); 1285 const $ecardRecipientEmail = $('#ecardSection-recipient-email'); 1286 const $ecardSavedUserMessage = $('#ecardSection-savedUserMessage'); 1287 const MAX_COMMENT_DISPLAY_LENGTH = 20; 1288 1289 function initializeARIA() { 1290 $addEcardBtn.attr('aria-expanded', 'false'); 1291 $backEcardBtn.attr('aria-label', 'Retour à la section précédente'); 1292 $saveEcardBtn.attr('aria-label', 'Sauvegarder mon message'); 1293 } 1294 1295 function showEcardSection() { 1296 $stepsSection.hide(); 1297 $ecardSection.show(); 1298 $addEcardBtn.attr('aria-expanded', 'true'); 1299 $ecardFrom.focus(); 1300 } 1301 1302 function hideEcardSection() { 1303 $ecardSection.hide(); 1304 $stepsSection.show(); 1305 $addEcardBtn.attr('aria-expanded', 'false'); 1306 const ecardText = $ecardUserComment.val().trim(); 1307 if (ecardText === '') { 1308 $addEcardBtn.text('Je souhaite envoyer une carte éléctronique'); 1309 $ecardSavedUserMessage.val(''); 1310 } 1311 } 1312 1313 function displayError($element, message) { 1314 $element.next('.error-message').remove(); 1315 const $error = $('<div class="error-message"></div>').text(message); 1316 $element.after($error); 1317 } 1318 1319 function clearErrors() { 1320 $('.error-message').remove(); 1321 } 1322 1323 function updateAddEcardBtnText(ecard) { 1324 const truncatedEcard = ecard.length > MAX_COMMENT_DISPLAY_LENGTH 1325 ? ecard.slice(0, MAX_COMMENT_DISPLAY_LENGTH) + '...' 1326 : ecard; 1327 $addEcardBtn.text(`Votre carte éléctronique : ${truncatedEcard}`); 1328 } 1329 1330 function displayConfirmation(message) { 1331 const $confirmation = $('#ecard-confirmation'); 1332 if ($confirmation.length) { 1333 $confirmation.text(message).fadeIn().delay(3000).fadeOut(); 1334 } else { 1335 console.warn('Conteneur de confirmation introuvable.'); 1336 } 1337 } 1338 1339 $addEcardBtn.on('click', function () { 1340 showEcardSection(); 1341 }); 1342 1343 $backEcardBtn.on('click', function () { 1344 hideEcardSection(); 1345 }); 1346 1347 $saveEcardBtn.on('click', function () { 1348 clearErrors(); 1349 const ecardFromVal = $ecardFrom.val().trim(); 1350 const ecardUserCommentVal = $ecardUserComment.val().trim(); 1351 const ecardRecipientFirstNameVal = $ecardRecipientFirstName.val().trim(); 1352 const ecardRecipientLastNameVal = $ecardRecipientLastName.val().trim(); 1353 const ecardRecipientEmailVal = $ecardRecipientEmail.val().trim(); 1354 let hasError = false;
1355 if (ecardFromVal === '') { 1356 displayError($ecardFrom, 'Entrez le nom de l\'expéditeur.'); 1357 hasError = true; 1358 } 1359 if (ecardUserCommentVal === '') { 1360 displayError($ecardUserComment, 'Entrez un message pour votre carte éléctronique.'); 1361 hasError = true; 1362 } 1363 if (ecardRecipientFirstNameVal === '') { 1364 displayError($ecardRecipientFirstName, 'Entrez le prénom du destinataire.'); 1365 hasError = true; 1366 } 1367 if (ecardRecipientLastNameVal === '') { 1368 displayError($ecardRecipientLastName, 'Entrez le nom du destinataire.'); 1369 hasError = true; 1370 } 1371 if (ecardRecipientEmailVal === '') { 1372 displayError($ecardRecipientEmail, 'Entrez le courriel du destinataire.'); 1373 hasError = true; 1374 } else if (!validateEmail(ecardRecipientEmailVal)) { 1375 displayError($ecardRecipientEmail, 'Entrez un courriel valide.'); 1376 hasError = true; 1377 } 1378 if (hasError) { 1379 return; 1380 } 1381 $ecardSavedUserMessage.val(ecardUserCommentVal); 1382 updateAddEcardBtnText(ecardUserCommentVal); 1383 hideEcardSection(); 1384 displayConfirmation('Carte éléctronique sauvegardée avec succès!'); 1385 }); 1386 1387 function validateEmail(email) { 1388 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 1389 return emailRegex.test(email); 1390 } 1391 1392 function init() { 1393 initializeARIA(); 1394 } 1395 1396 init(); 1397 } 1398 1399 function handleEcardImageSelection() { 1400 // When a thumbnail is clicked... 1401 $('.ecard-thumbnail').on('click', function() { 1402 // Remove selected state from all thumbnails 1403 $('.ecard-thumbnail').removeClass('selected'); 1404 // Add selected state to the clicked thumbnail 1405 $(this).addClass('selected'); 1406 // Get the image ID from data attribute 1407 var selectedId = $(this).data('image-id'); 1408 // Set the hidden input's value 1409 $('#selected-ecard-image').val(selectedId); 1410 }); 1411 } 1412 1413 function handleProductSelections() { 1414 // Loop over each product group. 1415 $('.product-line--loto').each(function() { 1416 var $group = $(this); 1417 // Get the product's price from the data attribute. 1418 var itemPrice = $group.data('item-price'); 1419 // Find the select element within this group. 1420 var $select = $group.find('select'); 1421 // Find the target element to update the total. 1422 var $totalDisplay = $group.find('.sync-product-total'); 1423 var $saveNumber = $group.find('.product-number--loto'); 1424 var $saveTotal = $group.find('.product-total--loto'); 1425 1426 var $lotoSummary = $('.loto-summary'); 1427 var $lotoTotalSummary = $('.loto-summary .donation-summary'); 1428 1429 // Attach a change event on the select element. 1430 $select.on('change', function() { 1431 var ticketCount = parseInt($(this).val(), 10); 1432 var total = calculateProductTotalPrice(itemPrice, ticketCount); 1433 $totalDisplay.text(total); 1434 $saveNumber.val(ticketCount); 1435 $saveTotal.val(total); 1436 1437 var pluralSuffix = (ticketCount > 1 ? "s" : ""); 1438 var newText = sprintf(DonationFormData.lotoTemplate, ticketCount, pluralSuffix, total); 1439 $lotoTotalSummary.html(newText); 1440 $lotoSummary.show(); 1441 }); 1442 }); 1443 } 1444 1445 function handleLotoRecurrence() { 1446 var checkbox = $('#product-recurrence-checkbox'); 1447 var saveNumber = $('#product-number--loto'); 1448 checkbox.on('change', function() { 1449 if ($(this).is(':checked')) { 1450 if (saveNumber.val() > 0) { 1451 var recurrenceAmount = (25 * saveNumber.val()); 1452 var total = (175 * saveNumber.val()); 1453 var lotoSummary = $('.loto-summary'); 1454 var lotoTotalSummary = $('.loto-summary .donation-summary'); 1455 var lotoRecurrenceSummary = $('.loto-summary .recurrence-summary'); 1456 1457 lotoTotalSummary.hide(); 1458 1459 var pluralSuffix = (saveNumber.val() > 1 ? "s" : ""); 1460 var newText = sprintf(DonationFormData.lotoRecurrenceTemplate, saveNumber.val(), pluralSuffix, recurrenceAmount, total); 1461 lotoRecurrenceSummary.html(newText); 1462 1463 } else { 1464 lotoTotalSummary.show(); 1465 lotoRecurrenceSummary.hide(); 1466 lotoRecurrenceSummary.html(''); 1467 } 1468 } else { 1469 1470 1471 } 1472 }); 1473 } 1474 1475$(document).ready(function(){ 1476 handleProductSelections(); // your existing function 1477 handleLotoRecurrence(); // our new function to handle the checkbox 1478}); 1479 1480 // Call the function on document ready 1481 $(document).ready(function() { 1482 handleEcardImageSelection(); 1483 }); 1484 1485 return { init }; 1486 })(); 1487 1488 $(document).ready(function() { 1489 FormWizard.InteractionManager.init(); 1490 }); 1491})(jQuery, window.FormWizard = window.FormWizard || {});
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.