PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.7.2
GiveWP – Donation Plugin and Fundraising Platform v2.7.2
4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / Views / Form / Templates / Sequoia / assets / js / form.js
give / src / Views / Form / Templates / Sequoia / assets / js Last commit date
form.js 5 years ago
form.js
722 lines
1 /* globals jQuery, Give */
2 ( function( $ ) {
3 const templateOptions = window.sequoiaTemplateOptions;
4 const $container = $( '.give-embed-form' );
5 const $advanceButton = $( '.advance-btn', $container );
6 const $backButton = $( '.back-btn' );
7 const $navigatorTitle = $( '.give-form-navigator .title' );
8 const $paymentGatewayContainer = $( '#give-payment-mode-select' );
9 let gatewayAnimating = false;
10
11 const navigator = {
12 currentStep: templateOptions.introduction.enabled === 'enabled' ? 0 : 1,
13 animating: false,
14 goToStep: ( step ) => {
15 // Adjust body height before animating step, to prevent choppy iframe resizing
16 // Compare next step to current step, and increase body height if next step is taller.
17 const nextStepHeight = steps[ step ].title ? $( steps[ step ].selector ).height() + 50 : $( steps[ step ].selector ).height();
18 const currentStepHeight = steps[ navigator.currentStep ].title ? $( steps[ navigator.currentStep ].selector ).height() + 50 : $( steps[ navigator.currentStep ].selector ).height();
19 if ( nextStepHeight > currentStepHeight ) {
20 $( '.give-form-templates' ).css( 'min-height', `${ nextStepHeight + 123 }px` );
21 } else {
22 // Delay setting body height if next step is shorter than current step
23 setTimeout( function() {
24 $( '.give-form-templates' ).css( 'min-height', `${ nextStepHeight + 123 }px` );
25 }, 200 );
26 }
27
28 $( '.step-tracker' ).removeClass( 'current' );
29 $( '.step-tracker[data-step="' + step + '"]' ).addClass( 'current' );
30
31 if ( templateOptions.introduction.enabled === 'disabled' ) {
32 if ( $( '.step-tracker' ).length === 3 ) {
33 $( '.step-tracker' ).remove();
34 }
35
36 step = step > 0 ? step : 1;
37 if ( step === 1 ) {
38 $( '.back-btn', $container ).hide();
39 } else {
40 $( '.back-btn', $container ).show();
41 }
42
43 $( '.give-form-navigator', $container ).addClass( 'nav-visible' );
44 $( steps[ step ].selector ).css( 'padding-top', '50px' );
45 } else if ( step === 0 ) {
46 $( '.give-form-navigator', $container ).removeClass( 'nav-visible' );
47 $( steps[ step ].selector ).css( 'padding-top', '' );
48 } else {
49 $( '.give-form-navigator', $container ).addClass( 'nav-visible' );
50 $( steps[ step ].selector ).css( 'padding-top', '50px' );
51 }
52
53 if ( steps[ step ].title ) {
54 $navigatorTitle.text( steps[ step ].title );
55 }
56
57 const hide = steps.map( ( obj, index ) => {
58 if ( index === step || index === navigator.currentStep ) {
59 return null;
60 }
61 return obj.selector;
62 } );
63 const hideSelector = hide.filter( Boolean ).join( ', ' );
64
65 $( hideSelector ).hide();
66
67 if ( navigator.currentStep !== step ) {
68 const directionClasses = 'slide-in-right slide-in-left slide-out-right slide-out-left';
69 const outDirection = navigator.currentStep < step ? 'left' : 'right';
70 const inDirection = navigator.currentStep < step ? 'right' : 'left';
71 $( steps[ navigator.currentStep ].selector ).removeClass( directionClasses ).addClass( `slide-out-${ outDirection }` );
72 $( steps[ step ].selector ).show().removeClass( directionClasses ).addClass( `slide-in-${ inDirection }` );
73 }
74 navigator.currentStep = step;
75 setupTabOrder();
76
77 setTimeout( function() {
78 if ( steps[ navigator.currentStep ].firstFocus ) {
79 $( steps[ navigator.currentStep ].firstFocus ).focus();
80 }
81 }, 200 );
82 },
83 init: () => {
84 steps.forEach( ( step ) => {
85 if ( step.setup !== undefined ) {
86 step.setup();
87 }
88 $( step.selector ).css( 'position', 'absolute' );
89 } );
90 $advanceButton.on( 'click', function( e ) {
91 e.preventDefault();
92 navigator.forward();
93 } );
94 $backButton.on( 'click', function( e ) {
95 e.preventDefault();
96 navigator.back();
97 } );
98 $( '.step-tracker' ).on( 'click', function( e ) {
99 e.preventDefault();
100 navigator.goToStep( parseInt( $( e.target ).attr( 'data-step' ) ) );
101 } );
102 setupHeightChangeCallback( function( height ) {
103 if ( gatewayAnimating === false ) {
104 $( '.form-footer' ).css( 'transition', 'margin-top 0.2s ease' );
105 } else {
106 $( '.form-footer' ).css( 'transition', '' );
107 }
108 $( '.form-footer' ).css( 'margin-top', `${ height }px` );
109 } );
110 navigator.goToStep( getInitialStep() );
111 },
112 back: () => {
113 const prevStep = navigator.currentStep !== 0 ? navigator.currentStep - 1 : 0;
114 navigator.goToStep( prevStep );
115 navigator.currentStep = prevStep;
116 },
117 forward: () => {
118 const nextStep = navigator.currentStep !== null ? navigator.currentStep + 1 : 1;
119 navigator.goToStep( nextStep );
120 navigator.currentStep = nextStep;
121 },
122 };
123
124 const steps = [
125 {
126 id: 'introduction',
127 title: null,
128 selector: '.give-section.introduction',
129 label: templateOptions.introduction.donate_label,
130 showErrors: false,
131 tabOrder: [
132 '.introduction .advance-btn',
133 '.step-tracker',
134 ],
135 },
136 {
137 id: 'choose-amount',
138 title: templateOptions.payment_amount.header_label,
139 selector: '.give-section.choose-amount',
140 label: templateOptions.payment_amount.next_label,
141 showErrors: false,
142 tabOrder: [
143 'input.give-amount-top',
144 '.give-donation-levels-wrap button',
145 '.give-recurring-period',
146 '.give-recurring-donors-choice-period',
147 '.give_fee_mode_checkbox',
148 '.choose-amount .advance-btn',
149 '.step-tracker',
150 '.back-btn',
151 ],
152 firstFocus: '.give-default-level',
153 setup: () => {
154 // Dynamically set grid columns based on number of buttons
155 const buttonCount = $( '.give-donation-level-btn' ).length;
156 if ( buttonCount === 1 ) {
157 $( '.give-donation-levels-wrap' ).attr( 'style', 'display: none!important;' );
158 } else if ( buttonCount % 2 === 0 && buttonCount < 6 ) {
159 $( '.give-donation-levels-wrap' ).css( 'grid-template-columns', 'repeat(2, minmax(0, 1fr))' );
160 }
161
162 $( '#give-amount' ).on( 'blur', function() {
163 if ( ! Give.form.fn.isValidDonationAmount( $( 'form' ) ) ) {
164 $( '.advance-btn' ).attr( 'disabled', true );
165 } else {
166 $( '.advance-btn' ).attr( 'disabled', false );
167 }
168 } );
169 $( '.give-donation-level-btn' ).each( function() {
170 const hasTooltip = $( this ).attr( 'has-tooltip' );
171 if ( hasTooltip ) {
172 return;
173 }
174
175 const value = $( this ).attr( 'value' );
176 const text = $( this ).text();
177 const symbol = window.give_global_vars.currency_sign;
178 const position = window.give_global_vars.currency_pos;
179
180 if ( value !== 'custom' ) {
181 const html = position === 'before' ? `<div class="currency currency--before">${ symbol }</div>${ value }` : `${ value }<div class="currency currency--after">${ symbol }</div>`;
182 $( this ).html( html );
183 }
184
185 // Setup string to check tooltip label ga
186 const compare = position === 'before' ? symbol + value : value + symbol;
187 // Setup tooltip unless for custom donation level, or if level label matches value
188 if ( value !== 'custom' && text !== compare ) {
189 const wrap = `<span class="give-tooltip hint--top hint--bounce ${ text.length < 50 ? 'narrow' : '' }" style="width: 100%" aria-label="${ text.length < 50 ? text : text.substr( 0, 50 ) + '...' }" rel="tooltip"></span>`;
190 $( this ).wrap( wrap );
191 $( this ).attr( 'has-tooltip', true );
192 }
193 } );
194 },
195 },
196 {
197 id: 'payment',
198 title: templateOptions.payment_information.header_label,
199 label: templateOptions.payment_information.checkout_label,
200 selector: '.give-section.payment',
201 showErrors: true,
202 tabOrder: [
203 '.payment input, .payment a, .payment button, .payment select, .payment multiselect, .payment textarea, .payment .button',
204 '.give-submit',
205 '.step-tracker',
206 '.back-btn',
207 ],
208 firstFocus: '#give-first',
209 setup: () => {
210 // Setup payment information screen
211
212 $( '.give-section.payment' ).on( 'click', '.give-cancel-login, .give-checkout-register-cancel', clearLoginNotices );
213
214 // Show Sequoia loader on click/touchend
215 $( '.give-section.payment' ).on( 'click touchend', 'input[name="give_login_submit"]', function() {
216 //Override submit loader with Sequoia loader
217 $( 'input[name="give_login_submit"] + .give-loading-animation' ).removeClass( 'give-loading-animation' ).addClass( 'sequoia-loader spinning' );
218 } );
219
220 // Remove purchase_loading text
221 window.give_global_vars.purchase_loading = '';
222
223 // Move errors
224 $( '.give_error' ).each( function() {
225 moveErrorNotice( $( this ) );
226 } );
227
228 // Setup anonymouse donations opt-in event listeners
229 setupCheckbox( {
230 container: '#give-anonymous-donation-wrap label',
231 label: '#give-anonymous-donation-wrap label',
232 input: '#give-anonymous-donation',
233 } );
234
235 // Setup recurring donations opt-in event listeners
236 setupCheckbox( {
237 container: '.give-recurring-donors-choice',
238 label: '.give-recurring-donors-choice label',
239 input: 'input[name="give-recurring-period"]',
240 } );
241
242 // Setup fee recovery opt-in event listeners
243 setupCheckbox( {
244 container: '.give-fee-recovery-donors-choice',
245 label: '.give-fee-message-label-text',
246 input: 'input[name="give_fee_mode_checkbox"]',
247 } );
248
249 // Setup mailchimp opt-in event listeners
250 setupCheckbox( {
251 container: '.give-mailchimp-fieldset',
252 label: '.give-mc-message-text',
253 input: 'input[name="give_mailchimp_signup"]',
254 } );
255
256 // Setup constant contact opt-in event listeners
257 setupCheckbox( {
258 container: '.give-constant-contact-fieldset',
259 label: '.give-constant-contact-fieldset span',
260 input: 'input[name="give_constant_contact_signup"]',
261 } );
262
263 // Setup terms and conditions opt-in event listeners
264 setupCheckbox( {
265 container: '#give_terms_agreement',
266 label: '#give_terms_agreement label',
267 input: 'input[name="give_agree_to_terms"]',
268 } );
269
270 // Show Sequoia loader on click/touchend
271 $( 'body.give-form-templates' ).on( 'click touchend', 'form.give-form input[name="give-purchase"].give-submit', function() {
272 //Override submit loader with Sequoia loader
273 $( '#give-purchase-button + .give-loading-animation' ).removeClass( 'give-loading-animation' ).addClass( 'sequoia-loader' );
274
275 // Only show spinner if form is valid
276 if ( $( 'form' ).get( 0 ).checkValidity() ) {
277 $( '.sequoia-loader' ).addClass( 'spinning' );
278 }
279 } );
280
281 // Go to choose amount step when donation maximum error is clicked
282 $( 'body.give-form-templates' ).on( 'click touchend', '#give_error_invalid_donation_maximum', function() {
283 // Go to choose amount step
284 navigator.goToStep( 1 );
285 } );
286
287 // Go to choose amount step when invalid donation error is clicked
288 $( 'body.give-form-templates' ).on( 'click touchend', '#give_error_invalid_donation_amount', function() {
289 // Go to choose amount step
290 navigator.goToStep( 1 );
291 } );
292
293 // Setup gateway icons
294 setupGatewayIcons();
295
296 const observer = new window.MutationObserver( function( mutations ) {
297 mutations.forEach( function( mutation ) {
298 if ( ! mutation.addedNodes ) {
299 return;
300 }
301
302 for ( let i = 0; i < mutation.addedNodes.length; i++ ) {
303 // do things to your newly added nodes here
304 const node = mutation.addedNodes[ i ];
305
306 if ( $( node ).find( '.give_error' ).length > 0 ) {
307 moveErrorNotice( $( node ).find( '.give_error' ) );
308 }
309
310 if ( $( node ).children().hasClass( 'give_errors' ) && ! $( node ).parent().hasClass( 'donation-errors' ) ) {
311 $( node ).children( '.give_errors' ).each( function() {
312 const notice = $( this );
313 moveErrorNotice( notice );
314 } );
315 }
316
317 if ( $( node ).hasClass( 'give_errors' ) && ! $( node ).parent().hasClass( 'donation-errors' ) ) {
318 moveErrorNotice( $( node ) );
319 $( '.sequoia-loader' ).removeClass( 'spinning' );
320 }
321
322 if ( $( node ).attr( 'id' ) === 'give_tributes_address_state' ) {
323 const placeholder = $( node ).attr( 'placeholder' );
324 $( node ).prepend( `<option selected disabled>${ placeholder }</option>` );
325 }
326
327 if ( $( node ).attr( 'name' ) === 'give_tributes_address_state' && $( node ).attr( 'class' ).includes( 'give-input' ) ) {
328 $( node ).attr( 'placeholder', $( node ).siblings( 'label' ).text().trim() );
329 }
330
331 if ( $( node ).attr( 'id' ) && $( node ).attr( 'id' ).includes( 'give-checkout-login-register' ) ) {
332 $( '[id*="give-register-account-fields"]' ).on( 'click', handleFFMInput );
333 }
334
335 if ( $( node ).prop( 'tagName' ) && $( node ).prop( 'tagName' ).toLowerCase() === 'select' ) {
336 const placeholder = $( node ).attr( 'placeholder' );
337 $( node ).prepend( `<option value="" disabled selected>${ placeholder }</option>` );
338 }
339 }
340 } );
341 } );
342
343 observer.observe( document.body, {
344 childList: true,
345 subtree: true,
346 attributes: false,
347 characterData: false,
348 } );
349 },
350 },
351 ];
352
353 navigator.init();
354
355 // Check if only a single gateway is enabled
356 if ( $paymentGatewayContainer.length && $paymentGatewayContainer.css( 'display' ) !== 'none' ) {
357 // Move payment information section when document load.
358 moveFieldsUnderPaymentGateway( true );
359
360 // Move payment information section when gateway updated.
361 $( document ).on( 'give_gateway_loaded', function() {
362 setupTabOrder();
363 moveFieldsUnderPaymentGateway( true );
364 setupSelectInputs();
365 $( '#give_purchase_form_wrap' ).slideDown( 200, function() {
366 gatewayAnimating = false;
367 } );
368 } );
369 $( document ).on( 'Give:onPreGatewayLoad', function() {
370 gatewayAnimating = true;
371 $( '#give_purchase_form_wrap' ).slideUp( 200 );
372 } );
373
374 // Clear gateway related errors
375 $( document ).on( 'Give:onPreGatewayLoad', function() {
376 const persistedNotices = [
377 'give_error_test_mode',
378 ];
379
380 $( '.give_errors, .give_notices, .give_error' ).each( function() {
381 if ( ! persistedNotices.includes( $( this ).attr( 'id' ) ) ) {
382 $( this ).slideUp( 200, function() {
383 $( this ).remove();
384 } );
385 }
386 } );
387 } );
388
389 // Refresh payment information section.
390 $( document ).on( 'give_gateway_loaded', refreshPaymentInformationSection );
391 } else {
392 $( '#give_purchase_form_wrap' ).addClass( 'give-single-gateway-wrap' );
393 setupSelectInputs();
394 }
395
396 /**
397 * Move error notices to error notice container at the top of the payment section
398 * @since 2.7.0
399 * @param {node} node The error notice node to be moved
400 */
401 function moveErrorNotice( node ) {
402 //If the error is inside stripe payment button, do nothing
403 if ( $( node ).parent().hasClass( 'give-stripe-payment-request-button' ) ) {
404 return;
405 }
406
407 // First check if specific donation notice container has been set up
408 if ( $( '.donation-errors' ).length === 0 ) {
409 $( '.payment' ).prepend( '<div class="donation-errors"></div>' );
410 }
411
412 // If a specific notice does not already exist, proceed with moving the error
413 if ( typeof $( '.donation-errors' ).html() !== undefined && ! $( '.donation-errors' ).html().includes( $( node ).html() ) ) {
414 $( node ).appendTo( '.donation-errors' );
415 } else {
416 // If the specific notice already exists, do not add it
417 $( node ).remove();
418 }
419 }
420
421 /**
422 * Add listeners and starting states to FFM inputs
423 * @since 2.7.0
424 */
425 function setupFFMInputs() {
426 $( '#give-ffm-section' ).off( 'click', handleFFMInput );
427 $( '[id*="give-register-account-fields"]' ).off( 'click', handleFFMInput );
428
429 $( '#give-ffm-section' ).on( 'click', handleFFMInput );
430 $( '[id*="give-register-account-fields"]' ).on( 'click', handleFFMInput );
431
432 $( '#give-ffm-section input' ).each( function() {
433 switch ( $( this ).prop( 'type' ) ) {
434 case 'checkbox': {
435 if ( $( this ).prop( 'checked' ) ) {
436 $( this ).parent().addClass( 'checked' );
437 } else {
438 $( this ).parent().removeClass( 'checked' );
439 }
440 break;
441 }
442 case 'radio': {
443 if ( $( this ).prop( 'checked' ) ) {
444 $( this ).parent().addClass( 'selected' );
445 } else {
446 $( this ).parent().removeClass( 'selected' );
447 }
448 break;
449 }
450 }
451 } );
452 }
453
454 /**
455 * Move form field under payment gateway
456 * @since 2.7.0
457 */
458 function moveFieldsUnderPaymentGateway() {
459 // Check if donate fieldset area has been created, if not set it up below payment gateways
460 // This area is necessary for correctly placing various elements (fee recovery notice, newsletters, submit button, etc)
461 if ( $( '#donate-fieldset' ).length === 0 ) {
462 $( '#give-payment-mode-select' ).after( '<fieldset id="donate-fieldset"></fieldset>' );
463 }
464
465 // Elements to move into donate fieldset (located at bottom of form)
466 // The elements will appear in order of array
467 const donateFieldsetElements = [
468 '.give-constant-contact-fieldset',
469 '.give-mailchimp-fieldset',
470 '#give_terms_agreement',
471 '.give-donation-submit',
472 ];
473
474 // Handle moving elements into donate fieldset
475 donateFieldsetElements.forEach( function( selector ) {
476 if ( $( `#donate-fieldset ${ selector }` ).length === 0 ) {
477 $( '#donate-fieldset' ).append( $( `#give_purchase_form_wrap ${ selector }` ) );
478 } else if ( $( `#donate-fieldset ${ selector }` ).html() !== $( `#give_purchase_form_wrap ${ selector }` ).html() ) {
479 $( `#donate-fieldset ${ selector }` ).remove();
480 $( '#donate-fieldset' ).append( $( `#give_purchase_form_wrap ${ selector }` ) );
481 } else {
482 $( `#give_purchase_form_wrap ${ selector }` ).remove();
483 }
484 } );
485
486 // Handle per-Gateway fee option
487 // If the fee recovery option wrapper is present, move it to the choose amount screen
488 if ( $( '#give_purchase_form_wrap fieldset[id*="give-fee-recovery-wrap"]' ).length !== 0 ) {
489 let checked = false;
490 if ( $( '.choose-amount fieldset[id*="give-fee-recovery-wrap"]' ).length !== 0 ) {
491 checked = $( 'input[name="give_fee_mode_checkbox"]' ).prop( 'checked' );
492 $( '.choose-amount fieldset[id*="give-fee-recovery-wrap"]' ).remove();
493 }
494 $( '.choose-amount' ).append( $( '#give_purchase_form_wrap fieldset[id*="give-fee-recovery-wrap"]' ) );
495 $( 'input[name="give_fee_mode_checkbox"]' ).prop( 'checked', checked );
496 }
497
498 // Move purchase fields (credit card, billing, etc)
499 $( 'li.give-gateway-option-selected' ).after( $( '#give_purchase_form_wrap' ) );
500
501 // Add gateway class to fields wrapper, indicating which gateway is active
502 const gatewayClass = 'gateway-' + $( '.give-gateway-option-selected input' ).attr( 'value' ).replace( '_', '-' );
503 $( '#give_purchase_form_wrap' ).attr( 'class', gatewayClass );
504
505 setupFFMInputs();
506 setupInputIcons();
507 }
508
509 /**
510 * Refresh payment information section
511 *
512 * @since 2.7.0
513 * @param {boolean} ev Event object
514 * @param {object} response Response object
515 * @param {number} formID Form ID
516 */
517 function refreshPaymentInformationSection( ev, response, formID ) {
518 if ( navigator.currentStep === 2 ) {
519 $( '.give-form-templates' ).css( 'min-height', '' );
520 }
521
522 const $form = $( `#${ formID }` );
523
524 // This function will run only for embed donation form.
525 // Show payment information section fields.
526 if ( $form.parent().hasClass( 'give-embed-form' ) ) {
527 const data = {
528 action: 'give_cancel_login',
529 form_id: $form.find( '[name="give-form-id"]' ).val(),
530 };
531
532 // AJAX get the payment fields.
533 $.post( Give.fn.getGlobalVar( 'ajaxurl' ), data, function( postResponse ) {
534 $form.find( '[id^=give-checkout-login-register]' ).replaceWith( $.parseJSON( postResponse.fields ) );
535 $form.find( '[id^=give-checkout-login-register]' ).css( { display: 'block' } );
536 $form.find( '.give-submit-button-wrap' ).show();
537 } ).done( function() {
538 // Trigger float-labels
539 window.give_fl_trigger();
540 } );
541 }
542 }
543
544 function setupInputIcon( selector, icon ) {
545 $( selector ).each( function() {
546 if ( $( this ).html() !== '' && $( this ).html().includes( `<i class="fas fa-${ icon }"></i>` ) === false ) {
547 $( this ).prepend( `<i class="fas fa-${ icon }"></i>` );
548 $( this ).children( 'input, selector' ).each( function() {
549 $( this ).attr( 'style', 'padding-left: 33px!important;' );
550 } );
551 }
552 } );
553 }
554
555 function setupInputIcons() {
556 setupInputIcon( '#give-first-name-wrap', 'user' );
557 setupInputIcon( '#give-email-wrap', 'envelope' );
558 setupInputIcon( '#give-company-wrap', 'building' );
559 setupInputIcon( '#date_field-wrap', 'calendar-alt' );
560 setupInputIcon( '#url_field-wrap', 'globe' );
561 setupInputIcon( '#phone_field-wrap', 'phone' );
562 setupInputIcon( '#give-phone-wrap', 'phone' );
563 setupInputIcon( '#email_field-wrap', 'envelope' );
564 }
565
566 /**
567 * Setup tab order for elements in form
568 *
569 * @since 2.7.0
570 */
571 function setupTabOrder() {
572 $( 'select, button, input, textarea, multiselect, a' ).attr( 'tabindex', -1 );
573
574 const tabOrder = steps[ navigator.currentStep ].tabOrder;
575 tabOrder.forEach( ( selector, index ) => {
576 $( selector ).attr( 'tabindex', index + 1 );
577 } );
578 }
579
580 /**
581 * Loop through gateway li elements and setup fontawesome icons
582 *
583 * @since 2.7.0
584 */
585 function setupGatewayIcons() {
586 $( '#give-gateway-radio-list li' ).each( function() {
587 const value = $( 'input', this ).val();
588 let icon;
589 switch ( value ) {
590 case 'manual':
591 icon = 'fas fa-tools';
592 break;
593 case 'offline':
594 icon = 'fas fa-wallet';
595 break;
596 case 'paypal':
597 icon = 'fab fa-paypal';
598 break;
599 case 'stripe':
600 icon = 'far fa-credit-card';
601 break;
602 case 'stripe_checkout':
603 icon = 'far fa-credit-card';
604 break;
605 case 'stripe_sepa':
606 icon = 'fas fa-university';
607 break;
608 case 'stripe_ach':
609 icon = 'fas fa-university';
610 break;
611 case 'stripe_ideal':
612 icon = 'fas fa-university';
613 break;
614 case 'stripe_becs':
615 icon = 'fas fa-university';
616 break;
617 case 'paypalpro_payflow':
618 icon = 'far fa-credit-card';
619 break;
620 case 'stripe_google_pay':
621 icon = 'fab fa-google';
622 break;
623 case 'stripe_apple_pay':
624 icon = 'fab fa-apple';
625 break;
626 default:
627 icon = 'fas fa-hand-holding-heart';
628 break;
629 }
630 $( this ).append( `<i class="${ icon }"></i>` );
631 } );
632 }
633
634 /**
635 * Setup prominent checkboxes (that use persistent borders on select)
636 *
637 * @since 2.7.0
638 * @param {object} args Argument object containing: container, label, input selectors
639 */
640 function setupCheckbox( { container, label, input } ) {
641 // If checkbox is opted in by default, add border on load
642 if ( $( input ).prop( 'checked' ) === true ) {
643 $( container ).addClass( 'active' );
644 }
645
646 // Persist checkbox input border when selected
647 $( label ).on( 'click touchend', function( evt ) {
648 if ( container === label ) {
649 evt.stopPropagation();
650 evt.preventDefault();
651 }
652 $( container ).toggleClass( 'active' );
653 } );
654 }
655
656 function setupHeightChangeCallback( callback ) {
657 let lastHeight = 0;
658 function checkHeightChange() {
659 const selector = $( steps[ navigator.currentStep ].selector );
660 const changed = lastHeight !== $( selector ).outerHeight();
661 if ( changed ) {
662 callback( $( selector ).outerHeight() );
663 lastHeight = $( selector ).outerHeight();
664 }
665 window.requestAnimationFrame( checkHeightChange );
666 }
667 window.requestAnimationFrame( checkHeightChange );
668 }
669
670 /**
671 * Get initial step to show donor.
672 *
673 * @since 2.7.0
674 * @returns {number} Step to start on
675 */
676 function getInitialStep() {
677 return Give.fn.getParameterByName( 'showDonationProcessingError' ) || Give.fn.getParameterByName( 'showFailedDonationError' ) ? 2 : 0;
678 }
679
680 /**
681 * Handle updating label classes for FFM radios and checkboxes
682 *
683 * @since 2.7.0
684 * @param {object} evt Reference to FFM input element click event
685 */
686 function handleFFMInput( evt ) {
687 if ( $( evt.target ).is( 'input' ) ) {
688 switch ( $( evt.target ).prop( 'type' ) ) {
689 case 'checkbox': {
690 $( evt.target ).parent().toggleClass( 'checked' );
691 break;
692 }
693 case 'radio': {
694 $( evt.target ).parent().addClass( 'selected' );
695 $( evt.target ).parent().siblings().removeClass( 'selected' );
696 break;
697 }
698 }
699 }
700 }
701
702 function clearLoginNotices() {
703 $( '#give_error_must_log_in' ).remove();
704 }
705
706 /**
707 * Setup select inputs
708 *
709 * @since 2.7.0
710 */
711 function setupSelectInputs() {
712 if ( $( 'select option[selected="selected"][value=""]' ).length > 0 ) {
713 $( 'select option[selected="selected"][value=""]' ).each( function() {
714 if ( $( this ).parent().siblings( 'label' ).length ) {
715 $( this ).text( $( this ).parent().siblings( 'label' ).text().replace( '*', '' ).trim() );
716 $( this ).attr( 'disabled', true );
717 }
718 } );
719 }
720 }
721 }( jQuery ) );
722