1/* globals Give*/ 2/** 3 * Give Frontend Recurring JS 4 * 5 * Scripts function in frontend form. 6 */ 7var Give_Recurring_Vars; 8 9jQuery( document ).ready( function( $ ) { 10 11 var doc = $( document ); 12 13 var Give_Recurring = { 14 15 /** 16 * Initialize 17 */ 18 init: function() { 19 /** 20 * Call notifyUserOnLevels. 21 */ 22 doc.on( 'give_donation_value_updated', function( e, parent_form, amount ) { 23 24 // If event is called when field blurred. 25 if ( ! parent_form ) { 26 parent_form = $( this ).closest( 'form.give-form' ); // If parent form is empty, assign the current form object. 27 } 28 29 var give_total = ('undefined' === typeof amount) ? parent_form.find( 'input[name="give-amount"]' ).val() : amount, 30 price_id = parent_form.find('input[name="give-price-id"]').val(), 31 give_is_donation_recurring = parent_form.find('input[name="_give_is_donation_recurring"]').data('_give_recurring'), 32 give_is_price_option = parent_form.find('input[name="_give_is_donation_recurring"]').data('_give_price_option'); 33 34 // Return if donation recurring type is Donor choice. 35 if( 'yes_donor' === give_is_donation_recurring || 'set' === give_is_price_option ) { 36 return false; 37 } 38 39 Give_Recurring.notifyUserOnLevels( parent_form, give_total, price_id ); 40 41 } ); 42 43 /** 44 * Call notify user on gateway change. 45 */ 46 doc.on( 'give_gateway_loaded', function( e, response, form_id ) { 47 48 var form = $( e.currentTarget.activeElement ).closest( 'form.give-form' ); 49 if ( 0 === form.length ) { 50 form = $( '#' + form_id ); 51 } 52
53 var amount = form.find( 'input[name="give-amount"]' ).val(), 54 price_id = form.find( 'input[name="give-price-id"]' ).val(), 55 give_is_donation_recurring = form.find( 'input[name="_give_is_donation_recurring"]' ).data( '_give_recurring' ), 56 give_is_price_option = form.find('input[name="_give_is_donation_recurring"]').data('_give_price_option'); 57 58 // Return if donation recurring type is Donor choice. 59 if ( 'yes_donor' === give_is_donation_recurring || 'set' === give_is_price_option ) { 60 var recurring_period_label = form.find( '.give-recurring-period' ); 61 Give_Recurring.fetchRecurringPeriodText( recurring_period_label ); 62 return false; 63 } 64 65 var decimal = Give.form.fn.getInfo( 'decimal_separator', form ); 66 amount = Give.fn.unFormatCurrency( amount, decimal ); 67 68 Give_Recurring.notifyUserOnLevels( form, amount, price_id ); 69 } ); 70 71 Give_Recurring.confirm_subscription_cancellation(); 72 Give_Recurring.conditional_account_creation(); 73 74 $( '.give-recurring-period' ).on( 'click', function() { 75 var $this = $( this ), 76 form = $this.closest( 'form.give-form' ); 77 78 if ( $this.is( ':checked' ) ) { 79 Give_Recurring.fetchRecurringPeriodText( $this ); 80 } else { 81 form.find( '#give-recurring-modal-period-wrap' ).hide(); 82 form.find( '#give-recurring-modal-period' ).html( '' ); 83 } 84 } ); 85 86 $( '.give-recurring-donors-choice-period' ).on( 'change', function() { 87 88 Give_Recurring.fetchRecurringPeriodText( $( this ) ); 89 }); 90 91 // Trigger formatting function when gateway changes. 92 doc.on( 'give_gateway_loaded', this.conditionalPeriodDropdown );
93 doc.on( 'blur', '.give-donation-amount .give-recurring-text-input', this.edit_renewal_amount ); 94 95 Give_Recurring.conditionalPeriodDropdown(); 96 Give_Recurring.changeGiveIsDonationRecurring(); 97 Give_Recurring.update_payment_method(); 98 }, 99 100 /** 101 * Display Recurring Period Label in Modal PopUp. 102 * 103 * @param label Period Label. 104 * @param form Form. 105 * 106 * @since 1.5.8 107 */ 108 displayModalLabel: function( label, form ) { 109 if ( label !== "once" && label !== "" ) { 110 form.find( '#give-recurring-modal-period-wrap' ).show(); 111 form.find( '#give-recurring-modal-period' ).html( label.charAt(0).toUpperCase() + label.slice(1) ); 112 } else if ( label === "once" ) { 113 form.find( '#give-recurring-modal-period-wrap' ).hide(); 114 form.find( '#give-recurring-modal-period' ).html( '' ); 115 } 116 }, 117 118 /** 119 * Fetch Recurring Period Text 120 * 121 * @param $this this object. 122 * 123 * @since 1.5.8 124 */ 125 fetchRecurringPeriodText: function( $this ) { 126 127 var recurringPeriod = $this.data( 'period' ); 128 var recurringPeriodLabel = $this.data( 'period-label' ); 129 var form = $this.closest( 'form.give-form' ); 130 var currentRecurringPeriod = form.find( '.give-recurring-donors-choice-period' ).val(); 131 var prettyPeriods = Give_Recurring_Vars.pretty_periods; 132 133 if ( $this.is( 'select' ) ) { 134 recurringPeriodLabel = $this.closest( 'div.give-recurring-donors-choice' ) 135 .find( '.give-recurring-period' ) 136 .data( 'period-label' ); 137 recurringPeriod = $this.closest( 'div.give-recurring-donors-choice' ) 138 .find( '.give-recurring-period' ) 139 .data( 'period' ); 140 } 141 142 // Replace texts in label onlt if donor can change the recurring period. 143 if ( currentRecurringPeriod ) { 144 recurringPeriodLabel = recurringPeriodLabel.replace( new RegExp( recurringPeriod, 'g' ), currentRecurringPeriod ); 145 recurringPeriodLabel = recurringPeriodLabel.replace( new RegExp( prettyPeriods[ recurringPeriod ], 'g' ), prettyPeriods[ currentRecurringPeriod ] ); 146 } 147 148 // Display Recurring Label if recurring is opted. 149 if ( this.isRecurringOpted(form) ) { 150 Give_Recurring.displayModalLabel( recurringPeriodLabel, form ); 151 } else { 152 form.find( '#give-recurring-modal-period-wrap' ).hide(); 153 form.find( '#give-recurring-modal-period' ).html( '' ); 154 } 155 }, 156 157 /** 158 * Notify users with message about the type of donation based on level. 159 * 160 * @since 1.4 161 * @since 1.8.1 Remove Ajax and Update message through JS. 162 */ 163 notifyUserOnLevels: function( form, amount, price_id ) { 164
165 var data = JSON.parse( form.find( 'input[name="give_recurring_donation_details"]' ).val() ); 166 167 // Return if form is not recurring or recurring option is donor choice. 168 if ( false === data.is_recurring || 'yes_donor' === data.give_recurring_option ) { 169 return false; 170 } 171 172 var multi_level_message = data.multi[ price_id ].give_recurring_pretty_text, 173 multi_level_lower_message = multi_level_message.toLowerCase(); 174 175 amount = Give.fn.formatCurrency( amount, { 176 currency: Give.form.fn.getInfo( 'currency_code', form ), 177 symbol: Give.form.fn.getInfo( 'currency_symbol', form ), 178 position: Give.form.fn.getInfo( 'currency_position', form ) 179 }, form ); 180 181 var multi_level_message_html = Give_Recurring_Vars.multi_level_message_pre_text + ' <span class="amount">' + amount + '</span> ' + multi_level_lower_message + '.'; 182 183 form.find( '.give-recurring-multi-level-message' ).html( multi_level_message_html ); 184 185 // Update recurring hidden field with the change based on the type of donation. 186 if ( 'once' !== multi_level_lower_message ) { 187 form.find( '#_give_is_donation_recurring' ).val( 1 ); 188 } else { 189 form.find( '#_give_is_donation_recurring' ).val( 0 ); 190 } 191 192 // Display Modal Label when recurring is enabled. 193 Give_Recurring.displayModalLabel( multi_level_message, form ); 194 Give_Recurring.register_checkbox( form ); 195 196 }, 197 198 changeGiveIsDonationRecurring: function () { 199 $( '.give-form' ).on( 'change', '.give-recurring-donors-choice', function () { 200 var give_is_donation_recurring = '0'; 201 var recurring_period = $( this ).find( '.give-recurring-period:checked' ).val(); 202 203 if ( 'undefined' !== typeof( 204 recurring_period 205 ) && 'on' === recurring_period ) { 206 give_is_donation_recurring = 1; 207 } 208 209 var form = $( this ).closest( 'form' ); 210 form.find( '._give_is_donation_recurring' ).val( give_is_donation_recurring ); 211 Give_Recurring.register_checkbox( form ); 212 } ); 213 }, 214 215 /** 216 * Toggle account creation fields if donor elects not to give recurring. 217 * 218 * If email access is not enabled, no guest donations are allowed. 219 * Therefore, if the donor doesn't give recurring no account is necessary. 220 */ 221 conditional_account_creation: function() { 222 223 // Only w/o Email Access Enabled 224 if ( Give_Recurring_Vars.email_access ) { 225 return false; 226 } 227 228 // fire once donation form gateway is change. 229 doc.on( 'give_gateway_loaded', function( ev, response, form_id ) { 230 // Trigger float-labels 231 Give_Recurring.register_checkbox( $( 'form#' + form_id ) ); 232 } ); 233 234 // On Page Load: When page loads loop through each form and show hide fields. 235 $( 'form[id^=give-form].give-recurring-form' ).each( function () { 236 Give_Recurring.register_checkbox( $( this ) ); 237 } ); 238 239 // Preserve Create account checkbox checked on login cancel ajax. 240 $( document ).ajaxComplete( function ( event, xhr, settings ) { 241 var get_action = Give_Recurring.get_parameter( 'action', settings.data ); 242 if ( 'give_cancel_login' === get_action ) { 243 var form_id = Give_Recurring.get_parameter( 'form_id', settings.data ); 244 Give_Recurring.register_checkbox( $( 'form#give-form-' + form_id ) ); 245 } 246 } ); 247 }, 248 249 /** 250 * Get specific parameter value from Query string. 251 * 252 * @param string parameter Parameter of query string. 253 * @param object data Set of data. 254 * 255 * @return bool 256 */ 257 get_parameter: function ( parameter, data ) { 258 259 if ( ! parameter ) { 260 return false; 261 } 262 263 if ( ! data ) { 264 data = window.location.href; 265 } 266 267 var parameter = parameter.replace( /[\[]/, "\\\[" ).replace( /[\]]/, "\\\]" ); 268 var expr = parameter + "=([^&#]*)"; 269 var regex = new RegExp( expr ); 270 var results = regex.exec( data ); 271 272 if ( null !== results ) { 273 return results[1]; 274 } else { 275 return false; 276 } 277 }, 278 279 /** 280 * Disable Enable the register user checkbox 281 * 282 * @since 1.5.5 283 * 284 * @param form 285 */ 286 register_checkbox: function( form ) { 287 288 // Only w/o Email Access Enabled 289 if ( Give_Recurring_Vars.email_access ) { 290 return false; 291 } 292 293 // check if guest donation is allow or not. 294 var recurring_logged = form.find( '.give-logged-in-only' ).val(); 295 296 // if guest donation is not allow then return false. 297 if ( 'undefined' !== typeof( recurring_logged ) && 1 === parseInt( recurring_logged ) ) { 298 var is_recurring = form.find( '._give_is_donation_recurring' ).val(); 299 300 if ( 'undefined' !== typeof( is_recurring ) && 1 === parseInt( is_recurring ) ) { 301 Give_Recurring.disable_register_checkbox( form ); 302 } else { 303 Give_Recurring.enable_register_checkbox( form ); 304 } 305 } 306 }, 307 308 /** 309 * Remove the Disable checkbox option so that user can check and uncheck if s/he want to register or not 310 * 311 * @since 1.5.5 312 * 313 * @param form 314 */ 315 enable_register_checkbox: function ( form ) { 316 var create_account_html = form.find( '[name="give_create_account"]' ); 317 create_account_html.removeClass( 'give-disabled' ); 318 create_account_html.closest( 'span' ).removeClass( 'hint--top hint--bou
318nce' ); 319 }, 320 321 /** 322 * Add the Disable checkbox option so that user can not check and uncheck if s/he want to register or not 323 * 324 * @since 1.5.5 325 * 326 * @param form 327 */ 328 disable_register_checkbox: function ( form ) { 329 var create_account_html = form.find( '[name="give_create_account"]' ); 330 create_account_html.attr( 'checked', true ); 331 create_account_html.addClass( 'give-disabled' ); 332 create_account_html.closest( 'span' ).addClass( 'hint--top hint--bounce' ); 333 }, 334 335 /** 336 * Confirm Cancellation 337 */ 338 confirm_subscription_cancellation: function() { 339 340 $( '.give-cancel-subscription' ).on( 'click touchend', function() { 341 var response = confirm( Give_Recurring_Vars.messages.confirm_cancel ); 342 // Cancel form submit if user rejects confirmation. 343 if ( response !== true ) { 344 return false; 345 } 346 } ); 347 348 }, 349 350 /** 351 * Conditional "Period" dropdown 352 * 353 * Some gateways don't support "daily" frequency. 354 * 355 * @since 1.5 356 */ 357 conditionalPeriodDropdown: function( response ) { 358 359 // Loop through selected gateways on page. 360 $( '.give-gateway-option-selected' ).each( function() { 361 362 var $form = $( this ).parents( '.give-form' ), 363 gateway = $( this ).find( 'input' ).val(), 364 period_select = $form.find( '.give-recurring-donors-choice-period' ), 365 period = period_select.val(), 366 day_option = $form.find( '.give-recurring-donors-choice-period option[value="day"]' ); 367 368 // Authorize doesn't support daily. 369 if ( 'authorize' === gateway || 'razorpay' === gateway ) { 370 371 // Only proceed if day is selected. 372 if ( 'day' !== period ) { 373 return; 374 } 375 376 // Disable and select next option. 377 day_option.prop( 'disabled', true ).next().prop( 'selected', true ); 378 379 // Only show alert when switching gateways and not on page load. 380 if ( 'undefined' !== typeof response ) { 381 alert( Give_Recurring_Vars.messages.daily_forbidden ); 382 } 383 384 } else { 385 386 // Ensure that daily option is disabled. 387 day_option.prop( 'disabled', false ); 388 389 } 390 391 } ); 392 393 }, 394 395 /** 396 * Update Payment method. 397 * 398 * @since 1.7 399 */ 400 update_payment_method: function() { 401 402 $( 'form[name="give-recurring-form"]' ).submit( function( e ) { 403 e.preventDefault(); 404 405 // this form object. 406 var this_form = $( this ), 407 update_button = this_form.find( '#give-recurring-update-submit' ),
408 loading_animation = this_form.find( 'input[type="submit"].give-submit + .give-loading-animation' ), 409 give_payment_update_form = this_form.get( 0 ), 410 complete_purchase_val = this_form.find( '#give-recurring-update-submit' ).val(), 411 action = $( 'input[name="give_action"]' ).val(); 412 413 loading_animation.fadeIn(); 414 415 // HTML5 required check validity. 416 if ( typeof give_payment_update_form.checkValidity === 'function' && give_payment_update_form.checkValidity() === false ) { 417 418 // Don't leave any hanging loading animations. 419 loading_animation.fadeOut(); 420 421 // Check for Safari (doesn't support HTML5 required). 422 if ( (navigator.userAgent.indexOf( 'Safari' ) !== - 1 && navigator.userAgent.indexOf( 'Chrome' ) === - 1) === false ) { 423 // Not safari: Support HTML5 "required" so skip the rest of this function 424 return; 425 } 426 427 } 428 429 /** 430 * Stripe payment method will only update if donor will submit form because Stripe JS SDK need to generate payment method then save it on server. 431 * This code prevent submitting form on ajax if subscription gateway is Stripe. 432 * 433 * @see https://github.com/impress-org/give-recurring/issues/998 434 */ 435 if( 436 -1 !== Give.form.fn.getInfo('gateway', this_form ).indexOf('stripe') && 437 'recurring_update_payment' === action 438 ) { 439 return; 440 } 441 442 // Update submit button text. 443 update_button.val( give_global_vars.purchase_loading ); 444 445 // Disable the form donation button. 446 update_button.attr( 'disabled', 'disabled' ); 447 448 $.ajax( { 449 type: 'POST', 450 url: give_global_vars.ajaxurl, 451 data: this_form.serialize(), 452 success: function( response ) { 453 if ( response.success ) { 454 loading_animation.fadeOut(); 455 this_form.find( '.give_errors' ).remove(); 456 update_button.val( complete_purchase_val ); 457 update_button.prop( 'disabled', false ); 458 } 459 460 window.location.href = response.data.url; 461 } 462 } ); 463 464 } ); 465 }, 466 467 /** 468 * Edit renewal amount. 469 * 470 * @since 1.8 471 */ 472 edit_renewal_amount:function( e, $parent_form ) { 473 var parent_form = ('undefined' !== typeof $parent_form) ? $parent_form : $( this ).closest( 'form' ), 474 this_value = $( this ).val(), 475 decimal_separator = Give.form.fn.getInfo( 'decimal_separator', parent_form ), 476 value_min = Give.form.fn.getMinimumAmount( parent_form ), 477 value_max = Give.form.fn.getMaximumAmount( parent_form ), 478 value_now = (this_value === 0 || '' === this_value ) ? value_min : Give.fn.unFormatCurrency( this_value, decimal_separator ), 479 formatted_total = Give.form.fn.formatAmount( value_now, parent_form, {} ); 480 481 $( this ).val( formatted_total ); 482 483 // Does this number have an accepted min/max value? 484 if ( ! Give_Recurring.isValidRenewalAmount( parent_form ) ) { 485 486 // It doesn't... add invalid class. 487 $( this ).addClass( 'give-invalid-amount' ); 488 489 // Disable submit 490 Give.form.fn.disable( parent_form, true ); 491 var invalid_minimum_notice = parent_form.find( '.give-invalid-minimum' ), 492 invalid_maximum_notice = parent_form.find( '.give-invalid-maximum' ); 493 494 // If no error present, create it, insert, slide down (show). 495 if ( 0 === invalid_minimum_notice.length && value_now < value_min ) { 496 Give.notice.fn.renderNotice( 'bad_minimum', parent_form ); 497 } else if( value_now >= value_min ) { 498 invalid_minimum_notice.slideUp( 300, function() { $( this ).remove(); } ); 499 } 500 501 // For maximum custom amount error. 502 if ( 0 === invalid_maximum_notice.length && value_now > value_max ) { 503 Give.notice.fn.renderNotice( 'bad_maximum', parent_form ); 504 } else if (value_now <= value_max ){ 505 invalid_maximum_notice.slideUp( 300, function() { $( this ).remove(); } ); 506 } 507 508 } else { 509 510 // Remove error message class from price field. 511 $( this ).removeClass( 'give-invalid-amount' ); 512 513 // Minimum amount met - slide up error & remove it from DOM. 514 parent_form.find( '.give-invalid-minimum, .give-invalid-maximum' ).slideUp( 300, function() { 515 $( this ).remove(); 516 } ); 517 518 // Re-enable submit. 519 Give.form.fn.disable( parent_form, false ); 520 } 521 522 // Added this trigger so that we can extend the functionality. 523 doc.trigger( 'give_recurring_donation_amount_updated', [ parent_form, value_now ] ); 524 }, 525 526 /**
527 * Is Renewal amount valid? 528 * 529 * @since 1.8 530 * 531 * @param $form 532 * @returns {boolean} 533 */ 534 isValidRenewalAmount: function( $form ) { 535 // Return true, if custom amount is not enabled. 536 if ( $form.find( 'input[name="give-form-minimum"]' ).length <= 0 ) { 537 return true; 538 } 539 540 var min_amount = Give.form.fn.getMinimumAmount( $form ), 541 max_amount = Give.form.fn.getMaximumAmount( $form ), 542 amount = Give.form.fn.getAmount( $form ); 543 544 // Don't allow zero donation amounts. 545 if ( 0 === amount ) { 546 return false; 547 } 548 549 return ( 550 ((- 1 < amount) && amount >= min_amount && amount <= max_amount) 551 ); 552 }, 553 554 /** 555 * Return whether or not donor opt in for subscription. 556 * 557 * @since 1.11.0 558 * 559 * @param {object} $form 560 * @return {boolean} 561 */ 562 isRecurringOpted: function ($form){ 563 var $field = $form.find( '.give-recurring-period:checked' ); 564 return $field && $field.val(); 565 } 566 }; 567 568 Give_Recurring.init(); 569 570} );
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.