1/** 2 * @author Softped Development Team <[email protected]> 3 */ 4jQuery.namespace( 'SS.com.Contributions.frontend.form' ); 5 6/** 7 * Control the checkout page form 8 * @param config - Array('loggedIn','personId','form','reviewUrl') 9 * @constructor 10 */ 11 12SS.com.Contributions.frontend.form.Payment = function( config ){ 13 var me = this; 14 this.config = config; 15 this.form = $('form[name="' + this.config.form + '"]'); 16 this.formHelper = this.form.data('formHelper'); 17 18 this.formHelper.options.errorMessages.required = __d('contributions','This field is required'); 19 this.formHelper.options.errorMessages.minlength = __d('contributions','This field must have at least {minLength} characters in length'); 20 this.formHelper.options.errorMessages.maxlength = __d('contributions','This field must have maximum {maxLength} characters in length'); 21 this.formHelper.options.errorMessages.email = __d('contributions','This email is not a valid email address'); 22 this.formHelper.options.errorMessages.phone = __d('contributions','This is not a valid US phone number'); 23 this.formHelper.options.errorMessages.number = __d('contributions','This field must contain only numbers'); 24 this.formHelper.options.errorMessages.cardNumber = __d('contributions','This is not a valid card number'); 25 26 this.init(); 27 28 SS.com.Contributions.frontend.form.instance = this; 29}; 30 31SS.com.Contributions.frontend.form.Payment.prototype = { 32 33 /** 34 * Init event listeners 35 */ 36 init: function() 37 { 38 var me = this; 39 40 this.formHelper.options.customErrorMessages = { 41 required: { 42 'person[title]': __d('contributions','Title is requried'), 43 'person[title_display]': __d('contributions','Title is requried') 44 } 45 }; 46 47 this.transparentRedirectWrapperInstances = {}; 48 49 // toggle payment type panels 50 this.form.find('input[name="payment[type]"]').on('change',function(){ 51 me.togglePaymentType(); 52 }); 53 54 // toggle organization information panels 55 this.form.find('input[name="group[yes]"]').on('change', function () { 56// me.toggleOrganizationInformation( $(this) ); 57 me.toggleOrganizationSelector($(this)); 58 }); 59 60 this.form.find('input[name="alternate_organization"]').on('change', function () { 61 me.toggleAlternateOrganizationSelector($(this)); 62 }); 63 64 var organizationField = this.form.find('input[name="group[id_display]"]'); 65 organizationField.data('validator',function(field){ 66 var panel = me.form.find('.form-panel-organization' ); 67 if( !panel.is(':visible') ){ 68 var combo = $(field).closest('.form-input-wrapper'); 69 var valueField = combo.find('input[type="hidden"]'); 70 if(valueField.val()==''){ 71 return __d('contributions','Select or add an Organization') 72 } 73 } 74 return false; 75 }); 76 77 var confirmEmailField = this.form.find('input[name="person[confirm_email]"]'); 78 confirmEmailField.data('validator',function(field){ 79 var emailField = me.form.find('input[name="person[email]"]'); 80 81 if(emailField.val()!=$(field).val()){ 82 return __d('contributions','Emails do not match') 83 } 84 return false; 85 }); 86 87 // toggle tribute options panel 88 this.form.find('input[name="tribute[is_tribute]"]').on('change',function(){ 89 me.toggleTributeOptions( $(this) ); 90 }); 91 92 // toggle tribute recipient panel 93 this.form.find('input[name="tribute[has_recipient]"]').on('change',function(){ 94 me.toggleTributeRecipient( $(this) ); 95 }); 96 97 // toggle recurring options panels and set the payment type to card 98 this.form.find('input[name="is_recurring"]').on('change', function () { 99 100 var updateCart = true; 101 var noSync = $(this).data('noSync'); 102 103 if (noSync) { 104 updateCart = false;
105 } 106 107 me.toggleRecurringOptions($(this), updateCart); 108 }); 109 110 this.form.find('input[name="recurring[start_date_display]"]').on('change',function(a,b){ 111 112 var minEndDate = $(this).datepicker('getDate'); 113 114 $(this).data('originalDate',new Date(minEndDate)); 115 116 minEndDate.setDate(minEndDate.getDate()+1); 117 118 var endDateField = me.form.find('input[name="recurring[end_date_display]"]'); 119 endDateField.datepicker("option", "minDate",minEndDate); 120 121 }) 122 123 if ((this.config.cart && this.config.cart.recurring) || 124 (this.config.forceRecurring)) { 125 this.form.find('input[name="is_recurring"]').prop('checked', true); 126 this.toggleRecurringOptions(null, false); 127 } 128 129 this.form.find('input[name="recurring[type]"]').on('change',function(){ 130 SS.com.Contributions.frontend.CartSummary.addRecurringToCart(null, $(this).val()); 131 }); 132 133 $(window).on('setRecurring',function(event,recurring){ 134 135 if(me.config.forceRecurring){ 136 return; 137 } 138 139 var recurringBox = me.form.find('input[name="is_recurring"]'); 140 141 var checked = recurringBox.prop('checked'); 142 143 if(checked!=recurring){ 144 recurringBox.data('noSync',1); 145 recurringBox.prop('checked',recurring).change(); 146 recurringBox.removeData('noSync'); 147 } 148 }) 149 150 this.form.find('.change-default-country a.form-field-button').on('click',function () { 151 152 $(this).closest('.change-default-country').find('input[name="address[location_country_id]"]').attr('disabled','disabled').data('force-disable',1); 153 $(this).closest('.change-default-country').find('input[name="group[address][location_country_id]"]').attr('disabled','disabled').data('force-disable',1); 154 $(this).closest('.change-default-country').hide(); 155 156 var addressWrapper = $(this).closest('.default-country.hide-country'); 157 addressWrapper.removeClass('hide-country'); 158 addressWrapper.find('.location-country-field').removeClass('form-disabled').find('select').data('force-disable',null).removeAttr('disabled'); 159 }) 160 161 // toggle register options panels 162// this.form.find('input[name="register"]').on('change',function(){ 163// me.toggleRegisterOptions( $(this) ); 164// }); 165 166 // show/hide new card panel for logged users when Add New button is clicked 167 this.form.find('select[name="payment[id]"]').parent('.form-input-holder').find('.form-field-button').on('click',function(){ 168 me.toggleAddCardOrCheck( $(this) ); 169 me.toggleText($(this),__d('contributions','Cancel'),$(this).data('add-new-text')); 170 return false; 171 }); 172 // hide new card panel if any value was set on cards drop down 173 this.form.find('select[name="payment[id]"]').on('change',function(){ 174 if( $(this).val() ){ 175 me.formHelper.allowBlank( $(this), false ); 176 me.formHelper.hidePanel( me.form.find('.form-panel-card') ); 177 me.formHelper.hidePanel( me.form.find('.form-panel-check') ); 178 me.formHelper.hidePanel( me.form.find('.form-panel-custom-method') ); 179 me.formHelper.hidePanel( me.form.find('.form-panel-payment-type') ); 180 me.formHelper.hidePanel( me.form.find('.billing-information') ); 181 if( me.form.find('.form-panel-card').is(':visible') || me.form.find('.form-panel-check').is(':visible') || me.form.find('.form-panel-custom-method').is(':visible')){ 182 var addNewButton = me.form.find('select[name="payment[id]"]').parent('.form-input-holder').find('.form-field-button'); 183 me.toggleText( addNewButton,'Cancel',addNewButton.data('add-new-text') ); 184 } 185 me.toggleTransferFee(); 186 me.toggleStoreOption(); 187 } 188 }); 189 // select a month when a number is pressed while month field is focused 190 this.monthKeyString = ''; 191 this.monthTimer = ''; 192 this.form.find('select[name="payment[card][expiration_month]"]').on('keypress',function(event){ 193 var monthField = $(this); 194 var pressedKey = String.fromCharCode(event.which); 195 if(pressedKey.match(/[0-9]/)){ 196 me.monthKeyString += pressedKey; 197 } 198 if(me.monthTimer){ 199 clearTimeout(me.monthTimer); 200 } 201 me.monthTimer = setTimeout(function(){ 202 if(parseInt(me.monthKeyString) >= 1 && parseInt(me.monthKeyString) <= 12){ 203 me.monthKeyString = me.padNumber(me.monthKeyString, 2); 204 monthField.val(me.monthKeyString); 205 } 206 me.monthKeyString = ''; 207 },300); 208 }); 209 210 // show/hide new address panel for logged users when Add New button is clicked 211 this.form.find('select[name="address[id]"]').parent('.form-input-holder').find('.form-field-button').on('click',function(){ 212 me.toggleAddAddress( $(this) ); 213 me.toggleText($(this),__d('contributions','Cancel'),__d('contributions','Add New')); 214 return false;
215 }); 216 // hide new address panel if any value was set on cards drop down 217 this.form.find('select[name="address[id]"]').on('change',function(){ 218 if( $(this).val() ){ 219 me.formHelper.allowBlank( $(this), false ); 220 me.formHelper.hidePanel( me.form.find('.form-panel-address') ); 221 } 222 }); 223 224 // Change the states field type in the billing address panel 225 this.form.find('select[name="address[city]"]').parent('.form-input-holder').find('.form-field-button').on('click',function(){ 226 me.formHelper.toggleFieldType( $(this).parent().find('select[name="address[city]"]') ); 227 me.toggleText($(this),__d('contributions','Back'),__d('contributions','Add New')); 228 }); 229 230 // Change the states field type in the organization panel 231 this.form.find('select[name="group[address][city]"]').parent('.form-input-holder').find('.form-field-button').on('click',function(){ 232 me.formHelper.toggleFieldType( $(this).parent().find('select[name="group[address][city]"]') ); 233 me.toggleText($(this),__d('contributions','Back'),__d('contributions','Add New')); 234 }); 235 236 // Listen to `beforeFormHelperSubmit` event 237 this.formHelper.form.on('beforeFormHelperSubmit',function(event, formValues){ 238 var cartSummaryValidationErrors = SS.com.Contributions.frontend.CartSummary.validate(); 239 240 SS.com.Contributions.frontend.CartSummary.clearValidationErrors(me.formHelper.validationErrors); 241 242 $.extend(me.formHelper.validationErrors, cartSummaryValidationErrors); 243 244 if(!$.isEmptyObject(cartSummaryValidationErrors)){ 245 return false; 246 } else { 247 me.validateCurrency(event); 248 } 249 }); 250 251 // Transparent Redirect 252 this.formHelper.form.on('beforeFormHelperSubmit',function(event, formValues){ 253 254 var currency = me.getCurrency(); 255 256 257 if(!$.isEmptyObject(me.formHelper.validationErrors)){ 258 return true; 259 } 260 261 if(formValues['payment[id]']){ 262 var paymentMethodHelper = me.form.find('select[name="payment[id]"]').data('helper'); 263 var selectedMethod = ""; 264 if(paymentMethodHelper){ 265 selectedMethod = paymentMethodHelper.getSelectedMethod(); 266 } 267 268 try { 269 hasTransparentRedirect = me.config.transparentRedirectOptions[SS.vars.Site.id][currency][selectedMethod]['enabled']; 270 } 271 catch(e) { 272 console && console.error && console.error(e); 273 } 274 if (hasTransparentRedirect) { 275 276 var transparentRedirectWrapper = me.getTransparentRedirectWrapper(SS.vars.Site.id, currency, selectedMethod); 277 278 if (transparentRedirectWrapper.needsAuthorization && transparentRedirectWrapper.needsAuthorization(selectedMethod, formValues)) { 279 transparentRedirectWrapper.submitForAuthorization(paymentMethodHelper.getSelectedRecord()); 280 return false; 281 } 282 } 283 284 return true; 285 } 286 287 // todo: handle exceptions during checking phase 288 289 var methodType = me.getMethodType(); 290 if(!methodType){ 291 return true; 292 } 293 294 var hasTransparentRedirect = false; 295 try { 296 hasTransparentRedirect = me.config.transparentRedirectOptions[SS.vars.Site.id][currency][methodType]['enabled']; 297 } 298 catch(e) { 299 console && console.error && console.error(e); 300 } 301 if (hasTransparentRedirect) { 302 303 var transparentRedirectWrapper = me.getTransparentRedirectWrapper(SS.vars.Site.id,currency,methodType); 304 try{ 305 if(transparentRedirectWrapper.needsTransparentRedirection(formValues)){ 306 transparentRedirectWrapper.submitTransparentRedirect(formValues); 307 return false;
308 }else{ 309 return true; 310 } 311 }catch(e){ 312 313 console && console.error && console.error(e); 314 315 new SS.customAlert({ 316 title: 'Payment Error', 317 msg: 'Could not load payment wrapper', 318 closeButton: true, 319 buttons: { 320 ok: { 321 btnText: 'OK', 322 btnCls: false, 323 overCls: false 324 }, 325 cancel: false 326 } 327 }); 328 return false; 329 } 330 } 331 332 }); 333 334 // Listen to `resetFormHelper` event and recall this.init() when triggered 335 this.formHelper.form.on('resetFormHelper',function(){ 336 me.init(); 337 }); 338 339 // Listen to `formHelperIsNotValid` event 340 this.formHelper.form.on('formHelperIsNotValid',function(event, validationErrors){ 341 me.formIsNotValid(validationErrors); 342 }); 343 344 // Listen to `formHelperError` event 345 this.formHelper.form.on('formHelperError',function(event, responseData, textStatus, jqXHR, errorThrown){ 346 if (me.config.captcha !== null) { 347 grecaptcha.reset(me.config.captcha); 348 349 if(responseData.show_captcha){ 350 var captchaHolder = me.form.find('.captcha-holder'); 351 captchaHolder.removeClass('hidden-captcha'); 352 captchaHolder.show(); 353 } 354 } 355 356 if(responseData.auth_code){ 357 var currency = me.getCurrency(); 358 var methodType = me.getMethodType(); 359 var wrapper = me.getTransparentRedirectWrapper(SS.vars.Site.id,currency,methodType); 360 wrapper.handleMethodAction(responseData.auth_code); 361 } 362 363 if(responseData.policy_change){ 364 var policyText = me.form.find('.privacy-policy .privacy-policy-text'); 365 var policyHash = me.form.find('.privacy-policy #privacy-policy-hash'); 366 var policyCheckbox = me.form.find('.privacy-policy #ContributionPolicy\\[aggree\\]'); 367 policyText.html(responseData.policy_change.text); 368 policyHash.val(responseData.policy_change.hash); 369 policyCheckbox.prop('checked',false).trigger('syncChecked'); 370 } 371 }); 372 373 // Listen to `formHelperError` event 374 this.formHelper.form.on('formHelperSuccess',function(event, responseData, textStatus, jqXHR){ 375 if( responseData.success ){ 376 document.location.href = responseData.thanks_url; 377 } 378 }); 379 380 this.form.find('.group-id-field').find('.form-input-holder').find('.form-field-button').on('click',function(){ 381 me.toggleOrganizationInformation( $(this) ); 382 me.toggleText($(this),__d('contributions','Cancel'),__d('contributions','Add New')); 383 return false; 384 }); 385 386 this.form.find('input[name="group[id_display]"]').on('comboLoadComplete',function(){ 387 me.autoSelectGroup($(this)); 388 }); 389 390 me.inputsChanged = false; 391 392 setTimeout(function(){ 393 me.form.find('input').on('change',function(){ 394 me.inputsChanged = true; 395 }); 396 },5000); 397 398 this.form.on('submit',function(){ 399 me.inputsChanged = false; 400 }); 401 402 me.leave_page_warning = SS.com.Contributions.frontend.componentSettings.leave_page_warning?SS.com.Contributions.frontend.componentSettings.leave_page_warning:'You have not submitted your gift.'; 403 404 405 me.requireReload = false; 406 $(window).on('requireReload',function(){ 407 me.requireReload = true; 408 }); 409 410 window.onbeforeunload = function(e){ 411 if (me.inputsChanged && me.currentPaymentType != 'paypal' && me.currentPaymentType != 'applepay' && !me.requireReload) { 412 return me.leave_page_warning; 413 } 414 } 415 416 // Listener to add or remove "checked" class on all checkboxes in the form 417 this.form.find('input[type=checkbox]').on('change syncChecked',function(){ 418 if(this.checked) { 419 $(this).parent().addClass('checked'); 420 } else { 421 $(this).parent().removeClass('checked'); 422 } 423 }); 424 // Listener to add or remove "checked" class on all radios in the form 425 this.form.find('input[type=radio]').on('change syncChecked',function(){ 426 if(this.checked) { 427 me.form.find('input[name="' + $(this).attr('name') + '"]').parent().removeClass('checked'); 428 $(this).parent().addClass('checked'); 429 } 430 }); 431 432 // Add or remove "checked" class on all radios that are rendered as checked 433 this.form.find('input[type=radio],input[type=checkbox]').each(function(index, element) { 434 if(this.checked) { 435 $(this).parent().addClass('checked'); 436 } else { 437 $(this).parent().removeClass('checked'); 438 } 439 }); 440 441 this.form.find('select[name="payment[check][checking_type]"]').on('change',function(){ 442 var nameOnAccountField = me.form.find('input[name="payment[check][name_on_account]"]'); 443 444 if (nameOnAccountField.prop('placeholder')) { 445 nameOnAccountField.prop('placeholder',$(this).val() == 'Personal' ? 'Name on Account' : 'Company Name'); 446 } 447 nameOnAccountField.parent().siblings('label').html($(this).val() == 'Personal' ? 'Name on Account' : 'Company Name'); 448 }); 449 450 if (this.config.cart.group) { 451 452 var groupCheckbox = this.form.find('input[name="group[yes]"]'); 453 //$(groupCheckbox).attr('checked','checked'); 454 me.toggleOrganizationSelector($(groupCheckbox)); 455 456 var groupAddButton = this.form.find('.group-id-field').find('.form-input-holder').find('.form-field-button'); 457 me.toggleOrganizationInformation($(groupAddButton)); 458 me.toggleText($(groupAddButton),__d('contributions','Cancel'),__d('contributions','Add New')); 459 } 460 461 this.form.find('input[name="currency"]').on('change',function(){ 462 me.toggleCheckFields( $(this).val() ); 463 me.toggleActiveMethodForm( $(this).val() ); 464 me.toggleMethodCurrency($(this).val(),true); 465 }); 466 467 me.toggleCheckFields(this.form.find('input[name="currency"]:checked').val()); 468 469 var canMakeApplePayPayments = false;
470 try { 471 canMakeApplePayPayments = (window.ApplePaySession && ApplePaySession.canMakePayments()); 472 }catch (e) { 473 console.warn(e); 474 } 475 476 if (canMakeApplePayPayments) { 477 this.form.find('.payment-type-field label[for="ContributionPayment[type]Applepay"]').show(); 478 var applePayTransparentWrapper = me.getTransparentRedirectWrapper(SS.vars.Site.id,'USD','applepay'); 479 if(applePayTransparentWrapper && applePayTransparentWrapper.initApplePay){ 480 applePayTransparentWrapper.initApplePay('#apple-pay-button',this); 481 }else{ 482 $('#apple-pay-button').on('click', function(){ 483 me.payWithApplePay(); 484 }); 485 } 486 } else { 487 this.form.find('.payment-type-field label[for="ContributionPayment[type]Applepay"]').hide(); 488 } 489 490 this.initPayPal(); 491 492 this.checkAndInitTransparentRedirect(); 493 this.toggleMethodCurrency(me.getCurrency()); 494 this.correctTransferFee(); 495 }, 496 correctTransferFee:function (){ 497 var currentMethodType = this.getMethodType(); 498 499 if(currentMethodType && !this.config.hasInitialMethod){ 500 if(currentMethodType != 'card' && SS.com.Contributions.frontend.feeEnabled){ 501 SS.com.Contributions.frontend.CartSummary.update(0) 502 } 503 504 } 505 }, 506 getCurrency:function(){ 507 var me = this; 508 var currency = 'USD'; 509 me.config.currencies.forEach(function(item){ 510 if (item.is_default) { 511 currency = item.code; 512 } 513 }); 514 515 if(me.form.find('input[name="currency"]').length) { 516 currency = me.form.find('input[name="currency"]:checked').val(); 517 } 518 return currency; 519 }, 520 getCustomMethodForm:function(currency,methodType){ 521 var me = this; 522 var hasTransparentRedirect = false; 523 try { 524 hasTransparentRedirect = me.config.transparentRedirectOptions[SS.vars.Site.id][currency][methodType]['enabled']; 525 } 526 catch(e) { 527 console && console.error && console.error(e); 528 } 529 530 if(hasTransparentRedirect){ 531 var transparentRedirectWrapper = me.getTransparentRedirectWrapper(SS.vars.Site.id, currency, methodType); 532 if(transparentRedirectWrapper){ 533 var customMethodForm = this.form.find('.form-panel-custom-' + currency + '-' + methodType); 534 if(customMethodForm.length){ 535 return customMethodForm; 536 } 537 } 538 } 539 540 return false; 541 }, 542 checkAndInitTransparentRedirect:function(){ 543 var me = this; 544 var currency = this.getCurrency(); 545 546 var methodType = this.getMethodType() 547 if(!methodType){ 548 this.removeTransparentLoading(); 549 return true; 550 } 551 552 var hasTransparentRedirect = false; 553 try { 554 hasTransparentRedirect = me.config.transparentRedirectOptions[SS.vars.Site.id][currency][methodType]['enabled']; 555 } 556 catch(e) { 557 console && console.error && console.error(e); 558 } 559 if (hasTransparentRedirect) { 560 var transparentRedirectWrapper = me.getTransparentRedirectWrapper(SS.vars.Site.id, currency, methodType); 561 562 if(transparentRedirectWrapper){ 563 var methodHidden = !this.form.find('.form-panel-'+methodType).is(':visible'); 564 565 if(!methodHidden){ 566 var customMethodForm = this.getCustomMethodForm(currency,methodType) 567 if(customMethodForm) { 568 this.formHelper.hidePanel(this.form.find('.form-panel-'+methodType)); 569 this.formHelper.showPanel(customMethodForm); 570 } 571 } 572 }else{ 573 this.removeTransparentLoading(); 574 } 575 }else{ 576 this.removeTransparentLoading(); 577 } 578 }, 579 removeTransparentLoading:function(){ 580 $('.contributions .forms').removeClass('transparent-loading'); 581 }, 582 getTransparentRedirectWrapper:function(siteId,currency,method){ 583 var me = this; 584 var wrapperConfig = false;
585 var wrapper = false; 586 try{ 587 wrapperConfig = me.config.transparentRedirectOptions[siteId][currency][method]; 588 }catch(e){} 589 590 if(wrapperConfig){ 591 592 if(!wrapperConfig['enabled']){ 593 return false; 594 } 595 var wrapperKey = siteId+'.'+currency+'.'+method; 596 597 if(!this.transparentRedirectWrapperInstances[wrapperKey]){ 598 try{ 599 var wrapperClassName = 'SS.com.PaymentProcessors.frontend.transparent_redirect.'+wrapperConfig.gateway; 600 601 var wrapperClass = eval(wrapperClassName); 602 var wrapperData = { 603 paymentForm:me, 604 siteId:siteId, 605 currency:currency, 606 method:method 607 }; 608 609 wrapperData = $.extend(wrapperData,wrapperConfig); 610 611 wrapper = new wrapperClass(wrapperData); 612 }catch(e){ 613 return false; 614 } 615 this.transparentRedirectWrapperInstances[wrapperKey] = wrapper; 616 }else{ 617 return this.transparentRedirectWrapperInstances[wrapperKey]; 618 } 619 } 620 621 622 return wrapper; 623 624 }, 625 626 627 /** 628 * Inform the user that the form has errors and scroll the page to the first error found 629 * @param errors 630 */ 631 formIsNotValid: function( errors ) 632 { 633 634 if ($.isEmptyObject(errors)) { 635 return; 636 } 637 638 var me = this; 639 var alertConfig = { 640 title: __d('contributions','Invalid checkout form'), 641 msg: __d('contributions','The checkout form contains errors. Please fix the fields marked in red.'), 642 closeButton: true, 643 targetLocation: this.form.find('input[type="submit"]'), 644 buttons: { 645 ok: { 646 btnText: 'OK', 647 btnCls: false, 648 overCls: false 649 }, 650 cancel: false 651 }, 652 callback: function(){ 653 for( var i in errors ){ 654 break; 655 } 656 657 var el = me.form.closest('body').find('input[name="'+i+'"], select[name="'+i+'"], textarea[name="'+i+'"]'); 658 659 if(!me.inIframe()){ 660 $('html, body').animate({ 661 scrollTop: el.offset().top - 100 662 }, 200); 663 }else{ 664 me.scrollIntoView(el[0]); 665 } 666 } 667 }; 668 this.lastAlert = new SS.customAlert(alertConfig); 669 }, 670 671 scrollIntoView:function(el){ 672 if(this.requiresIframeScrollFix()){ 673 window.parent.postMessage( JSON.stringify( {action: 'scrollTo', value: el.getBoundingClientRect().top} ), '*' ); 674 }else{ 675 el.scrollIntoView({ 676 behavior: "smooth", 677 block: "start" 678 }); 679 } 680 }, 681 requiresIframeScrollFix:function() { 682 try { 683 // Check for safari 684 var is_safari = navigator.userAgent.indexOf("Safari") > -1; 685 // Chrome has Safari in the user agent so we need to filter (https://stackoverflow.com/a/7768006/1502448) 686 var is_chrome = navigator.userAgent.indexOf('Chrome') > -1; 687 if ((is_chrome) && (is_safari)) { is_safari = false; } 688 689 // If we need to narrow this down even further we can use a more robust browser detection (https://stackoverflow.com/questions/5916900) 690 // Problematic browsers can be adjusted here. 691 if (is_safari && ( 692 navigator.userAgent.match(/iPad/i) || 693 navigator.userAgent.match(/iPhone/i) 694 )) 695 return true; 696 else 697 return false; 698 699 } catch (e) { 700 alert(e.message); 701 } 702 }, 703 inIframe:function(){ 704 try { 705 return window.self !== window.top; 706 } catch (e) { 707 return true; 708 } 709 }, 710 711 validateCurrency: function(event) { 712 713 var me = this; 714 715 if(me.form.find('input[name="currency"]').length) { 716 if(!me.form.find('input[name="currency"]:checked').val()) { 717 718 event.preventDefault(); 719 720 var alertConfig = { 721 title: __d('contributions','Invalid checkout form'), 722 msg: __d('contributions','Please choose a currency.'), 723 closeButton: true, 724 buttons: { 725 ok: { 726 btnText: 'OK', 727 btnCls: false, 728 overCls: false 729 }, 730 cancel: false 731 } 732 }; 733 new SS.customAlert(alertConfig); 734 } 735 } 736 }, 737 738 /** 739 * Toggle text on element 740 * @param element 741 * @param text1 742 * @param text2 743 */ 744 toggleText: function( element, text1, text2 ) 745 { 746 if( element.html() == text1 ){ 747 element.html(text2); 748 }else{ 749 element.html(text1); 750 } 751 }, 752 753 /** 754 * Toggle payment type panel visibility 755 * @param trigger 756 */ 757 togglePaymentType: function( ) 758 { 759 var me = this;
760 var type = this.getMethodType(); 761 var currency = this.getCurrency(); 762 var captchaHolder = this.form.find('.captcha-holder'); 763 764 this.formHelper.hidePanel( this.form.find('.form-panel-card') ); 765 this.formHelper.hidePanel( this.form.find('.form-panel-check') ); 766 this.formHelper.hidePanel( this.form.find('.form-panel-custom-method') ); 767 768 if(!captchaHolder.hasClass('hidden-captcha')){ 769 captchaHolder.show(); 770 } 771 772 var startDateDisplay = $('input[name="recurring[start_date_display]"]'); 773 774 775 if (type=='paypal') { 776 this.formHelper.hidePanel( this.form.find('.form-panel-existing-cards') ); 777 this.formHelper.hidePanel( me.form.find('.billing-information') ); 778 // this.formHelper.hidePanel( me.form.find('.organization-information') ); 779 $('.form-actions').hide(); 780 $('.form-panel-paypal').show(); 781 $('.form-panel-applepay').hide(); 782 this.form.find('.captcha-holder').hide(); 783 startDateDisplay.data('originalDate', startDateDisplay.datepicker('getDate')); 784 startDateDisplay.datepicker("setDate", new Date()); 785 startDateDisplay.datepicker("option", 'disabled', true); 786 } else if (type=='applepay') { 787 this.formHelper.hidePanel( this.form.find('.form-panel-existing-cards') ); 788 this.formHelper.hidePanel( me.form.find('.billing-information') ); 789 // this.formHelper.hidePanel( me.form.find('.organization-information') ); 790 $('.form-actions').hide(); 791 $('.form-panel-applepay').show(); 792 $('.form-panel-paypal').hide(); 793 } else { 794 this.formHelper.showPanel( this.form.find('.form-panel-existing-cards') ); 795 this.formHelper.showPanel( me.form.find('.billing-information'), false ); 796 // this.formHelper.showPanel( me.form.find('.organization-information') ); 797 $('.form-actions').show(); 798 $('.form-panel-paypal').hide(); 799 $('.form-panel-applepay').hide(); 800 801 var customMethodForm = this.getCustomMethodForm(currency,type) 802 if(customMethodForm){ 803 this.formHelper.showPanel( customMethodForm ); 804 }else{ 805 this.formHelper.showPanel( this.form.find('.simple-form.form-panel-' + type) ); 806 } 807 } 808 809 if(type != 'paypal'){ 810 var originalDate = startDateDisplay.data("originalDate")?startDateDisplay.data("originalDate"):null; 811 startDateDisplay.datepicker('setDate', originalDate); 812 } 813 814 if(this.currentPaymentType == 'paypal'){ // previous method was paypal 815 var recurring = this.form.find('input[name="is_recurring"]').prop('checked'); 816 if(recurring){ 817 startDateDisplay.datepicker("option", 'disabled', false); 818 } 819 } 820 821 this.currentPaymentType = type; 822 me.toggleTransferFee(); 823 me.toggleStoreOption(); 824 }, 825 826 /** 827 * Toggle organization information panel visibility 828 * @param trigger 829 */ 830 toggleOrganizationInformation: function( trigger ) 831 { 832 var panel = this.form.find('.form-panel-organization' ); 833 if( !panel.is(':visible') ){ 834 trigger.parent('.form-input-holder').find('input,select,textarea').val('').attr('disabled','disabled').removeClass('has-error').closest('label').addClass('disabled'); 835 this.formHelper.showPanel( this.form.find('.form-panel-organization' ) ); 836 }else{ 837 trigger.parent('.form-input-holder').find('input,select,textarea').removeAttr('disabled').closest('label').removeClass('disabled'); 838 this.formHelper.hidePanel( this.form.find('.form-panel-organization' ) ); 839 } 840 }, 841 842 /** 843 * Toggle organization selector panel visibility 844 * @param trigger 845 */ 846 toggleOrganizationSelector: function( trigger ) 847 { 848 var organizationPanelSelector = this.form.find('.form-panel-organization-selector' ); 849 var organizationPanel = this.form.find('.form-panel-organization' ); 850 var alternateOrganizationPanel = this.form.find('.form-panel-alternate-organization'); 851 var alternateField = this.form.find('input[name="alternate_organization"]:checked'); 852 853 var directForm = $(trigger).data('direct-form'); 854 855 if(directForm) { 856 if (trigger.is(':checked')) { 857 this.formHelper.showPanel(organizationPanel); 858 this.formHelper.hidePanel(alternateOrganizationPanel); 859 alternateField.prop('checked', false).trigger('syncChecked'); 860 }else{ 861 this.formHelper.hidePanel(organizationPanel); 862 } 863 }else { 864 if (trigger.is(':checked')) { 865 this.formHelper.showPanel(organizationPanelSelector); 866 this.formHelper.hidePanel(alternateOrganizationPanel); 867 alternateField.prop('checked', false).trigger('syncChecked'); 868 } else { 869 this.formHelper.hidePanel(organizationPanelSelector); 870 if (organizationPanel.is(':visible')) { 871 this.formHelper.hidePanel(organizationPanel); 872 this.toggleText(organizationPanelSelector.find('.form-field-button'), __d('contributions','Cancel'), __d('contributions','Add New')); 873 } 874 } 875 } 876 }, 877 toggleAlternateOrganizationSelector: function(trigger) { 878 var alternateOrganizationPanel = this.form.find('.form-panel-alternate-organization'); 879 var organizationPanelSelector = this.form.find('.form-panel-organization-selector' ); 880 var organizationPanel = this.form.find('.form-panel-organization'); 881 var organizationField = this.form.find('input[name="group[yes]"]:checked') 882 883 if (trigger.is(':checked')) { 884 this.formHelper.showPanel(alternateOrganizationPanel); 885 this.formHelper.hidePanel(organizationPanelSelector); 886 this.formHelper.hidePanel(organizationPanel); 887 organizationField.prop('checked', false).trigger('syncChecked'); 888 }else{ 889 this.formHelper.hidePanel(alternateOrganizationPanel); 890 } 891 }, 892 893 /** 894 * Toggle recurring options panel visibility 895 * @param trigger 896 */ 897 toggleRecurringOptions: function( trigger , updateCart) 898 { 899 var me = this; 900 var recurringType = this.form.find('input[name="recurring[type]"]:checked'); 901 if (!recurringType) { 902 recurringType = this.form.find('input[name="recurring[type]"]') 903 } 904 905 if(recurringType){ 906 recurringType = recurringType.val(); 907 } 908 909 if(!trigger || trigger.is(':checked')){ 910 this.formHelper.showPanel( this.form.find('.form-panel-recurring') ); 911 this.formHelper.showPanel( this.form.find('.form-panel-register') ); 912// if( !this.form.find('input[name="register"]').is(':checked') ){ 913// this.form.find('input[name="register"]').click(); 914// this.form.find('input[name="register"]').attr('disabled',true); 915// } 916 if(me.config.disableCheckForRecurring){ 917 $('input[name="payment[type]"][value="check"]').attr('disabled','disabled').closest('label').addClass('disabled'); 918 $('input[name="payment[type]"][value="card"]').trigger('click'); 919 } 920 921 if (this.currentPaymentType == 'paypal') { 922 $('input[name="recurring[start_date_display]"]').datepicker("setDate", new Date()); 923 $('input[name="recurring[start_date_display]"]').datepicker("option", 'disabled', true); 924 } else { 925 $('input[name="recurring[start_date_display]"]').datepicker("option", 'disabled', false); 926 } 927 928 if (updateCart) { 929 SS.com.Contributions.frontend.CartSummary.addRecurringToCart(true, recurringType); 930 } 931 932 this.formHelper.hidePanel( this.form.find('.form-panel-store-preference') ); 933 934 }else{ 935 this.formHelper.hidePanel( this.form.find('.form-panel-recurring') ); 936 this.formHelper.hidePanel( this.form.find('.form-panel-register') ); 937// this.form.find('input[name="register"]').removeAttr('disabled'); 938 if(me.config.disableCheckForRecurring){ 939 $('input[name="payment[type]"][value="check"]').removeAttr('disabled').closest('label').removeClass('disabled'); 940 } 941 942 if (updateCart) { 943 SS.com.Contributions.frontend.CartSummary.addRecurringToCart(false, recurringType); 944 } 945 } 946 947 me.toggleStoreOption(); 948 }, 949 950 951 toggleStoreOption:function(){ 952 var me = this; 953 var panel = this.form.find('.form-panel-store-preference'); 954 if(panel){ 955 var recurring = this.form.find('input[name="is_recurring"]').prop('checked'); 956 957 var card = me.form.find('.form-panel-card'); 958 var check = me.form.find('.form-panel-check'); 959 var customCard = me.form.find('.form-panel-custom-card');
960 var customCheck = me.form.find('.form-panel-custom-check'); 961 962 var cardVisible = typeof card.data('isHidden') == 'boolean'? !card.data('isHidden'):(card.is(':visible')); 963 var checkVisible = typeof check.data('isHidden') == 'boolean'? !check.data('isHidden'):(check.is(':visible')); 964 var customCardVisible = typeof customCard.data('isHidden') == 'boolean'? !customCard.data('isHidden'):(customCard.is(':visible')); 965 var customCheckVisible = typeof customCheck.data('isHidden') == 'boolean'? !customCheck.data('isHidden'):(customCheck.is(':visible')); 966 967 968 var hasAddNewMethod = cardVisible || checkVisible || customCardVisible || customCheckVisible; 969 970 if(recurring){ 971 this.formHelper.hidePanel( this.form.find('.form-panel-store-preference') ) 972 }else if(hasAddNewMethod){ 973 this.formHelper.showPanel( this.form.find('.form-panel-store-preference') ) 974 }else{ 975 this.formHelper.hidePanel( this.form.find('.form-panel-store-preference') ) 976 } 977 } 978 }, 979 980 /** 981 * Toggle tribute options panel visibility 982 * @param trigger 983 */ 984 toggleTributeOptions: function( trigger ) 985 { 986 var me = this; 987 if(!trigger || trigger.is(':checked')){ 988 this.formHelper.showPanel( this.form.find('.form-panel-tribute-options') ); 989 }else{ 990 this.formHelper.hidePanel( this.form.find('.form-panel-tribute-options') ); 991 this.formHelper.hidePanel( this.form.find('.form-panel-tribute-recipient') ); 992 var hasRecipient = this.form.find('.tribute-has-recipient-field'); 993 if(hasRecipient.length){ 994 hasRecipient.find('.form-input-label').removeClass('checked'); 995 hasRecipient.find('input[name="tribute[has_recipient]"]:checked').attr('checked', false); 996 } 997 } 998 }, 999 1000 /** 1001 * Toggle tribute recipient panel visibility 1002 * @param trigger 1003 */ 1004 toggleTributeRecipient: function( trigger ) 1005 { 1006 var me = this; 1007 if(!trigger || trigger.is(':checked')){ 1008 this.formHelper.showPanel( this.form.find('.form-panel-tribute-recipient') ); 1009 }else{ 1010 this.formHelper.hidePanel( this.form.find('.form-panel-tribute-recipient') ); 1011 } 1012 }, 1013 1014 /** 1015 * Toggle register options panel visibility 1016 * @param trigger 1017 */ 1018// toggleRegisterOptions: function( trigger ) 1019// { 1020// if(trigger.is(':checked')){ 1021// this.formHelper.showPanel( this.form.find('.form-panel-' + trigger.val()) ); 1022// }else{ 1023// this.formHelper.hidePanel( this.form.find('.form-panel-' + trigger.val()) ); 1024// } 1025// }, 1026 1027 /** 1028 * Toggle add card panel visibility 1029 * @param trigger 1030 */ 1031 toggleAddCardOrCheck: function( trigger ) 1032 { 1033 var me = this; 1034 var state = trigger.html(); 1035 var currency = this.getCurrency(); 1036 var selectedType = this.form.find('.form-panel-payment-type input:checked').val(); 1037 if(!selectedType) { 1038 selectedType = 'card'; 1039 } 1040 var visiblePanel = this.form.find('.simple-form.form-panel-' + selectedType); 1041 var customMethodForm = this.getCustomMethodForm(currency,selectedType) 1042 if(customMethodForm) { 1043 visiblePanel = customMethodForm; 1044 } 1045 var hasAddressCombo = me.form.find('.form-panel-saved-addresses').length; 1046 if( !visiblePanel.is(':visible') ){ 1047 trigger.parent('.form-input-holder').find('input,select,textarea').val(''); 1048 this.formHelper.allowBlank( trigger.parent('.form-input-holder').find('input,select,textarea'), true ); 1049 this.formHelper.showPanel( visiblePanel ); 1050 this.formHelper.showPanel( me.form.find('.form-panel-payment-type') ); 1051 this.formHelper.showPanel( me.form.find('.billing-information'), !hasAddressCombo); 1052 this.formHelper.showPanel( me.form.find('.form-panel-saved-addresses') ); 1053 this.formHelper.clearValidationErrors( trigger.parent('.form-input-holder').find('input,select,textarea') ); 1054 }else{ 1055 this.formHelper.hidePanel( visiblePanel ); 1056 this.formHelper.hidePanel( me.form.find('.form-panel-payment-type') ); 1057 this.formHelper.hidePanel( me.form.find('.billing-information') ); 1058 this.formHelper.allowBlank( trigger.parent('.form-input-holder').find('input,select,textarea'), false ); 1059 this.formHelper.clearValidationErrors( trigger.parent('.form-input-holder').find('input,select,textarea') ); 1060 } 1061 me.toggleTransferFee(); 1062 me.toggleStoreOption(); 1063 }, 1064 1065 /** 1066 * Toggle add address panel visibility 1067 * @param trigger 1068 */ 1069 toggleAddAddress: function( trigger ) 1070 { 1071 var me = this; 1072 var addAddressPanel = this.form.find('.form-panel-address'); 1073 if( !addAddressPanel.is(':visible') ){ 1074 trigger.parent('.form-input-holder').find('input,select,textarea').val(''); 1075 this.formHelper.allowBlank( trigger.parent('.form-input-holder').find('input,select,textarea'), true ); 1076 this.formHelper.showPanel( addAddressPanel ); 1077 this.formHelper.clearValidationErrors( trigger.parent('.form-input-holder').find('input,select,textarea') ); 1078 }else{ 1079 this.formHelper.hidePanel( addAddressPanel ); 1080 this.formHelper.allowBlank( trigger.parent('.form-input-holder').find('input,select,textarea'), false ); 1081 this.formHelper.clearValidationErrors( trigger.parent('.form-input-holder').find('input,select,textarea') ); 1082 } 1083 }, 1084 1085 autoSelectGroup: function(displayField) 1086 { 1087 var me = this; 1088 var combo = displayField.closest('.form-input-wrapper'); 1089 var valueField = combo.find('input[type="hidden"]'); 1090 var value = this.formHelper.findValueByFieldName(valueField); 1091 if(value){ 1092 var comboOptions = combo.find('.option'); 1093 var comboValues = []; 1094 $.each(comboOptions,function(index, option){
1095 comboValues[$(option).data('value')] = $(option).html(); 1096 }); 1097 displayField.val(comboValues[value]); 1098 valueField.val(value); 1099 } 1100 }, 1101 1102 padNumber: function(num, size) 1103 { 1104 var s = num+""; 1105 while (s.length < size) s = "0" + s; 1106 return s; 1107 }, 1108 1109 toggleTransferFee: function() 1110 { 1111 var me = this; 1112 var transferFeePanel = this.form.find('.form-panel-transfer-fee'); 1113 var isCard = false; 1114 var paymentMethodHelper = this.form.find('select[name="payment[id]"]').data('helper'); 1115 var selectedMethod = ""; 1116 if(!isCard && paymentMethodHelper){ 1117 selectedMethod = paymentMethodHelper.getSelectedMethod(); 1118 if(selectedMethod){ 1119 isCard = selectedMethod=='card'; 1120 } 1121 } 1122 1123 if(!isCard && !selectedMethod){ 1124 isCard = !me.form.find('.form-panel-card').data('isHidden'); 1125 } 1126 1127 if(!isCard && me.currentPaymentType){ 1128 isCard = me.currentPaymentType == 'card' 1129 } 1130 1131 if(!isCard && !selectedMethod){ 1132 isCard = this.getMethodType()=='card'; 1133 } 1134 1135 if(isCard){ 1136 me.formHelper.showPanel( transferFeePanel ); 1137 }else{ 1138 me.formHelper.hidePanel( transferFeePanel ); 1139 } 1140 1141 if( isCard ){ 1142 var transferChecked = transferFeePanel.find('input[name="transfer_fee"]:checked').val(); 1143 SS.com.Contributions.frontend.CartSummary.update(transferChecked); 1144 }else{ 1145 SS.com.Contributions.frontend.CartSummary.update(0); 1146 } 1147 }, 1148 toggleCheckFields:function( currency ){ 1149 1150 var me = this; 1151 1152 var checkForm = this.form.find('.form-panel-check'); 1153 if(!currency){ 1154 currency = this.config.currencies?this.config.currencies[0]['code']:'USD'; 1155 } 1156 1157 if(currency=='CAD'){ 1158 checkForm.addClass('form-panel-check-cad'); 1159 me.formHelper.showField( checkForm.find('.payment-check-bank-number-field') ) 1160 me.formHelper.showField( checkForm.find('.payment-check-transit-number-field') ) 1161 me.formHelper.hideField( checkForm.find('.payment-check-routing-number-field') ) 1162 }else{ 1163 checkForm.removeClass('form-panel-check-cad'); 1164 me.formHelper.showField( checkForm.find('.payment-check-routing-number-field') ) 1165 me.formHelper.hideField( checkForm.find('.payment-check-bank-number-field') ) 1166 me.formHelper.hideField( checkForm.find('.payment-check-transit-number-field') ) 1167 } 1168 }, 1169 getMethodType:function(){ 1170 var me = this; 1171 var paymentType = me.form.find('input[name="payment[type]"]'); 1172 1173 if(paymentType.is(':radio')){ 1174 return me.form.find('input[name="payment[type]"]:checked').val() 1175 }else{ 1176 return paymentType.val(); 1177 } 1178 }, 1179 restrictCurrencyOptions(currency){ 1180 var methodtypes = this.config.paymentTypeByCurrencyOptions[currency]; 1181 var paymentType = this.form.find('input[name="payment[type]"]'); 1182 var changed = false; 1183 var validElement = null; 1184 1185 if(paymentType.is(':radio')){ 1186 paymentType.each(function(index,element){ 1187 var el = $(element); 1188 var type = el.val(); 1189 if(methodtypes.indexOf(type)==-1){ 1190 el.attr('disabled','disabled').data('force-disable',1); 1191 el.closest('label').addClass('disabled'); 1192 if(el.is(':checked')){ 1193 changed = true; 1194 el.prop('checked',false).trigger('syncChecked'); 1195 1196 } 1197 }else{ 1198 if(!validElement){ 1199 validElement = el; 1200 } 1201 el.data('force-disable',null).removeAttr('disabled'); 1202 el.closest('label').removeClass('disabled'); 1203 } 1204 }) 1205 } 1206 1207 if(changed){ 1208 validElement.prop('checked',true).trigger('syncChecked'); 1209 return true; 1210 } 1211 1212 return false;
1213 }, 1214 toggleActiveMethodForm:function( currency ){ 1215 var me = this; 1216 1217 if(!currency){ 1218 currency = 'USD'; 1219 } 1220 1221 var changedMethod = this.restrictCurrencyOptions(currency); 1222 if(changedMethod){ 1223 var paymentTypePanel = this.form.find('.form-panel-payment-type'); 1224 if(paymentTypePanel.is(':visible')){ 1225 this.togglePaymentType(); 1226 1227 return true; 1228 } 1229 1230 } 1231 1232 var methodType = this.getMethodType(); 1233 1234 var customMethodForm = this.getCustomMethodForm(currency,methodType); 1235 var currentMethodForm = this.form.find('.simple-form.form-panel-' + methodType); 1236 if(customMethodForm) { 1237 currentMethodForm = customMethodForm; 1238 } 1239 1240 var anyForm = this.form.find('.form-panel-'+methodType); 1241 if(currentMethodForm && currentMethodForm.is(':visible')){ 1242 return 1243 }if(anyForm.is(':visible') && !currentMethodForm.is(':visible')){ 1244 this.formHelper.hidePanel(anyForm); 1245 this.formHelper.showPanel(currentMethodForm); 1246 } 1247 }, 1248 toggleMethodCurrency: function(currency, onEvent){ 1249 var methodHelper = this.form.find('select[name="payment[id]"]').data('helper'); 1250 1251 if(methodHelper){ 1252 methodHelper.setCurrency(currency); 1253 } 1254 1255 if(onEvent){ 1256 this.updateCart(); 1257 } 1258 }, 1259 updateCart:function (){ 1260 SS.com.Contributions.frontend.CartSummary.updateContent(); 1261 }, 1262 payWithApplePay: function() { 1263 var me = this; 1264 var runningTotal = SS.com.Contributions.frontend.total; 1265 1266 var paymentRequest = { 1267 currencyCode: 'USD', 1268 countryCode: 'US', 1269 requiredShippingContactFields: ['email', 'phone'], 1270 requiredBillingContactFields: ['postalAddress', 'name'], 1271 total: { 1272 label: 'Contributions', 1273 amount: runningTotal 1274 }, 1275 supportedNetworks: ['amex', 'masterCard', 'visa', 'discover'], 1276 merchantCapabilities: ['supports3DS', 'supportsEMV', 'supportsCredit', 'supportsDebit'] 1277 }; 1278 1279 var session = new ApplePaySession(2, paymentRequest); 1280 1281 // Merchant Validation 1282 session.onvalidatemerchant = function (event) { 1283 var promise = performValidation(event.validationURL); 1284 promise.then(function (merchantSession) { 1285 session.completeMerchantValidation(merchantSession); 1286 }); 1287 } 1288 1289 1290 function performValidation(valURL) { 1291 return new Promise(function(resolve, reject) { 1292 var xhr = new XMLHttpRequest(); 1293 xhr.onload = function() { 1294 var data = JSON.parse(this.responseText); 1295 console.log(data); 1296 resolve(data); 1297 }; 1298 xhr.onerror = reject; 1299 xhr.open('GET', SS.route('PaymentProcessors','PaymentProcessorApplePay','validateMerchant',null,null)+'?url=' + valURL); 1300 xhr.send(); 1301 }); 1302 } 1303 1304 session.onpaymentauthorized = function (event) { 1305 1306 console.log('starting session.onpaymentauthorized'); 1307 console.log(event); 1308 console.log(JSON.stringify(event.payment.token.paymentData)); 1309 1310 var promise = sendPaymentToken(event.payment); 1311 promise.then(function (success) { 1312 var status; 1313 if (success){ 1314 status = ApplePaySession.STATUS_SUCCESS; 1315 } else { 1316 status = ApplePaySession.STATUS_FAILURE; 1317 } 1318 1319 console.log( "result of sendPaymentToken() function = " + success ); 1320 session.completePayment(status); 1321 }); 1322 } 1323 1324 function sendPaymentToken(paymentData) { 1325 return new Promise(function(resolve, reject) { 1326 // console.log('starting function sendPaymentToken()'); 1327 // console.log(paymentToken); 1328 // console.log(JSON.stringify(paymentToken.paymentData)); 1329 // 1330 // console.log("this is where you would pass the payment token to your third-party payment provider to use the token to charge the card. Only if your provider tells you the payment was successful should you return a resolve(true) here. Otherwise reject;"); 1331 // console.log("defaulting to resolve(true) here, just to show what a successfully completed transaction flow looks like"); 1332 1333 1334 me.form.one('beforeFormHelperSubmit',function(event, formValues) { 1335 formValues['payment[apple_pay_data]'] = encodeURIComponent(JSON.stringify(paymentData)); 1336 return true; 1337 }); 1338 1339 me.form.one('formHelperError',function(event, responseData, textStatus, jqXHR, errorThrown){ 1340 resolve(false); 1341 }); 1342 1343 me.form.one('formHelperSuccess',function(event, responseData, textStatus, jqXHR){ 1344 resolve(true); 1345 }); 1346 1347 console.log(me.form); 1348 1349 me.form.submit(); 1350 1351 }); 1352 } 1353 1354 session.oncancel = function(event) { 1355 console.log('starting session.cancel'); 1356 console.log(event); 1357 } 1358 1359 session.begin(); 1360 }, 1361 1362 initPayPal: function() { 1363 var me = this; 1364 $('form[name="PayPal"]').on('submit', function (event) { 1365 1366 $('form[name="PayPal"] input[name="amount"]').val(SS.com.Contributions.frontend.total); 1367 $('form[name="PayPal"] input[name="custom"]').val(SS.com.Contributions.frontend.cartId); 1368 1369 me.formHelper.validatePanel(); 1370 if (!$.isEmptyObject(me.formHelper.validationErrors)) { 1371 event.preventDefault(); 1372 return false;
1373 } else { 1374 var values = me.formHelper.getAllFieldValues(); 1375 1376 if (values['recurring[type]']) { 1377 1378 $('input[name="recurring[start_date_display]"]').datepicker("setDate", new Date()); 1379 1380 values = me.formHelper.getAllFieldValues(); 1381 1382 var recurringType = values['recurring[type]'].split('-'); 1383 var recurringInterval = parseInt(recurringType[0]); 1384 var recurringPeriod = recurringType[1]; 1385 var recurringPeriodShort = recurringPeriod.charAt(0).toUpperCase(); 1386 1387 1388 var srt = 52; 1389 if (values['recurring[end_date]']) { 1390 var startDate = $.datepicker.parseDate("yy-mm-dd", values['recurring[start_date]']); 1391 var endDate = $.datepicker.parseDate("yy-mm-dd", values['recurring[end_date]']); 1392 var timeDiff = Math.abs(endDate.getTime() - startDate.getTime()); 1393 var multiplier; 1394 switch (recurringPeriodShort) { 1395 case 'D': 1396 multiplier = 1000 * 3600 * 24; 1397 break; 1398 case 'W': 1399 multiplier = 1000 * 3600 * 24 * 7; 1400 break; 1401 case 'M': 1402 multiplier = 1000 * 3600 * 24 * 31; 1403 break; 1404 case 'Y': 1405 multiplier = 1000 * 3600 * 24 * 365; 1406 break; 1407 } 1408 multiplier *= recurringInterval; 1409 srt = Math.ceil(timeDiff / multiplier); 1410 1411 } 1412 srt = Math.max(srt, 2); 1413 srt = Math.min(srt, 52); 1414 1415 // console.log(startDate, endDate, srt); 1416 1417 $('form[name="PayPal"] input[name="cmd"]').val('_xclick-subscriptions'); 1418 $('form[name="PayPal"] input[name="a3"]').val(SS.com.Contributions.frontend.total); 1419 $('form[name="PayPal"] input[name="p3"]').val(recurringInterval); 1420 $('form[name="PayPal"] input[name="t3"]').val(recurringPeriodShort); 1421 $('form[name="PayPal"] input[name="src"]').val(1); 1422 $('form[name="PayPal"] input[name="srt"]').val(srt); 1423 1424 } else { 1425 1426 $('form[name="PayPal"] input[name="cmd"]').val('_xclick'); 1427 $('form[name="PayPal"] input[name="a3"]').val(''); 1428 $('form[name="PayPal"] input[name="p3"]').val(''); 1429 $('form[name="PayPal"] input[name="t3"]').val(''); 1430 $('form[name="PayPal"] input[name="src"]').val(''); 1431 $('form[name="PayPal"] input[name="srt"]').val(''); 1432 } 1433 1434 // console.log(values); 1435 // return false; 1436 1437 $.ajax({ 1438 url: SS.route('Contributions','Contributions','setGroupToCart',null), 1439 type: 'POST', 1440 data: values, 1441 dataType : 'json', 1442 abortOnRetry: false 1443 }); 1444 } 1445 }); 1446 }, 1447 getAddressInformation:function(){ 1448 var addAddressPanel = this.form.find('.form-panel-address'); 1449 var selectedAddressRecord = null; 1450 if( !addAddressPanel.is(':visible') ){ 1451 var addressField = this.form.find('select[name="address[id]"]'); 1452 selectedAddressRecord = addressField.data('helper').getSelectedRecord(); 1453 if(selectedAddressRecord){ 1454 return { 1455 address1:selectedAddressRecord['PersonAddress']['address1'], 1456 address2:selectedAddressRecord['PersonAddress']['address2'], 1457 city:selectedAddressRecord['PersonAddress']['city'], 1458 zip:selectedAddressRecord['PersonAddress']['zip'], 1459 stateCode:selectedAddressRecord['LocationState']['code'], 1460 state:selectedAddressRecord['LocationState']['name'], 1461 countryCode:selectedAddressRecord['LocationCountry']['code'], 1462 country:selectedAddressRecord['LocationCountry']['name'] 1463 } 1464 } 1465 }else{ 1466 var address1Field = addAddressPanel.find('[name="address[address1]"]'); 1467 var address2Field = addAddressPanel.find('[name="address[address2]"]'); 1468 var cityField = addAddressPanel.find('[name="address[city]"]'); 1469 var zipField = addAddressPanel.find('[name="address[zip]"]'); 1470 var stateField = addAddressPanel.find('[name="address[location_state_id_display]"]'); 1471 var countryField = addAddressPanel.find('[name="address[location_country_id_display]"]'); 1472 1473 if(!stateField.length){ 1474 stateField=addAddressPanel.find('select[name="address[location_state_id]"]') 1475 } 1476 1477 if(!countryField.length){ 1478 countryField=addAddressPanel.find('select[name="address[location_country_id]"]') 1479 } 1480
1481 var stateRecord = stateField.data('helper').getSelectedRecord(); 1482 var countryRecord = countryField.data('helper').getSelectedRecord(); 1483 1484 var state = stateRecord?stateRecord:{}; 1485 var country = countryRecord?countryRecord:{}; 1486 1487 if(stateRecord.LocationState){ 1488 state = stateRecord.LocationState; 1489 } 1490 1491 if(countryRecord.LocationCountry){ 1492 country = countryRecord.LocationCountry; 1493 } 1494 1495 return{ 1496 address1:address1Field.val(), 1497 address2:address2Field.val(), 1498 city:cityField.val(), 1499 zip:zipField.val(), 1500 stateCode:state.code, 1501 state:state.name, 1502 countryCode:country.code, 1503 country:country.name 1504 } 1505 } 1506 return false; 1507 }, 1508 getRecurringTypeInformation:function(){ 1509 var values = this.formHelper.getAllFieldValues(); 1510 1511 if (values['recurring[type]']) { 1512 var recurringType = values['recurring[type]']; 1513 if(this.config.recurringTypeOptions && this.config.recurringTypeOptions[recurringType]){ 1514 return this.config.recurringTypeOptions[recurringType] 1515 } 1516 } 1517 return false; 1518 } 1519};
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.