1// Multi Step Form Vars (also used for payment calcs/handling when applicable) 2var form = $('#main-submission-form'); 3var is_multi_step_form = ($(form).hasClass('multi-step')?1:0); 4var cur_step = 1; 5var cur_idx = cur_step-1; 6var submit_button = $(form).find('#submit-button'); 7var require_form_captcha = 1; 8 9if($('.phone').length) { 10 $.when(add_js(shared_root+'/js/jquery/jquery.autotab/jquery.autotab-1.1b.js')).done(function() { 11 $("input.phone").closest('.field-wrap').addClass('phone-field-wrap'); 12 $('.phone-field-wrap').each(function() { 13 $(this).find('input').autotab_magic().autotab_filter("numeric"); 14 }); 15 }); 16} 17 18if($('.datepicker').length) { 19 add_css(shared_root+'/css/smoothness/jquery-ui-1.8.custom.css'); 20} 21 22if($('#map_canvas').length || $('.google-address-field').length) { 23 $.when(add_js('//maps.googleapis.com/maps/api/js?key=AIzaSyBhu5ibJC_Df3aYWZW_ryElSDtrQbvg9HA&libraries=places')).done(function() { 24 if($('.google-address-field').length) { 25 $.when( 26 add_js(shared_root+'/js/json/json2.js') 27 ).done(function() { 28 add_js(shared_root+'/js/google-address-lookup-crm.js',1); 29 }); 30 } 31 32 if($('#map_canvas').length) { 33 var map; 34 var marker; 35 36 function initialize() { 37 var myOptions = { 38 zoom: 14, 39 center: new google.maps.LatLng($('#map_canvas').attr('data-latitude'),$('#map_canvas').attr('data-longitude')), 40 mapTypeId: google.maps.MapTypeId.ROADMAP 41 } 42 map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 43 44 marker = new google.maps.Marker({ 45 position: new google.maps.LatLng($('#map_canvas').attr('data-latitude'),$('#map_canvas').attr('data-longitude')), 46 map: map 47 }); 48 } 49 50 initialize(); 51 52 $("#go").click(function() { 53 var start = document.getElementById("start").value; 54 var end = document.getElementById("end").value; 55 56 window.open('https://www.google.com/maps/dir/'+encodeURIComponent(start)+'/'+encodeURIComponent(end),'_blank'); 57 return false; 58 }); 59 60 $("#start").keydown(function(e) { 61 if(e.keyCode==13) { 62 $("#go").click(); 63 } 64 }); 65 } 66 }); 67} 68 69 70/* ----------------------------------------------------------------------------------------------------------------------- */ 71/* Post-Submit Error Auto-Scroll to Form --------------------------------------------------------------------------------- */ 72/* ----------------------------------------------------------------------------------------------------------------------- */ 73if($('.bad-alert').length) { 74 var form_top = $('#main-submission-form').offset().top; 75 76 var header; 77 if($('#header').length) { 78 header = $('#header'); 79 } else if($('.header').length) { 80 header = $('.header'); 81 } 82 if(header && $(header).length && ($(header).css('position') == 'absolute' || $(header).css('position') == 'fixed')) { 83 form_top -= $(header).height(); 84 } 85 if(form_top) { 86 $('body,html').animate({'scrollTop':form_top+'px'},'fast','easeInOutQuad'); 87 } 88} 89 90 91/* ---------------------------------------------------------------------------------------------------------------------- */ 92/* Discount Code Handling ----------------------------------------------------------------------------------------------- */ 93/* ---------------------------------------------------------------------------------------------------------------------- */ 94var discount_type = 'amount'; // or percentage 95var discount_amount = 0; 96$('#apply-discount-code-button').click(function() { 97 var discount_code = $('#discount-code-field').val(); 98 discount_type = 'amount'; 99 discount_amount = 0; 100 101 if(discount_code) { 102 $.ajax({ 103 type: "POST", 104 url: "?check_discount_code="+discount_code, 105 success: function(json,textStatus) { 106 if(json == '0') { 107 $('#discount-code-message').html('<strong class="red">This discount code is not valid.</strong>'); 108 109 } else if(json == '-1') { 110 $('#discount-code-message').html('<strong class="red">You have made too many requests, please wait a while before trying again.</strong>'); 111 112 } else { 113 var data = jQuery.parseJSON(json); 114 $('#discount-code-message').html('<strong class="green" id="discount-amount" data-type="'+data.type+'" data-amount="'+data.amount+'">Valid Code! A discount of '+(data.type=='percentage'?data.amount+'%':'$'+parseFloat(data.amount).toFixed(2))+' will be applied.'); 115 discount_type = data.type; 116 discount_amount = data.amount; 117 } 118 calculate_fees();
119 } 120 }); 121 } else { 122 $('#discount-code-message').html('<strong class="red">This discount code is not valid.</strong>'); 123 calculate_fees(); 124 } 125 126 return false; 127}); 128 129 130/* ----------------------------------------------------------------------------------------------------------------------- */ 131/* Payment Handling ------------------------------------------------------------------------------------------------------ */ 132/* ----------------------------------------------------------------------------------------------------------------------- */ 133/* 134if($('#card-element').length) { 135 var form = $("#main-submission-form"); 136 137 $(form).submit(function() { 138 if($('#per-month').length) { 139 if(confirm('Are you sure you want to submit this form and setup an automatically recurring monthly payment?')) { 140 $('body').append('<div id="form-loading"></div>'); 141 return true; 142 } 143 144 return false; 145 146 } else { 147 $('body').append('<div id="form-loading"></div>'); 148 } 149 }); 150} 151*/ 152 153if($('select[name=payment_method]').find('option').length <= 1) { 154 $("#payment-method-field-wrap").hide(); 155} 156 157$("#payment-method").on('change',function() { 158 $("#stripe-fields").hide().find('.required').addClass('payment-conditionally-required').removeClass('required'); 159 $('#authdotnet-cc-fields, #authdotnet-ach-fields, #card-zip-field-wrap, #bluesnap-cc-fields, #clover-cc-fields').hide().find('.required').addClass('payment-conditionally-required').removeClass('required'); 160 $("#form-section-captcha").show(); 161 require_form_captcha = 1; 162 if($('.captcha-wrap').closest('.field-wrap').length) $('.captcha-wrap').closest('.field-wrap').show(); 163 if(is_multi_step_form) { 164 show_or_hide_multi_step_submit_button() 165 } else { 166 $(submit_button).val("Submit").show(); 167 } 168 $("#non-card-method-field-wrap").hide(); 169 if($('#paypal-button-container').length) $('#paypal-button-container').hide(); 170 if($('#field-wrap-allow-customer-to-pay-for-fees').length) $('#field-wrap-allow-customer-to-pay-for-fees').hide(); 171 172 var amount = get_payment_amount(); 173 174 if(amount) { 175 if($(this).val() == "stripe") { 176 $("#stripe-fields").stop(1,1).fadeIn("fast").find('.payment-conditionally-required').addClass('required'); 177 // $("#form-section-captcha").hide(); 178 // require_form_captcha = 0; 179 // if($('.captcha-wrap').closest('.field-wrap').length) $('.captcha-wrap').closest('.field-wrap').hide(); 180 if($('#field-wrap-allow-customer-to-pay-for-fees').length) $('#field-wrap-allow-customer-to-pay-for-fees').show(); 181 182 } else if ($(this).val() == "paypal") { 183 $(submit_button).val("Submit & Continue to PayPal"); 184 185 } else if ($(this).val() == "paypal_business") { 186 $(submit_button).hide(); 187 // $("#form-section-captcha").hide(); 188 // require_form_captcha = 0; 189 // if($('.captcha-wrap').closest('.field-wrap').length) $('.captcha-wrap').closest('.field-wrap').hide(); 190 if(!$('#paypal_json').length) { 191 $('#main-submission-form').append('<input type="hidden" name="paypal_funding_source" id="paypal_funding_source"></textarea>'); 192 $('#main-submission-form').append('<textarea name="paypal_json" id="paypal_json" style="display: none;"></textarea>'); 193 $('#main-submission-form #form-section-payment-details').append('<div class="paypal-button-container" id="paypal-button-container"></div>'); 194 do_paypal_business_handling(); 195 } 196 $('#paypal-button-container').show(); 197 198 } else if ($(this).val() == "authdotnet") { 199 $("#authdotnet-cc-fields").stop(1,1).fadeIn("fast").find('.payment-conditionally-required').addClass('required'); 200 if($('#field-wrap-allow-customer-to-pay-for-fees').length) $('#field-wrap-allow-customer-to-pay-for-fees').show(); 201 // $("#form-section-captcha").hide(); 202 // require_form_captcha = 0; 203 // if($('.captcha-wrap').closest('.field-wrap').length) $('.captcha-wrap').closest('.field-wrap').hide(); 204 $('#card-zip-field-wrap').hide().find('.required').addClass('payment-conditionally-required').removeClass('required'); 205 206 207 } else if ($(this).val() == "authdotnet_ach") { 208 $("#authdotnet-ach-fields").stop(1,1).fadeIn("fast").find('.payment-conditionally-required').addClass('required');; 209 // $("#form-section-captcha").hide(); 210 // require_form_captcha = 0; 211 // if($('.captcha-wrap').closest('.field-wrap').length) $('.captcha-wrap').closest('.field-wrap').hide(); 212 213 } else if ($(this).val() == "bluesnap") { 214 $("#bluesnap-cc-fields").stop(1,1).fadeIn("fast").find('.payment-conditionally-required').addClass('required'); 215 if($('#field-wrap-allow-customer-to-pay-for-fees').length) $('#field-wrap-allow-customer-to-pay-for-fees').show(); 216 $('#card-zip-field-wrap').show().find('.payment-conditionally-required').removeClass('payment-conditionally-required').addClass('required'); 217 218 } else if ($(this).val() == "clover") { 219 $("#clover-cc-fields").stop(1,1).fadeIn("fast").find('.payment-conditionally-required').addClass('required'); 220 if($('#field-wrap-allow-customer-to-pay-for-fees').length) $('#field-wrap-allow-customer-to-pay-for-fees').show(); 221 222 } else if ($(this).val() == '') { 223 // $(submit_button).hide(); 224 // $("#form-section-captcha").hide(); 225 // if($('.captcha-wrap').closest('.field-wrap').length) $('.captcha-wrap').closest('.field-wrap').hide(); 226 227 } else { 228 $("#non-card-method-field-wrap").show(); 229 } 230 } 231}).change(); 232 233$('#main-submission-form').submit(function() { 234 if($('#payment-method').length && $('#payment-method').val() == 'authdotnet') { 235 $('body').append('<div id="form-loading"></div>'); 236 } 237}); 238 239var original_base_amount = $('#amount').attr('data-base-amount'); 240 241if($('#payment-frequency-selection').length) { 242 var payment_methods_html = $('#payment-method').html(); 243 244 $('.payment-frequency-selection-radio').change(function() { 245 check_recurring_payment_frequency(); 246 }); 247 check_recurring_payment_frequency(); 248 249 function check_recurring_payment_frequency() { 250 $('#amount').attr('data-base-amount',original_base_amount); 251 252 if($('.payment-frequency-selection-radio:checked').length && $('.payment-frequency-selection-radio:checked').val() == 1) { 253 $('.field-wrap-how-often, .field-wrap-recurring-payment-start-date, .field-wrap-recurring-payment-end-date').show(); 254 $('#payment-method option').each(function() { 255 if( 256 $(this).val() != 'stripe' && 257 $(this).val() != 'authdotnet' && 258 $(this).val() != 'bluesnap' && 259 $(this).val() != 'cash' && 260 $(this).val() != 'check' && 261 $(this).val() != 'po' && 262 $(this).val() != 'account' 263 ) { 264 $(this).remove(); 265 } 266 }).change(); 267 268 $('#recurring_payment_interval').change(); 269 } else { 270 var cur_payment_method_val = $('#payment-method').val(); 271 $('#payment-method').html(payment_methods_html).val(cur_payment_method_val).change(); 272 $('.field-wrap-how-often, .field-wrap-recurring-payment-start-date, .field-wrap-recurring-payment-end-date').hide(); 273 } 274 275 calculate_fees();
276 } 277} 278 279$('#recurring_payment_interval').change(function() { 280 if($('.payment-frequency-selection-radio:checked').length && $('.payment-frequency-selection-radio:checked').val() == 1) { 281 var selected_interval = $(this).val(); 282 if($('#recurring_payment_interval option[value="'+selected_interval+'"]').attr('data-price-adjustment')) { 283 $('#amount').attr('data-base-amount',$('#recurring_payment_interval option[value="'+selected_interval+'"]').attr('data-price-adjustment')); 284 } 285 } else { 286 $('#amount').attr('data-base-amount',original_base_amount); 287 } 288 289 $('#amount').html('$'+parseFloat($('#amount').attr('data-base-amount')).toLocaleString('us', {minimumFractionDigits: 2, maximumFractionDigits: 2})); 290 calculate_fees(); 291}).change(); 292 293$('.check-routing-number-helper-link').click(function() { 294 showSoSimpleOverlay($('#check-routing-number-helper-content').html()); 295 return false; 296}); 297 298 299/* ----------------------------------------------------------------------------------------------------------------------- */ 300/* BlueSnap Payment Handling --------------------------------------------------------------------------------------------- */ 301/* ----------------------------------------------------------------------------------------------------------------------- */ 302$(window).on('load',function() { 303 if($('#bluesnap-cc-fields').length) { 304 $.ajax({ 305 type: "GET", 306 url: '?get_bluesnap_token=1&no_template=1', 307 success: function(bluesnap_token,textStatus) { 308 function changeImpactedElement(tagId, removeClass, addClass) { 309 removeClass = removeClass || ""; 310 addClass = addClass || ""; 311 $("[data-bluesnap=" + tagId + "]") 312 .removeClass(removeClass) 313 .addClass(addClass); 314 } 315 var bluesnap_card_url = { 316 "AMEX": "https://files.readme.io/97e7acc-Amex.png", 317 "DINERS": "https://files.readme.io/8c73810-Diners_Club.png", 318 "DISCOVER": "https://files.readme.io/caea86d-Discover.png", 319 "JCB": "https://files.readme.io/e076aed-JCB.png", 320 "MASTERCARD": "https://files.readme.io/5b7b3de-Mastercard.png", 321 "VISA": "https://files.readme.io/9018c4f-Visa.png" 322 }; 323 324 var bsObj = { 325 token: bluesnap_token, 326 onFieldEventHandler: { 327 onFocus: function(tagId) { 328 changeImpactedElement(tagId, "hosted-field-valid hosted-field-invalid", "hosted-field-focus"); 329 }, 330 onBlur: function(tagId) { 331 changeImpactedElement(tagId, "hosted-field-focus"); 332 }, 333 onError: function(tagId, errorCode, errorDescription, eventOrigin) { 334 changeImpactedElement(tagId, "hosted-field-valid hosted-field-focus", "hosted-field-invalid"); 335 $("#" + tagId + "-help").removeClass('helper-text-green').text(errorCode + " - " + errorDescription + " - " + eventOrigin); 336 }, 337 onType: function(tagId, cardType, cardData) { 338 $("#card-logo > img").attr("src", bluesnap_card_url[cardType]); 339 if (null != cardData) { 340 $("#" + tagId + "-help").addClass('helper-text-green').text(JSON.stringify(cardData)); 341 } 342 }, 343 onValid: function(tagId) { 344 changeImpactedElement(tagId, "hosted-field-focus hosted-field-invalid", "hosted-field-valid"); 345 $("#" + tagId + "-help").text(""); 346 } 347 }, 348 style: { 349 // Styling all inputs 350 "input": { 351 "border-style": "solid", 352 "border-width": "1px", 353 "border-color": "#808080", 354 "position": "static", 355 "font-size": "16px", 356 "font-family": "Helvetica Neue,Helvetica,Arial,sans-serif", 357 "line-height": "1.42857143", 358 "color": "#555", 359 "padding": "5px", 360 "height": "auto !important", 361 "width": "220px !important", 362 }, 363 "#cvv": { 364 "width": "100px !important" 365 }, 366 "#exp": { 367 "width": "100px !important" 368 }, 369 ":focus": { 370 "color": "#555" 371 } 372 }, 373 ccnPlaceHolder: "", 374 cvvPlaceHolder: "", 375 expPlaceHolder: "MM / YY" 376 } 377 378 $(document).ready(function() { 379 bluesnap.hostedPaymentFieldsCreate(bsObj); 380 }); 381 382 // Handle form submission. 383 var form = document.getElementById("main-submission-form"); 384 form.addEventListener("submit", function(event) { 385 var amount = get_payment_amount(); 386 387 if(amount > 0) { 388 if($("#payment-method").val() == "bluesnap") { 389 var bluesnap_error = 0; 390 $('.bluesnap-hosted-field-wrap').each(function() { 391 if(!$(this).hasClass('hosted-field-valid')) { 392 bluesnap_error = 1; 393 } 394 });
395 396 if(bluesnap_error) { 397 showAlert('Some of your billing information is invalid.','bad'); 398 399 } else { 400 $("body").append('<div id="form-loading"></div>'); 401 do_blue_snap_initial_submit(); 402 } 403 404 event.preventDefault(); 405 } 406 } 407 }); 408 409 function do_blue_snap_initial_submit() { 410 bluesnap.hostedPaymentFieldsSubmitData( 411 function(callback) { 412 if (null != callback.error) { 413 showAlert("There was a problem processing your card information.","bad"); 414 /* 415 var errorArray = callback.error; 416 for (i in errorArray) { 417 $("#" + errorArray[i].tagId + "-help").text(errorArray[i].errorCode + " - " + errorArray[i].errorDescription); 418 }*/ 419 } else { 420 // var cardData = callback.cardData; 421 422 var form = $('#main-submission-form'); 423 424 // Insert the token ID into the form so it gets submitted to the server 425 // Add Stripe Token to hidden input 426 var hiddenInput = document.createElement("input"); 427 hiddenInput.setAttribute("type", "hidden"); 428 hiddenInput.setAttribute("name", "bluesnap_token"); 429 hiddenInput.setAttribute("value", bluesnap_token); 430 $(form).append(hiddenInput); 431 432 // Submit form 433 $(form).submit(); 434 } 435 } 436 ); 437 } 438 } 439 }); 440 } 441}); 442 443 444/* ----------------------------------------------------------------------------------------------------------------------- */ 445/* Clover Payment Handling ----------------------------------------------------------------------------------------------- */ 446/* ----------------------------------------------------------------------------------------------------------------------- */ 447$(window).on('load',function() { 448 if($('#clover-cc-fields').length) { 449 $.ajax({ 450 type: "GET", 451 url: '?get_clover_api_key=1&no_template=1', 452 success: function(clover_key,textStatus) { 453 if(clover_key == 'ERROR') { 454 console.log('Error getting Clover API Key'); 455 $("#payment-method option[value='clover']").remove(); 456 $('#payment-method').change(); 457 $('#clover-cc-fields').hide(); 458 459 } else { 460 var clover = new Clover(clover_key); 461 var clover_elements = clover.elements(); 462 463 var clover_styles = { 464 body: { 465 fontFamily: "Roboto, Open Sans, sans-serif", 466 fontSize: "16px", 467 }, 468 input: { 469 border: "1px solid #ccc", 470 fontSize: "16px", 471 padding: "10px", 472 height: "auto", 473 width: "auto", 474 } 475 }; 476 477 var clover_form = document.getElementById("main-submission-form"); 478 var cardNumber = clover_elements.create("CARD_NUMBER", clover_styles); 479 var cardDate = clover_elements.create("CARD_DATE", clover_styles); 480 var cardCvv = clover_elements.create("CARD_CVV", clover_styles); 481 var cardPostalCode = clover_elements.create("CARD_POSTAL_CODE", clover_styles); 482 483 cardNumber.mount("#card-number"); 484 cardDate.mount("#card-date"); 485 cardCvv.mount("#card-cvv"); 486 cardPostalCode.mount("#card-postal-code"); 487 488 /* 489 var cardResponse = document.getElementById("card-response"); 490 var displayCardNumberError = document.getElementById("card-number-errors"); 491 var displayCardDateError = document.getElementById("card-date-errors"); 492 var displayCardCvvError = document.getElementById("card-cvv-errors"); 493 var displayCardPostalCodeError = document.getElementById("card-postal-code-errors"); 494 495 cardNumber.addEventListener("change", function(event) { 496 console.log(`cardNumber changed ${JSON.stringify(event)}`); 497 }); 498 499 cardNumber.addEventListener("blur", function(event) { 500 console.log(`cardNumber blur ${JSON.stringify(event)}`); 501 }); 502 503 cardDate.addEventListener("change", function(event) { 504 console.log(`cardDate changed ${JSON.stringify(event)}`); 505 }); 506 507 cardDate.addEventListener("blur", function(event) { 508 console.log(`cardDate blur ${JSON.stringify(event)}`); 509 });
510 511 cardCvv.addEventListener("change", function(event) { 512 console.log(`cardCvv changed ${JSON.stringify(event)}`); 513 }); 514 515 cardCvv.addEventListener("blur", function(event) { 516 console.log(`cardCvv blur ${JSON.stringify(event)}`); 517 }); 518 519 cardPostalCode.addEventListener("change", function(event) { 520 console.log(`cardPostalCode changed ${JSON.stringify(event)}`); 521 }); 522 523 cardPostalCode.addEventListener("blur", function(event) { 524 console.log(`cardPostalCode blur ${JSON.stringify(event)}`); 525 }); 526 */ 527 528 clover_form.addEventListener("submit", function(event) { 529 var amount = get_payment_amount(); 530 531 if(amount > 0) { 532 if($("#payment-method").val() == "clover") { 533 $("body").append('<div id="form-loading"></div>'); 534 535 clover.createToken().then(function(result) { 536 var errors = do_form_validation($(form).find('.required').not('.conditionally-required'),require_captcha=1,do_not_show_errors=1); 537 538 if (result.errors) { 539 Object.values(result.errors).forEach(function (value) { 540 errors += (errors?'<br />':'')+value; 541 }); 542 showAlert(errors,'bad'); 543 $("#form-loading").remove(); 544 545 } else { 546 // Insert the token ID into the form so it gets submitted to the server 547 var clover_form = document.getElementById("main-submission-form"); 548 var hiddenInput = document.createElement("input"); 549 hiddenInput.setAttribute("type", "hidden"); 550 hiddenInput.setAttribute("name", "cloverToken"); 551 hiddenInput.setAttribute("value", result.token); 552 clover_form.appendChild(hiddenInput); 553 clover_form.submit(); 554 } 555 });
556 557 event.preventDefault(); 558 } 559 } 560 }); 561 } 562 } 563 }); 564 } 565}); 566 567 568/* ----------------------------------------------------------------------------------------------------------------------- */ 569/* Signature Pad Handling ------------------------------------------------------------------------------------------------ */ 570/* ----------------------------------------------------------------------------------------------------------------------- */ 571if($('.m-signature-pad').length) { 572 var form_builder_signature_cached_widths = []; 573 var form_builder_signature_cached_images = []; 574 var form_builder_signature_pads = []; 575 $.when(add_js(shared_root+'/js/signature-pad/signature_pad.js')).done(function() { 576 var i = 0; 577 $('.m-signature-pad').each(function() { 578 var wrapper = $(this); 579 var clearButton = $(wrapper).find('.clear'), 580 canvas = $(wrapper).find('canvas')[0], 581 signature = $(wrapper).find('textarea.signature'); 582 583 if($(signature).val()) { 584 var ctx = canvas.getContext("2d"); 585 var image = new Image(); 586 image.onload = function() { 587 ctx.drawImage(image, 0, 0); 588 }; 589 image.src = $(signature).val(); 590 } 591 592 var ratio = Math.max(window.devicePixelRatio || 1, 1); 593 canvas.width = canvas.offsetWidth * ratio; 594 canvas.height = canvas.offsetHeight * ratio; 595 canvas.getContext("2d").scale(ratio, ratio); 596 form_builder_signature_cached_widths[i] = canvas.offsetWidth; 597 window.onresize = resizeSignatureCanvas; 598 599 form_builder_signature_pads[i] = new SignaturePad(canvas,{ 600 onEnd: function() { 601 $(signature).val(canvas.toDataURL()).change(); 602 } 603 }); 604 605 var signaturePad = form_builder_signature_pads[i]; 606 607 $(clearButton).on('click',function() { 608 signaturePad.clear(); 609 $(signature).val('').change(); 610 }); 611 612 i++; 613 }); 614 }); 615 616 // Adjust canvas coordinate space taking into account pixel ratio, 617 // to make it look crisp on mobile devices. 618 // This also causes canvas to be cleared. 619 function resizeSignatureCanvas() { 620 var i = 0; 621 $('.m-signature-pad').each(function() { 622 var wrapper = $(this), 623 canvas = $(wrapper).find('canvas')[0]; 624 625 if(canvas.offsetWidth !== form_builder_signature_cached_widths[i]){ //add 626 if (typeof form_builder_signature_pads[i] != 'undefined') { 627 form_builder_signature_cached_images[i] = form_builder_signature_pads[i].toDataURL("image/png"); 628 } 629 form_builder_signature_cached_widths[i] = canvas.offsetWidth; 630 631 // When zoomed out to less than 100%, for some very strange reason, 632 // some browsers report devicePixelRatio as less than 1 633 // and only part of the canvas is cleared then. 634 var ratio = Math.max(window.devicePixelRatio || 1, 1); 635 canvas.width = canvas.offsetWidth * ratio; 636 canvas.height = canvas.offsetHeight * ratio; 637 canvas.getContext("2d").scale(ratio, ratio); 638 if (typeof form_builder_signature_pads[i] != 'undefined') { 639 form_builder_signature_pads[i].fromDataURL(form_builder_signature_cached_images[i]); // add 640 } 641 } 642 643 i++; 644 }); 645 } 646} 647 648 649/* ----------------------------------------------------------------------------------------------------------------------- */ 650/* Chosen Dropdown Replace Handling (for multi-selects) ------------------------------------------------------------------ */ 651/* ----------------------------------------------------------------------------------------------------------------------- */ 652var chosen_loaded = 0; 653var chosen_loading = 0; 654function do_chosen() { 655 if($('.do-chosen').length) { 656 if(!chosen_loaded) { 657 if(!chosen_loading) { 658 chosen_loading = 1; 659 add_css(shared_root+'/js/jquery/jquery.chosen/chosen.min.css'); 660 $.when(add_js(shared_root+'/js/jquery/jquery.chosen/chosen.jquery.min.js')).done(function() { 661 chosen_loaded = 1; 662 $('.do-chosen').chosen(); 663 664 $('.do-chosen').on('chosen:showing_dropdown', function(event, params) { 665 var chosen_container = $( event.target ).next( '.chosen-container' ); 666 var dropdown = chosen_container.find( '.chosen-drop' ); 667 var dropdown_top = dropdown.offset().top - $(window).scrollTop(); 668 var dropdown_height = dropdown.height(); 669 var viewport_height = $(window).height(); 670 671 if ( dropdown_top + dropdown_height > viewport_height ) { 672 chosen_container.addClass( 'chosen-drop-up' ); 673 } 674 675 }); 676 $('.do-chosen').on('chosen:hiding_dropdown', function(event, params) { 677 $( event.target ).next( '.chosen-container' ).removeClass( 'chosen-drop-up' ); 678 }); 679 }); 680 } 681 } else { 682 $('.do-chosen').each(function(){ 683 $(this).siblings('.chosen-container').css('width', realWidth($(this))); 684 $(this).trigger("chosen:updated"); 685 }); 686 } 687 } 688} 689function kill_chosen() { 690 $(".do-chosen").chosen("destroy"); 691 chosen_loaded = 0; 692 chosen_loading = 0; 693} 694function realWidth($element){ 695 var $clone = $element.clone(); 696 $clone.css({"display":"block","visibility":"hidden"}); 697 $($element).parent('.field-wrap').append($clone); 698 var width = $clone.outerWidth(); 699 $clone.remove(); 700 return width; 701} 702do_chosen(); 703 704 705/* ----------------------------------------------------------------------------------------------------------------------- */ 706/* Conditional Field Handling -------------------------------------------------------------------------------------------- */ 707/* ----------------------------------------------------------------------------------------------------------------------- */ 708if(typeof conditional_field_js_data_arr !== 'undefined') { 709 $.each(conditional_field_js_data_arr, function(conditional_field_id,conditions) { 710 $.each(conditions, function(key,arr) { 711 if($('.field-wrap[data-field-id="'+arr.conditional_field_id+'"]')) { 712 $('.field-wrap[data-field-id="'+arr.conditional_field_id+'"]').addClass('conditional-field-controller') 713 } 714 }); 715 }); 716 717 if($('.conditional-field-controller').length) { 718 $('.conditional-field-controller').each(function() { 719 var controller_field_wrap = $(this); 720 var controller_field_type = $(controller_field_wrap).attr('data-field-type'); 721 var controller_field_id = $(controller_field_wrap).attr('data-field-id'); 722 var controller_html_field_type = controller_field_type; 723 if(controller_html_field_type == 'multiselect') controller_html_field_type = 'select'; 724 if(controller_html_field_type == 'yesno') controller_html_field_type = 'select'; 725 726 if(controller_html_field_type == 'radio' || controller_html_field_type == 'checkbox') { 727 $(controller_field_wrap).find('input').change(function() { 728 do_conditional_field_handling(); 729 }); 730 731 } else { 732 $(controller_field_wrap).find(controller_html_field_type).first().change(function() { 733 do_conditional_field_handling(); 734 }); 735 } 736 }); 737 } 738 739 function check_conditional_status(field_id) { 740 var conditional_field = $('.conditional-field[data-field-id='+field_id+']'); 741 var show_this_field = 0; 742 743 if($(conditional_field).length) { 744 if(typeof conditional_field_js_data_arr[field_id] !== 'undefined') { 745 $.each(conditional_field_js_data_arr[field_id], function(key,arr) { 746 var controller_field_wrap = $('.conditional-field-controller[data-field-id="'+arr.conditional_field_id+'"]'); 747 748 if($(controller_field_wrap).length) { 749 var controller_field_type = $(controller_field_wrap).attr('data-field-type'); 750 var controller_html_field_type = controller_field_type; 751 if(controller_field_type == 'yesno') controller_html_field_type = 'select'; 752 if(controller_field_type == 'multiselect') controller_html_field_type = 'select'; 753 if(controller_field_type == 'checkbox') controller_html_field_type = 'input'; 754 if(controller_field_type == 'radio') controller_html_field_type = 'input'; 755 var controller_field = $(controller_field_wrap).find(controller_html_field_type).first(); 756 757 if($(controller_field).length) { 758 switch(controller_field_type) { 759 case 'select': 760 case 'yesno': 761 if($(controller_field_wrap).find('select').first().val() == arr.conditional_field_option_id) show_this_field = 1; 762 break; 763 764 case 'radio':
765 if($(controller_field_wrap).find('input:checked').length && $(controller_field_wrap).find('input:checked').val() == arr.conditional_field_option_id) show_this_field = 1; 766 break; 767 768 case 'multiselect': 769 if($(controller_field_wrap).find('select').first().find('option:selected').length) { 770 $(controller_field_wrap).find('select').first().find('option:selected').each(function() { 771 if($(this).val() == arr.conditional_field_option_id) show_this_field = 1; 772 }); 773 } 774 break; 775 776 case 'checkbox': 777 if($(controller_field_wrap).find('input:checked').length) { 778 $(controller_field_wrap).find('input:checked').each(function() { 779 if($(this).val() == arr.conditional_field_option_id) show_this_field = 1; 780 }); 781 } 782 break; 783 784 } 785 } 786 } 787 }); 788 789 if(show_this_field) { 790 if($(conditional_field).find('.conditionally-required').length) $(conditional_field).find('.conditionally-required').removeClass('conditionally-required'); 791 $(conditional_field).show(); 792 $(conditional_field).addClass('show-field-conditionally'); 793 794 795 } else { 796 if($(conditional_field).find('.required')) $(conditional_field).find('.required').addClass('conditionally-required'); 797 $(conditional_field).removeClass('show-field-conditionally'); 798 799 switch($(conditional_field).attr('data-field-type')) { 800 case 'radio': 801 case 'checkbox': 802 $(conditional_field).hide().find('input').removeAttr('checked'); 803 break; 804 805 case 'select': 806 case 'multiselect': 807 case 'yesno': 808 $(conditional_field).hide().find('select').first().val(''); 809 break; 810 811 case 'textarea': 812 $(conditional_field).hide().find('textarea').first().val(''); 813 break; 814 815 default: 816 case 'text': 817 $(conditional_field).hide().find('input').first().val(''); 818 break; 819 } 820 } 821 } 822 } 823 824 return false; 825 } 826 827 function do_conditional_field_handling() { 828 $('.conditional-field').each(function() { 829 var field_id = $(this).attr('data-field-id'); 830 check_conditional_status(field_id); 831 }); 832 833 // now show/hide entire section if there are no visible fields 834 $('.form-section').each(function() { 835 var section = $(this); 836 if($(section).find('.field-wrap.conditional-field').length && !$(section).find('.field-wrap').not('.conditional-field').length) { 837 var show_section = 0; 838 $(section).find('.conditional-field').each(function() { 839 if($(this).css('display') !== 'none' || $(this).hasClass('show-field-conditionally')) show_section = 1; 840 }); 841 842 if(show_section) { 843 $(section).show(); 844 } else { 845 $(section).hide(); 846 } 847 } 848 }); 849 850 $(window).resize(); 851 do_chosen(); 852 calculate_fees(); 853 do_checkboxes(); 854 } 855 856 do_conditional_field_handling(); 857} 858 859// form validation 860function do_form_validation(fields,require_captcha,do_not_show_errors) { 861 var error = ''; 862 var validated_radios_and_checkboxes = new Array(); 863 if(!require_form_captcha) require_captcha = 0; 864 865 $('.required').removeClass('error'); 866 867 $(fields).each(function() { 868 var field_type = $(this).prop('nodeName').toLowerCase(); 869 if(field_type == 'input') { 870 if($(this).attr('type') == 'checkbox') field_type = 'checkbox'; 871 if($(this).attr('type') == 'radio') field_type = 'radio'; 872 } 873 874 switch(field_type) { 875 case 'input': 876 case 'select': 877 case 'textarea': 878 default: 879 if(!$(this).val()) { 880 $(this).addClass('error'); 881 var label = $(this).closest('.field-wrap').find('label').html().replace('<em>*</em>',''); 882 error += (error?'<br />':'')+'The Field "'+label+'" is required.'; 883 } 884 break; 885 886 case 'checkbox': 887 case 'radio': 888 var field_name = $(this).attr('name'); 889 890 var already_validated = 0; 891 for(i=0;i<validated_radios_and_checkboxes.length;i++) { 892 if(validated_radios_and_checkboxes[i] == field_name) already_validated = 1; 893 } 894 895 if(!already_validated) { 896 if(!$('input[name="'+field_name+'"]:checked').length) { 897 $(this).addClass('error'); 898 var label = $(this).closest('.field-wrap').find('label').first().html().replace('<em>*</em>',''); 899 error += (error?'<br />':'')+'The Field "'+label+'" is required.'; 900 } 901 902 validated_radios_and_checkboxes.push(field_name); 903 } 904 break; 905 } 906 }); 907 908 // captcha validation 909 if(require_captcha) { 910 if((!is_multi_step_form || (cur_step == step_count)) && $(form).find('.recaptcha_widget').length) { 911 var googleResponse = jQuery('#g-recaptcha-response').val(); 912 if (!googleResponse) error += (error?'<br />':'')+'Please check the "I\'m not a robot" box.'; 913 } 914 } 915 916 // show error message if present 917 if(error && !do_not_show_errors) showAlert(error,'bad'); 918 919 return error; 920} 921 922 923/* ----------------------------------------------------------------------------------------------------------------------- */ 924/* Maintain Partial Submissions (via localstorage) ----------------------------------------------------------------------- */ 925/* ----------------------------------------------------------------------------------------------------------------------- */ 926if($('#main-submission-form').hasClass('maintain-partial-submissions')) { 927 // clear local storage if successful submission cookie is present 928 if($('#main-submission-form').hasClass('clear-existing-partial-submissions')) { 929 localStorage.clear(); 930 } 931 932 if($('#global-cookie-notice').length) $('#global-cookie-notice').hide(); 933 934 $.when(add_js(shared_root+'/js/jquery/jquery.cookie/jquery.cookie.js')).done(function() { 935 // gdpr cookie acceptance 936 if($('#global-cookie-notice').length) { 937 $('#global-cookie-notice').slideDown('slow'); 938 939 $('#global-cookie-notice-button').click(function() { 940 var id = $(this).attr('data-attr-id'); 941 $('#global-cookie-notice').fadeOut('fast',function() { 942 $(this).remove(); 943 }); 944 $.cookie('cookie-consent-'+id,1,{expires: 60, path: '/'}); 945 return false; 946 }); 947 } 948 }); 949 950 var form = $('#main-submission-form'); 951 var key_prefix = 'f'+$(form).attr('data-fid')+'-'; 952 var soft_save_t; 953 954 setTimeout(function() { 955 $('input[type=text], textarea').keyup(function() { do_soft_save(); }); 956 $('input[type=radio], textarea').change(function() { do_soft_save(); }); 957 $('input[type=checkbox]').change(function() { do_soft_save(); }); 958 $('select').change(function() { do_soft_save(); }); 959 }, 1000); 960
961 function do_soft_save() { 962 clearTimeout(soft_save_t); 963 soft_save_t = setTimeout(function() { 964 var postData = {}; 965 var form_data = $(form).serializeArray(); 966 for (var i = 0; i < form_data.length; i++) { 967 if(form_data[i]['name'].indexOf('form_submitted_') >= 0) continue; 968 969 if (form_data[i]['name'].endsWith('[]')) { 970 var name = form_data[i]['name']; 971 // name = name.substring(0, name.length - 2); 972 if (!(name in postData)) { 973 postData[name] = []; 974 } 975 postData[name].push(form_data[i]['value']); 976 977 } else { 978 postData[form_data[i]['name']] = form_data[i]['value']; 979 } 980 } 981 982 $.each(postData,function(key,val) { 983 if(val && val != '') { 984 if(Array.isArray(val)) { 985 val = JSON.stringify(val); 986 } 987 localStorage.setItem(key_prefix+key,val); 988 } 989 }); 990 },1000); 991 } 992 993 var has_partial_submission_data = 0; 994 for (var key in localStorage) { 995 var value = localStorage.getItem(key); 996 var key = key.replace(key_prefix,''); 997 998 if(value != '' && value != '-1') { 999 if($('input[name="'+key+'"]').length) { 1000 var field = $('input[name="'+key+'"]'); 1001 var type = $(field).attr('type'); 1002 1003 if(type == 'checkbox') { 1004 try { 1005 tmp_val = JSON.parse(value); 1006 value = tmp_val; 1007 } catch(e) { 1008 } 1009 1010 $(field).each(function() { 1011 if((typeof value !== 'string' && inArray($(this).val(),value)) || ($(this).val() == value)) { 1012 $(this).prop('checked','checked').change(); 1013 if(key.indexOf('use_google_smart_search') == -1) has_partial_submission_data = 1; 1014 } else { 1015 $(this).prop('checked',false).change(); 1016 } 1017 }); 1018 1019 } else if (type == 'radio') { 1020 $(field).each(function() { 1021 if($(this).val() == value) { 1022 $(this).prop('checked','checked').change(); 1023 } else { 1024 $(this).prop('checked',false).change(); 1025 } 1026 }); 1027 1028 } else { 1029 $(field).val(value); 1030 has_partial_submission_data = 1; 1031 } 1032 1033 } else if($('select[name="'+key+'"]').length) { 1034 var field = $('select[name="'+key+'"]'); 1035 if($(field).attr('multiple')) { 1036 field.find('option').each(function() { 1037 if (value.indexOf($(this).val()) !== -1) { 1038 $(this).prop('selected', true); 1039 } 1040 }); 1041 } else { 1042 $(field).val(value); 1043 } 1044 has_partial_submission_data = 1; 1045 1046 // reinit multi-selects 1047 if(chosen_loaded) kill_chosen(); 1048 do_chosen(); 1049 $(field).change(); 1050 1051 1052 } else if($('textarea[name="'+key+'"]').length) { 1053 var field = $('textarea[name="'+key+'"]'); 1054 $(field).val(value); 1055 has_partial_submission_data = 1; 1056 } 1057 } 1058 } 1059 1060 if(has_partial_submission_data) $('#partial-submissions-notification').show(); 1061 $('#reset-partial-submission-data-button').click(function() { 1062 localStorage.clear(); 1063 var url = window.location.href; 1064 window.location.href = url+(url.indexOf('?') >= 0?'&':'?')+'reset=1'; 1065 return false; 1066 }); 1067} 1068 1069function inArray(needle, haystack) { 1070 var length = haystack.length; 1071 for(var i = 0; i < length; i++) { 1072 if(haystack[i] == needle) return true; 1073 } 1074 return false; 1075} 1076 1077 1078/* ----------------------------------------------------------------------------------------------------------------------- */ 1079/* Multi Step Handling --------------------------------------------------------------------------------------------------- */ 1080/* ----------------------------------------------------------------------------------------------------------------------- */ 1081if(is_multi_step_form) { 1082 // first move captcha 1083 if($('#form-section-captcha').length) { 1084 var target_section = $('#form-section-captcha').prev('.form-section'); 1085 $('#form-section-captcha').contents().appendTo($(target_section)); 1086 $('#form-section-captcha').remove(); 1087 } 1088 1089 // now move send myself a copy field 1090 if($('#send-myself-a-copy-field-wrap').length) { 1091 var target_section = $('#send-myself-a-copy-field-wrap').prev('.form-section'); 1092 $('#send-myself-a-copy-field-wrap').appendTo($(target_section)); 1093 } 1094 1095 var step_count = $(form).find('.form-section').length; 1096 1097 // only initiate if we have more than one section 1098 if(step_count > 1) { 1099 // define submit button and add prev/next buttons 1100 $(submit_button).before('<a href="#" id="multi-step-form-prev" class="button">Back</a> '); 1101 $(submit_button).before('<a href="#" id="multi-step-form-next" class="button">Next</a> '); 1102 1103 // do step initiation function 1104 do_form_step(1); 1105 1106 // add click handling for prev/next step button 1107 $('#multi-step-form-prev').click(function() { 1108 cur_step = cur_step - 1; 1109 cur_idx = cur_step-1; 1110 do_form_step(); 1111 return false; 1112 }); 1113 $('#multi-step-form-next').click(function() { 1114 var has_error = do_step_validation(); 1115 1116 if(!has_error) { 1117 cur_step = cur_step + 1; 1118 cur_idx = cur_step-1; 1119 do_form_step(); 1120 } 1121 1122 return false; 1123 }); 1124 1125 // add keydown/enter handling override 1126 $('input').keydown(function(e) { 1127 if(e.keyCode==13) { 1128 var has_error = do_step_validation(); 1129 1130 if(!has_error) { 1131 $('#multi-step-form-next').click(); 1132 } 1133 1134 return false; 1135 } 1136 }); 1137 1138 // add last step validation (on form submit) 1139 $(form).submit(function() { 1140 if(!$(this).hasClass('paypal-business-submittable')) { 1141 var has_error = do_step_validation(); 1142 if(has_error) return false; 1143 } 1144 }); 1145 } 1146 1147 // main function to init each step 1148 function do_form_step(is_init=false) { 1149 // hide all sections but current 1150 $(form).find('.form-section').hide(); 1151 $(form).find('.form-section').eq(cur_idx).show(); 1152 1153 // add counter to top of form, step cur step 1154 if(!$('#form-step-counter').length) $(form).prepend('<h3 class="form-step-counter" id="form-step-counter">Step <span id="form-step-counter-current">'+cur_step+'</span>
1154 of '+step_count+'</h3>'); 1155 $('#form-step-counter-current').html(cur_step); 1156 1157 show_or_hide_multi_step_submit_button(); 1158 1159 // scroll back to top of form 1160 if(!is_init) { 1161 var scroll_to_top_amount = $(form).offset().top - 50;; 1162 if($('#header').length) { 1163 if($('#header').css('position') == 'fixed') scroll_to_top_amount -= $('#header').height(); 1164 } else if($('.header').length) { 1165 if($('.header').css('position') == 'fixed') scroll_to_top_amount -= $('.header').height(); 1166 } 1167 $('html,body').animate({'scrollTop':scroll_to_top_amount+'px'},'fast'); 1168 } 1169 1170 // fire window resize to reinit signature pad if present 1171 $(window).resize(); 1172 1173 // do payment method select handling 1174 if($("#payment-method").length) $("#payment-method").change(); 1175 1176 // reinit multi-selects 1177 if(chosen_loaded) kill_chosen(); 1178 do_chosen(); 1179 } 1180 1181 function do_step_validation() { 1182 return do_form_validation($(form).find('.form-section').eq(cur_idx).find('.required').not('.conditionally-required'),1); 1183 } 1184} 1185 1186function show_or_hide_multi_step_submit_button() { 1187 // show/hide prev/next buttons based on current step 1188 if(cur_step == 1) { 1189 $('#multi-step-form-prev').hide(); 1190 $('#multi-step-form-next').show(); 1191 $(submit_button).hide(); 1192 1193 } else if(cur_step == step_count) { 1194 $('#multi-step-form-prev').show(); 1195 $('#multi-step-form-next').hide(); 1196 1197 // reinit recaptcha if present 1198 if($('.cf-turnstile').length) { 1199 if (window.turnstile && typeof turnstile.reset === 'function') { 1200 // reset the first widget on the page 1201 turnstile.reset(0); // 0 is the first widget 1202 } 1203 } 1204 1205 $(submit_button).show(); 1206 1207 } else { 1208 $('#multi-step-form-prev').show(); 1209 $('#multi-step-form-next').show(); 1210 $(submit_button).hide(); 1211 } 1212} 1213 1214 1215/* ----------------------------------------------------------------------------------------------------------------------- */ 1216/* JS Client Side Validation --------------------------------------------------------------------------------------------- */ 1217/* ----------------------------------------------------------------------------------------------------------------------- */ 1218if(!is_multi_step_form && $(form).find('input[type=file]').length) { 1219 $(form).submit(function() { 1220 var has_error = do_form_validation($(form).find('.required').not('.conditionally-required'),1); 1221 if(has_error) return false; 1222 }); 1223} 1224 1225 1226/* ----------------------------------------------------------------------------------------------------------------------- */ 1227/* Price Adjustment Field Handling --------------------------------------------------------------------------------------- */ 1228/* ----------------------------------------------------------------------------------------------------------------------- */ 1229if($('.price-adjustment-field').length && $('#amount').length && (typeof field_option_prices_arr !== "undefined" || $('.usd-field.price-adjustment-field').length)) { 1230 $('.price-adjustment-field').change(function() { 1231 calculate_fees(); 1232 }); 1233 $('.usd-field.price-adjustment-field').keyup(function() { 1234 calculate_fees(); 1235 }); 1236 $('.usd-field.price-adjustment-field').keydown(function() { 1237 calculate_fees(); 1238 }); 1239} 1240 1241 1242/* ----------------------------------------------------------------------------------------------------------------------- */ 1243/* Customer Paying Fee Handling ------------------------------------------------------------------------------------------ */ 1244/* ----------------------------------------------------------------------------------------------------------------------- */ 1245if($('#will_pay_fees').length) { 1246 $('#will_pay_fees').change(function() { 1247 calculate_fees(); 1248 }); 1249 calculate_fees(); 1250} 1251 1252$('#simple_payment_amount-field').keyup(function() { 1253 calculate_fees(); 1254}); 1255 1256 1257function get_payment_amount() { 1258 if($('#simple_payment_amount-field').length) { 1259 var amount = parseFloat($('#simple_payment_amount-field').val().replace(',','').replace('$','')); 1260 1261 } else { 1262 var amount = parseFloat($('#amount').attr('data-base-amount')); 1263 if(isNaN(amount)) amount = 0; 1264 1265 if($('.price-adjustment-field').length && $('#amount').length && (typeof field_option_prices_arr !== "undefined" || $('.usd-field.price-adjustment-field').length)) { 1266 $('.price-adjustment-field').each(function() { 1267 if(!$(this).closest('.field-wrap').hasClass('conditional-field') || ($(this).closest('.field-wrap').hasClass('conditional-field') && $(this).closest('.field-wrap').css('display') != 'none')) { 1268 var field_name = $(this).attr('name').replace('[]',''); 1269 1270 var type = $(this)[0].nodeName.toLowerCase(); 1271 switch(type) { 1272 case 'select': 1273 if($(this).attr('multiple')) { 1274 var val = $(this).val(); 1275 if(val) { 1276 for(i=0;i<val.length;i++) { 1277 if(typeof field_option_prices_arr[field_name] !== "undefined" && typeof field_option_prices_arr[field_name][val[i]] !== "undefined") { 1278 amount += parseFloat(field_option_prices_arr[field_name][val[i]].toString().replace(',','')); 1279 } 1280 } 1281 } 1282 } else { 1283 var val = $(this).val(); 1284 if(val) { 1285 if(typeof field_option_prices_arr[field_name] !== "undefined" && typeof field_option_prices_arr[field_name][val] !== "undefined") { 1286 amount += parseFloat(field_option_prices_arr[field_name][val].toString().replace(',','')); 1287 } 1288 } 1289 } 1290 break; 1291 1292 case 'input': 1293 if($(this).attr('type') == 'checkbox' || $(this).attr('type') == 'radio') { 1294 if($(this).is(':checked')) { 1295 var val = $(this).val(); 1296 if(val) { 1297 if(typeof field_option_prices_arr[field_name] !== "undefined" && typeof field_option_prices_arr[field_name][val] !== "undefined") { 1298 amount += parseFloat(field_option_prices_arr[field_name][val].toString().replace(',','')); 1299 } 1300 } 1301 } 1302 } 1303 1304 if($(this).hasClass('usd-field')) { 1305 var val = parseFloat($(this).val().replace(',','')); 1306 if(val > 0) amount += parseFloat(val); 1307 } 1308 break; 1309 } 1310 } 1311 }); 1312 } 1313 1314 // discount code 1315 if(amount > 0 && discount_type && discount_amount > 0) { 1316 var discount = 0; 1317 if(discount_type == 'percentage') { 1318 discount = amount * (discount_amount/100); 1319 } else { 1320 discount = discount_amount; 1321 } 1322 amount -= discount; 1323 } 1324 1325 if(amount <= 0) amount = 0; 1326
1327 $('#amount').html('$'+amount.toLocaleString('us', {minimumFractionDigits: 2, maximumFractionDigits: 2})); 1328 1329 var amount = parseFloat($('#amount').text().replace(',','').replace('$','')); 1330 } 1331 if(isNaN(amount)) amount = 0; 1332 return amount; 1333} 1334 1335if(typeof stripe !== 'undefined' && stripe !== null) { 1336 // one time stripe payment, allows for card, google pay or apple pay if the client has them enabled 1337 if(stripe_payment_frequency == 0 && enable_google_and_apple_pay == 1) { 1338 let elements; 1339 let stripePaymentElementOptions; 1340 let stripePaymentElement; 1341 1342 function updateStripePaymentElement() { 1343 if (typeof stripePaymentElement !== 'undefined') { 1344 stripePaymentElement.unmount(); // Use unmount() to remove the existing instance 1345 } 1346 1347 amount = get_payment_amount(); 1348 1349 if(amount > 0) { 1350 const options = { 1351 mode: 'payment', 1352 amount: amount*100, // in cents for stripe 1353 currency: 'usd', 1354 paymentMethodCreation: 'manual', 1355 paymentMethodTypes: ['card'], 1356 appearance: { 1357 theme: 'flat' 1358 }, 1359 }; 1360 1361 // Set up Stripe.js and Elements to use in checkout form 1362 elements = stripe.elements(options); 1363 1364 // Create and mount the Payment Element 1365 stripePaymentElementOptions = { layout: 'tabs' }; 1366 stripePaymentElement = elements.create('payment', stripePaymentElementOptions); 1367 stripePaymentElement.mount('#stripe-payment-element'); 1368 } 1369 } 1370 1371 updateStripePaymentElement(); 1372 1373 document.getElementById('main-submission-form').addEventListener('submit', async (event) => { 1374 if($('#payment-method').length && $('#payment-method').val() != 'stripe') { 1375 1376 } else { 1377 amount = get_payment_amount(); 1378 if(amount > 0) { 1379 event.preventDefault(); 1380 1381 document.getElementById('submit-button').disabled = true; // Disable the button to prevent duplicate submissions 1382 1383 const {error: submitError} = await elements.submit(); 1384 if (submitError) { 1385 console.log(submitError); 1386 document.getElementById('stripe-error-message').textContent = submitError.message; 1387 document.getElementById('submit-button').disabled = false; // Re-enable the button 1388 return; 1389 } 1390 1391 const {error, confirmationToken} = await stripe.createConfirmationToken({ 1392 elements, 1393 params: { 1394 return_url: window.location.href, 1395 } 1396 }); 1397 1398 if (error) { 1399 document.getElementById('stripe-error-message').textContent = error.message; 1400 document.getElementById('submit-button').disabled = false; // Re-enable the button 1401 return; 1402 } 1403 1404 if(confirmationToken && confirmationToken.id) { 1405 // Add the paymentIntent ID to the form 1406 const hiddenInput = document.createElement('input'); 1407 hiddenInput.type = 'hidden'; 1408 hiddenInput.name = 'stripeConfirmationToken'; 1409 hiddenInput.value = confirmationToken.id; 1410 document.getElementById('main-submission-form').appendChild(hiddenInput); 1411 1412 // Submit the form to the server 1413 document.getElementById('submit-button').disabled = false; 1414 document.getElementById('main-submission-form').submit(); 1415 } else { 1416 document.getElementById('stripe-error-message').textContent = 'Unable to retrieve confirmation token. Please try again.'; 1417 document.getElementById('submit-button').disabled = false; // Re-enable the button 1418 return false; 1419 } 1420 } 1421 } 1422 }); 1423 1424 // recurring or user selectable frequency, credit card only 1425 } else { 1426 // Create an instance of Elements. 1427 var elements = stripe.elements(); 1428 1429 // Custom styling can be passed to options when creating an Element. 1430 // (Note that this demo uses a wider set of styles than the guide below.) 1431 var style = { 1432 base: { 1433 color: "#32325d", 1434 lineHeight: "18px", 1435 fontFamily: "'Helvetica Neue', Helvetica, sans-serif", 1436 fontSmoothing: "antialiased", 1437 fontSize: "16px", 1438 "::placeholder": { 1439 color: "#aab7c4" 1440 } 1441 }, 1442 invalid: { 1443 color: "#fa755a", 1444 iconColor: "#fa755a" 1445 } 1446 }; 1447 1448 // Create an instance of the card Element. 1449 var card = elements.create("card", {style: style}); 1450 1451 // Add an instance of the card Element into the `card-element` <div>. 1452 card.mount("#card-element"); 1453
1454 // Handle real-time validation errors from the card Element. 1455 card.addEventListener("change", function(event) { 1456 var displayError = document.getElementById("card-errors"); 1457 if (event.error) { 1458 displayError.textContent = event.error.message; 1459 } else { 1460 displayError.textContent = ""; 1461 } 1462 }); 1463 1464 // Handle form submission. 1465 var form = document.getElementById("main-submission-form"); 1466 form.addEventListener("submit", function(event) { 1467 var amount = get_payment_amount(); 1468 1469 if(amount > 0) { 1470 if($("#payment-method").val() == "stripe") { 1471 if(stripe_payment_frequency != 0) { 1472 if($('.payment-frequency-selection-radio:checked').length && $('.payment-frequency-selection-radio:checked').val() == 1) { 1473 if(confirm("Are you sure you want to submit this form and setup an automatically recurring "+$('#recurring_payment_interval').val()+" payment?")) { 1474 $("body").append('<div id="form-loading"></div>'); 1475 } else { 1476 event.stopPropagation(); 1477 event.preventDefault(); 1478 return false; 1479 } 1480 1481 } else { 1482 if($("#per-month").length) { 1483 if(confirm("Are you sure you want to submit this form and setup an automatically recurring monthly payment?")) { 1484 $("body").append('<div id="form-loading"></div>'); 1485 } else { 1486 event.stopPropagation(); 1487 event.preventDefault(); 1488 return false; 1489 } 1490 } else { 1491 $("body").append('<div id="form-loading"></div>'); 1492 } 1493 } 1494 } 1495 1496 event.preventDefault(); 1497 1498 var card_name = document.getElementById("card-name").value; 1499 stripe.createToken(card, {name: card_name}).then(function(result) { 1500 if (result.error) { 1501 // Inform the user if there was an error. 1502 var errorElement = document.getElementById("card-errors"); 1503 errorElement.textContent = result.error.message; 1504 $("#form-loading").remove(); 1505 } else { 1506 // Send the token to your server. 1507 stripeTokenHandler(result.token); 1508 } 1509 }); 1510 } 1511 } 1512 }); 1513 1514 // Send Stripe Token to Server 1515 function stripeTokenHandler(token) { 1516 var form = $('#main-submission-form'); 1517 1518 // Insert the token ID into the form so it gets submitted to the server 1519 // Add Stripe Token to hidden input 1520 var hiddenInput = document.createElement("input"); 1521 hiddenInput.setAttribute("type", "hidden"); 1522 hiddenInput.setAttribute("name", "stripeToken"); 1523 hiddenInput.setAttribute("value", token.id); 1524 $(form).append(hiddenInput); 1525 // Submit form 1526 $(form).submit(); 1527 } 1528 } 1529} 1530 1531function calculate_fees() { 1532 var amount = get_payment_amount(); 1533 1534 if($('#will_pay_fees').length) { 1535 if( 1536 ( 1537 $('select[name=payment_method]').val() == 'authdotnet' || 1538 $('select[name=payment_method]').val() == 'bluesnap' || 1539 $('select[name=payment_method]').val() == 'clover' || 1540 $('select[name=payment_method]').val() == 'stripe' 1541 ) && 1542 $('#will_pay_fees').prop('checked') && 1543 !isNaN(amount) && amount > 0 1544 ) { 1545 var desired_net = amount; 1546 var base_fee_percent = 2.9; // stripe percentage fee 1547 var flat_fee = 0.30; // stripe flat fee amount 1548 1549 if($('select[name=payment_method]').val() == 'authdotnet') { 1550 base_fee_percent = 2.9; // auth.net percentage fee 1551 } 1552 if($('select[name=payment_method]').val() == 'clover') { 1553 base_fee_percent = 3.5; // clover percentage fee 1554 flat_fee = 0.10; 1555 } 1556 1557 var amount_to_charge = (desired_net + flat_fee) / (1 - (base_fee_percent/100)); 1558 var calculated_fee = amount_to_charge - desired_net; 1559 $('#subtotal').text(number_format(amount,2)); 1560 $('#fee').text(number_format(calculated_fee,2)); 1561 $('#grand-total').text(number_format(amount_to_charge,2)); 1562 $('#field-wrap-fee-calculation-area').show(); 1563 } else { 1564 $('#field-wrap-fee-calculation-area').hide(); 1565 } 1566 } 1567 1568 if(amount <= 0) { 1569 var hide_payment_methods = 1; 1570 if($('.field-wrap-simple-payment-field > label').length && $('.field-wrap-simple-payment-field > label').text().indexOf('*') >= 0) hide_payment_methods = 0; 1571 if(hide_payment_methods) $('#payment-method-field-wrap, #non-card-method-field-wrap, #stripe-fields, #authdotnet-cc-fields, #authdotnet-ach-fields, #bluesnap-cc-fields, #clover-cc-fields').hide(); 1572 $(submit_button).val("Submit"); 1573 $("#form-section-captcha").show(); 1574 1575 } else { 1576 if($('select[name=payment_method]').find('option').length > 1) $('#payment-method-field-wrap').show(); 1577 $("#payment-method").change(); 1578 } 1579 1580 if (typeof stripe_payment_frequency !== 'undefined' && stripe_payment_frequency == 0 && typeof updateStripePaymentElement === 'function') { 1581 updateStripePaymentElement(); 1582 } 1583} 1584 1585calculate_fees();
1586 1587 1588function number_format (number, decimals, dec_point, thousands_sep) { 1589 // Strip all characters but numerical ones. 1590 number = (number + '').replace(/[^0-9+\-Ee.]/g, ''); 1591 var n = !isFinite(+number) ? 0 : +number, 1592 prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), 1593 sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, 1594 dec = (typeof dec_point === 'undefined') ? '.' : dec_point, 1595 s = '', 1596 toFixedFix = function (n, prec) { 1597 var k = Math.pow(10, prec); 1598 return '' + Math.round(n * k) / k; 1599 }; 1600 // Fix for IE parseFloat(0.55).toFixed(0) = 0; 1601 s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.'); 1602 if (s[0].length > 3) { 1603 s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep); 1604 } 1605 if ((s[1] || '').length < prec) { 1606 s[1] = s[1] || ''; 1607 s[1] += new Array(prec - s[1].length + 1).join('0'); 1608 } 1609 return s.join(dec); 1610} 1611 1612 1613/* ----------------------------------------------------------------------------------------------------------------------- */ 1614/* PayPal for Business / Venmo Button Display Handling and Post Processing ----------------------------------------------- */ 1615/* ----------------------------------------------------------------------------------------------------------------------- */ 1616// documentation https://developer.paypal.com/docs/checkout/standard/integrate/ && https://developer.paypal.com/docs/checkout/pay-with-venmo/integrate/ 1617function do_paypal_business_handling() { 1618 var purchase_units = []; 1619 purchase_units[0] = {}; 1620 purchase_units[0].amount = {}; 1621 purchase_units[0].description = document.title; 1622 purchase_units[0].amount.value = get_payment_amount(); 1623 1624 $('input').keydown(function(e) { 1625 if($('#payment-method').val() == 'paypal_business') { 1626 if(e.keyCode == 13) { 1627 do_form_validation($(form).find('.required').not('.conditionally-required'),0); 1628 return false; 1629 } 1630 } 1631 }); 1632 1633 paypal.Buttons({ 1634 style: { 1635 color: 'gold', 1636 shape: 'rect', 1637 label: 'paypal', 1638 layout: 'vertical', 1639 }, 1640 1641 onInit: function (data, actions) { 1642 //actions.disable(); 1643 1644 // loop through fields an 1645 var form_has_error = do_form_validation($(form).find('.required').not('.conditionally-required'),0,1); 1646 if(form_has_error) { 1647 //actions.disable(); 1648 } else { 1649 //actions.enable(); 1650 } 1651 }, 1652 1653 onClick: function (data) { 1654 $('#paypal_funding_source').val(data.fundingSource); 1655 purchase_units[0].amount.value = get_payment_amount(); 1656 var form_has_error = do_form_validation($(form).find('.required').not('.conditionally-required'),0); 1657 if(form_has_error) { 1658 return false; 1659 } 1660 }, 1661 1662 createOrder: function (data, actions) { 1663 purchase_units[0].amount.value = get_payment_amount(); 1664 1665 return actions.order.create({ 1666 purchase_units: purchase_units, 1667 }); 1668 }, 1669 1670 onApprove: function (data, actions) { 1671 return actions.order.capture().then(function (orderData) { 1672 // Full available details 1673 // console.log('Capture result', orderData, JSON.stringify(orderData, null, 2)); 1674 1675 // Show a success message within this page, e.g. 1676 const element = document.getElementById('paypal-button-container'); 1677 element.innerHTML = ''; 1678 element.innerHTML = '<h3>Thank you for your payment!</h3>'; 1679 1680 // Or go to another URL: actions.redirect('thank_you.html'); 1681 document.getElementById('paypal_json').value = JSON.stringify(orderData, null, 2); 1682 $('#main-submission-form').addClass('paypal-business-submittable').submit(); 1683 }); 1684 }, 1685 1686 onCancel: function(data, actions) { 1687 }, 1688 1689 onError: function (err) { 1690 // console.log(err); 1691 } 1692 }).render('#paypal-button-container'); 1693}
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.