PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.1
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.1
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
charitable / assets / js / charitable.js

charitable.js in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0.1, at assets/js/charitable.js

1,024 lines 28.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 CHARITABLE = window.CHARITABLE || {};
2
3 /**
4 * Set up Donation_Form object.
5 */
6 ( function( exports, $ ) {
7
8 /**
9 * Donation_Form expects a jQuery this.form object.
10 */
11 var Donation_Form = function( form ) {
12
13 /**
14 * Array of errors.
15 *
16 * @access public
17 */
18 this.errors = [];
19
20 /**
21 * Pending processes array.
22 *
23 * @access public
24 */
25 this.pending_processes = [];
26
27 /**
28 * Form object.
29 *
30 * @access public
31 */
32 this.form = form;
33
34 /**
35 * Flag to allow processing to be paused (i.e. while something like Stripe is processing).
36 *
37 * @access public
38 */
39 this.pause_processing = false;
40
41 /**
42 * Flag to prevent the on_submit handler from sending multiple concurrent AJAX requests
43 *
44 * @access public
45 */
46 this.submit_processing = false;
47
48 /**
49 * The donation amount.
50 *
51 * @access public
52 */
53 this.total = 0;
54
55 /**
56 * Whether to scroll to the top of the form after a submission with errors.
57 *
58 * @access private
59 */
60 this.prevent_scroll_to_top = false;
61
62 /**
63 * Reference to this object.
64 *
65 * @access private
66 */
67 var self = this;
68
69 /**
70 * Body element reference.
71 *
72 * @access private
73 */
74 var $body = $( 'body' );
75
76 /**
77 * Handle click of terms link.
78 *
79 * @access private
80 */
81 var on_click_terms = function() {
82 self.form.find( '.charitable-terms-text' ).addClass( 'active' );
83 return false;
84 };
85
86 /**
87 * Focus event handler on custom donation amount input field.
88 *
89 * @access private
90 */
91 var on_focus_custom_amount = function() {
92 $( this ).closest( 'li' ).trigger( 'click' ).find( 'input[name=donation_amount]' ).prop( 'checked', true ).trigger( 'change' );
93
94 self.form.off( 'focus', 'input.custom-donation-input', on_focus_custom_amount );
95
96 $( this ).focus();
97
98 self.form.on( 'focus', 'input.custom-donation-input', on_focus_custom_amount );
99 };
100
101 /**
102 * Trigger jQuery events to broadcast the change in donation amount.
103 *
104 * @since 1.6.19
105 *
106 * @access private
107 */
108 var trigger_amount_change_events = function() {
109 /* The chosen donation amount has changed. */
110 $body.trigger( 'charitable:form:amount:changed', self );
111
112 /* The overall donation amount has changed. */
113 $body.trigger( 'charitable:form:total:changed', self );
114 };
115
116 /**
117 * Focus event handler for changes to custom donation amount input field.
118 *
119 * @access private
120 */
121 var on_change_custom_donation_amount = function() {
122 var unformatted = self.unformat_amount( $( this ).val() );
123
124 if ( $.trim( unformatted ) > 0 ) {
125 $( this ).val( self.format_amount( unformatted ) );
126 }
127
128 trigger_amount_change_events();
129 };
130
131 /**
132 * Select a donation amount.
133 *
134 * @return void
135 */
136 var on_select_donation_amount = function() {
137 var $li = $( this ).closest( 'li' );
138
139 // Already selected, quit early to prevent focus/change loop
140 if ( $li.hasClass( 'selected' ) ) {
141 return;
142 }
143
144 $li.parents( '.charitable-donation-form' ).find( '.donation-amount.selected' ).removeClass( 'selected' );
145
146 $li.addClass( 'selected' ).find( '[name=donation_amount]' ).prop( 'checked', true );
147
148 if ( $li.hasClass( 'custom-donation-amount' ) ) {
149 $li.find( 'input.custom-donation-input' ).focus();
150 }
151
152 trigger_amount_change_events();
153 };
154
155 /**
156 * Change event handler for payment gateway selector.
157 *
158 * @access private
159 */
160 var on_change_payment_gateway = function() {
161 self.hide_inactive_payment_methods();
162 self.show_active_payment_methods( $(this).val() );
163 };
164
165 /**
166 * Event handler when the "Change" link is clicked for pre-filled donations.
167 */
168 var on_click_change_amount_link = function() {
169 $(this).parent().addClass( 'charitable-hidden' );
170 };
171
172 /**
173 * Submit event handler for donation form.
174 *
175 * @access private
176 */
177 var on_submit = function( event ) {
178 var helper = event.data.helper;
179
180 if ( helper.submit_processing ) {
181 return false;
182 }
183
184 helper.submit_processing = true;
185
186 /* Display the processing spinner and hide the button */
187 helper.show_processing();
188
189 /* Validate the form submission before going further. */
190 if ( false === helper.validate() ) {
191 helper.cancel_processing();
192 return false;
193 }
194
195 /* If processing has been paused, return false now. */
196 if ( false !== helper.pause_processing ) {
197 return false;
198 }
199
200 /* If we're not using AJAX to process the donation further, return now. */
201 if ( 1 !== helper.form.data( 'use-ajax' ) ) {
202 return true;
203 }
204
205 /* Continue on to process the donation. */
206 maybe_process( helper, function() {
207 $body.trigger( 'charitable:form:process', helper );
208 } );
209
210 return false;
211 };
212
213 /**
214 * Check whether there are any asynchronous threads we need to wait for.
215 *
216 * If not, trigger processing. If there are, check again in 500ms.
217 */
218 var maybe_process = function( helper, callback ) {
219 if ( ! helper.waiting() ) {
220 /* Double-check that there are still no errors. */
221 if ( helper.get_errors().length > 0 ) {
222 helper.cancel_processing();
223 } else {
224 callback();
225 }
226
227 return;
228 }
229
230 setTimeout( maybe_process, 500, helper, callback );
231 }
232
233 /**
234 * Process the donation.
235 *
236 * This is a callback for the 'charitable:form:process' event. It's called
237 * after validation has taken place.
238 *
239 * @param object Event
240 * @param object Donation_Form
241 */
242 var process_donation = function( event, helper ) {
243 var data = helper.get_data();
244 var form = helper.form;
245
246 /* Cancel the default Charitable action, but pass it along as the form_action variable */
247 data.action = 'make_donation';
248 data.form_action = data.charitable_action;
249 delete data.charitable_action;
250
251 $.ajax({
252 type: "POST",
253 data: data,
254 dataType: "json",
255 url: CHARITABLE_VARS.ajaxurl,
256 timeout: 0,
257 xhrFields: {
258 withCredentials: true
259 },
260 success: function (response) {
261 $body.trigger( 'charitable:form:processed', [ response, helper ] );
262
263 if ( response.success ) {
264 maybe_process( helper, function() {
265 window.location.href = response.redirect_to;
266 } );
267 }
268 else {
269 helper.cancel_processing( response.errors );
270
271 if ( response.donation_id ) {
272 helper.set_donation_id( response.donation_id );
273 }
274 }
275 }
276 }).fail(function (response, textStatus, errorThrown) {
277 if ( window.console && window.console.log ) {
278 console.log( response );
279 }
280
281 helper.cancel_processing( [ CHARITABLE_VARS.error_unknown ] );
282 });
283
284 return false;
285 }
286
287 /**
288 * Set up event handlers for donation forms.
289 *
290 * @return void
291 */
292 var init = function() {
293 // Init donation amount selection
294 self.form.on( 'click', '.donation-amount', on_select_donation_amount );
295 self.form.on( 'focus', 'input.custom-donation-input', on_focus_custom_amount );
296 self.form.on( 'click', '.charitable-terms-link', on_click_terms );
297
298 // Init currency formatting
299 self.form.on( 'blur', '.custom-donation-input', on_change_custom_donation_amount );
300
301 self.form.find( '.donation-amount input:checked' ).each( function() {
302 $( this ).closest( 'li' ).addClass( 'selected' );
303 });
304
305 if ( self.get_all_payment_methods().length ) {
306 self.hide_inactive_payment_methods();
307 self.form.on( 'change', '#charitable-gateway-selector input[name=gateway]', on_change_payment_gateway );
308 }
309
310 self.form.on( 'click', '.change-donation', on_click_change_amount_link );
311
312 // Handle donation form submission
313 self.form.on( 'submit', {
314 helper : self,
315 }, on_submit );
316
317 // This only fires after the first form instance is initialized.
318 if ( false === CHARITABLE.forms_initialized ) {
319
320 // Process the donation on the 'charitable:form:process' event.
321 $body.on( 'charitable:form:process', process_donation );
322
323 $body.trigger( 'charitable:form:initialize', self );
324
325 CHARITABLE.forms_initialized = true;
326 }
327
328 $body.trigger( 'charitable:form:loaded', self );
329 }
330
331 init();
332 };
333
334 /**
335 * Return a particular input field.
336 *
337 * @param string The field name to retrieve.
338 * @return object
339 */
340 Donation_Form.prototype.get_input = function( field ) {
341 return this.form.find( '[name=' + field + ']' );
342 }
343
344 /**
345 * Return the submitted email address.
346 *
347 * @return string
348 */
349 Donation_Form.prototype.get_email = function() {
350 return this.form.find( '[name=email]' ).val();
351 };
352
353 /**
354 * Returns whether this is a recurring donation.
355 *
356 * @since 1.4.21
357 *
358 * @return boolean
359 */
360 Donation_Form.prototype.is_recurring_donation = function() {
361 var recurring = this.form.find( '[name=recurring_donation]:checked, [name=recurring_donation][type=hidden]' );
362
363 return recurring.length && 'once' !== recurring.val();
364 };
365
366 /**
367 * Get the chosen suggested amount.
368 *
369 * Note that when no option has been selected, or a custom donation amount has been added,
370 * this will return 0.
371 *
372 * @since 1.4.19
373 *
374 * @return float
375 */
376 Donation_Form.prototype.get_suggested_amount = function() {
377 return accounting.unformat(
378 this.form.find( '[name=donation_amount]:checked, input[type=hidden][name=donation_amount]' ).val(),
379 CHARITABLE_VARS.currency_format_decimal_sep
380 );
381 }
382
383 /**
384 * Get the custom amount.
385 *
386 * Note that this will return 0 when no custom amount has been entered or a 0 has been entered.
387 *
388 * @since 1.4.19
389 *
390 * @return float
391 */
392 Donation_Form.prototype.get_custom_amount = function() {
393 var input = this.form.find( '.charitable-donation-options.active input.custom-donation-input,.charitable-donation-options.active input.custom-donation-amount' );
394
395 if ( 0 === input.length ) {
396 input = this.form.find( 'input.custom-donation-input' );
397 }
398
399 return accounting.unformat(
400 input.val(),
401 CHARITABLE_VARS.currency_format_decimal_sep
402 );
403 }
404
405 /**
406 * Get the donation subtotal, which is the amount passed by the donor.
407 *
408 * Notably, this does not include any additional amounts that may be added onto the donation
409 * total, such as processing fees that the donor agrees to pay.
410 *
411 * @since 1.6.7
412 *
413 * @return float
414 */
415 Donation_Form.prototype.get_subtotal = function() {
416 return this.get_suggested_amount() || this.get_custom_amount();
417 };
418
419 /**
420 * Get the submitted amount, taking into account both the custom & suggested donation fields.
421 *
422 * @return float
423 */
424 Donation_Form.prototype.get_amount = function() {
425 this.total = this.get_subtotal();
426
427 this.form.trigger( 'charitable:form:get_amount', this );
428
429 return this.total;
430 };
431
432 /**
433 * Get the submitted amount, taking into account both the custom & suggested donation fields.
434 *
435 * @since 1.6.8
436 *
437 * @param float add
438 * @return void
439 */
440 Donation_Form.prototype.add_amount = function( add ) {
441 this.total += add;
442 };
443
444 /**
445 * Get the submitted amount, taking into account both the custom & suggested donation fields.
446 *
447 * @since 1.6.8
448 *
449 * @param float remove Amount to be removed
450 * @return void
451 */
452 Donation_Form.prototype.remove_amount = function( remove ) {
453 this.total -= remove;
454 };
455
456 /**
457 * Get a description of the donation.
458 *
459 * @return string
460 */
461 Donation_Form.prototype.get_description = function() {
462 return this.form.find( '[name=description]' ).val() || '';
463 };
464
465 /**
466 * Get credit card number.
467 *
468 * @return string
469 */
470 Donation_Form.prototype.get_cc_number = function() {
471 return this.form.find( '#charitable_field_cc_number input' ).val() || '';
472 };
473
474 /**
475 * Get credit card CVC number.
476 *
477 * @return string
478 */
479 Donation_Form.prototype.get_cc_cvc = function() {
480 return this.form.find( '#charitable_field_cc_cvc input' ).val() || '';
481 };
482
483 /**
484 * Get credit card expiry month.
485 *
486 * @return string
487 */
488 Donation_Form.prototype.get_cc_expiry_month = function() {
489 return this.form.find( '#charitable_field_cc_expiration select.month' ).val() || '';
490 };
491
492 /**
493 * Get credit card expiry year.
494 *
495 * @return string
496 */
497 Donation_Form.prototype.get_cc_expiry_year = function() {
498 return this.form.find( '#charitable_field_cc_expiration select.year' ).val() || '';
499 };
500
501 /**
502 * Clear credit card fields.
503
504 *
505 * This is used by gateways that create tokens through Javascript (such as Stripe), to
506 * avoid credit card details hitting the server.
507 *
508 * @return void
509 */
510 Donation_Form.prototype.clear_cc_fields = function() {
511 this.form.find( '#charitable_field_cc_number input, #charitable_field_cc_name input, #charitable_field_cc_cvc input, #charitable_field_cc_expiration select' ).removeAttr( 'name' );
512 };
513
514 /**
515 * Return the selected payment method.
516 *
517 * @return string
518 */
519 Donation_Form.prototype.get_payment_method = function() {
520 return this.form.find( '[type=hidden][name=gateway], [name=gateway]:checked' ).val() || '';
521 };
522
523 /**
524 * Return all payment methods.
525 *
526 * @return object
527 */
528 Donation_Form.prototype.get_all_payment_methods = function() {
529 return this.form.find( '#charitable-gateway-selector input[name=gateway]' );
530 }
531
532 /**
533 * Hide inactive payment methods.
534 *
535 * @return void
536 */
537 Donation_Form.prototype.hide_inactive_payment_methods = function() {
538 var active = this.get_payment_method();
539 var fields = this.form.find( '.charitable-gateway-fields[data-gateway!=' + active + ']' );
540
541 fields.hide();
542 fields.find( 'input[required],select[required],textarea[required]' ).attr( 'data-required', 1 ).attr( 'required', false );
543 };
544
545 /**
546 * Show active payment methods.
547 *
548 * @return void
549 */
550 Donation_Form.prototype.show_active_payment_methods = function( active ) {
551 var active = active || this.get_payment_method();
552 var fields = this.form.find( '.charitable-gateway-fields[data-gateway=' + active + ']' );
553
554 fields.show();
555 fields.find( '[data-required]' ).attr( 'required', true );
556 };
557
558 /**
559 * Select a donation amount.
560 *
561 * @param int price
562 * @param string symbol
563 * @return string
564 */
565 Donation_Form.prototype.format_amount = function( price, symbol ){
566 if ( typeof symbol === 'undefined' )
567 symbol = '';
568
569 return accounting.formatMoney( price, {
570 symbol : symbol,
571 decimal : CHARITABLE_VARS.currency_format_decimal_sep,
572 thousand: CHARITABLE_VARS.currency_format_thousand_sep,
573 precision : CHARITABLE_VARS.currency_format_num_decimals,
574 format: CHARITABLE_VARS.currency_format
575 }).trim();
576 };
577
578 /**
579 * Select a donation amount.
580 *
581 * @param int price
582 * @return string
583 */
584 Donation_Form.prototype.unformat_amount = function( price ) {
585 return Math.abs( parseFloat( accounting.unformat( price, CHARITABLE_VARS.currency_format_decimal_sep ) ) );
586 };
587
588 /**
589 * Add an error message.
590 *
591 * @param string message
592 * @return void
593 */
594 Donation_Form.prototype.add_error = function( message ) {
595 this.errors.push( message );
596 };
597
598 /**
599 * Return the errors.
600 *
601 * @return []
602 */
603 Donation_Form.prototype.get_errors = function() {
604 return this.errors;
605 };
606
607 /**
608 * Prints out a nice string describing the errors.
609 *
610 * @return string
611 */
612 Donation_Form.prototype.get_error_message = function() {
613 return this.errors.join( ' ' );
614 };
615
616 /**
617 * Print the errors at the top of the form.
618 *
619 * @param array
620 */
621 Donation_Form.prototype.print_errors = function( errors ) {
622 var e = errors || this.errors,
623 i = 0,
624 count = e.length,
625 output = '';
626
627 if ( 0 === count ) {
628 return;
629 }
630
631 if ( this.form.find( '.charitable-form-errors' ).length ) {
632 this.form.find( '.charitable-form-errors' ).remove();
633 }
634
635 output += '<div class="charitable-form-errors charitable-notice"><ul class="errors"><li>';
636 output += e.join( '</li><li>' );
637 output += '</li></ul></div>';
638
639 this.form.prepend( output );
640 }
641
642 /**
643 * Clear the errors and remove the printed errors.
644 */
645 Donation_Form.prototype.clear_errors = function() {
646 this.errors = [];
647
648 if ( this.form.find( '.charitable-form-errors' ).length ) {
649 this.form.find( '.charitable-form-errors' ).remove();
650 }
651 }
652
653 /**
654 * Return whether we are waiting for an asynchronous process to finish.
655 *
656 * @since 1.6.9
657 *
658 * @return boolean
659 */
660 Donation_Form.prototype.waiting = function() {
661 return this.pending_processes.length > 0;
662 }
663
664 /**
665 * Add a pending process.
666 *
667 * @since 1.6.9
668 *
669 * @param string Process identifier.
670 * @return int Index of the process.
671 */
672 Donation_Form.prototype.add_pending_process = function( process ) {
673 var index = this.pending_processes.indexOf( process );
674 return -1 === index ? ( this.pending_processes.push( process ) - 1 ) : index;
675 }
676
677 /**
678 * Remove a pending process by index.
679 *
680 * @since 1.6.9
681 *
682 * @param int Index of the process.
683 * @return void
684 */
685 Donation_Form.prototype.remove_pending_process = function( index ) {
686 this.pending_processes.splice( index, 1 );
687 }
688
689 /**
690 * Remove a pending process by process name.
691 *
692 * @since 1.6.17
693 *
694 * @param string Name of the process.
695 * @return void
696 */
697 Donation_Form.prototype.remove_pending_process_by_name = function( process ) {
698 var index = this.pending_processes.indexOf( process );
699 return -1 !== index && this.remove_pending_process( index );
700 }
701
702 /**
703 * Show that the donation form is processing.
704 */
705 Donation_Form.prototype.show_processing = function() {
706 this.form.find( '.charitable-form-processing' ).show();
707 this.form.find( 'button[name="donate"]' ).hide();
708 }
709
710 /**
711 * Hide the processing spinner and show the donate button.
712 */
713 Donation_Form.prototype.hide_processing = function() {
714 this.form.find( '.charitable-form-processing' ).hide();
715 this.form.find( 'button[name="donate"]' ).show();
716
717 this.submit_processing = false;
718 this.pause_processing = false;
719 }
720
721 /**
722 * Scroll to the top of the form.
723 */
724 Donation_Form.prototype.scroll_to_top = function() {
725 if ( this.prevent_scroll_to_top ) {
726 this.prevent_scroll_to_top = false;
727 return;
728 }
729
730 var $modal = this.form.parents( '.charitable-modal' );
731
732 if ( $modal.length ) {
733 $modal.scrollTop( 0 );
734 }
735 else {
736 window.scrollTo( this.form.offset().left, this.form.offset().top );
737 }
738 };
739
740 /**
741 * Cancel donation processing.
742 *
743 * @param array errors Error messages to show.
744 */
745 Donation_Form.prototype.cancel_processing = function( errors ) {
746 this.hide_processing();
747 this.print_errors( errors );
748 this.scroll_to_top();
749
750 this.form.trigger( 'charitable:form:cancelled', this );
751 };
752
753 /**
754 * Set the donation ID.
755 */
756 Donation_Form.prototype.set_donation_id = function( donation_id ) {
757 this.form.find( '[name=ID]' ).val( donation_id );
758 }
759
760 /**
761 * Returns all of the submitted data as key=>value object.
762 *
763 * @return object
764 */
765 Donation_Form.prototype.get_data = function() {
766 return this.form.serializeArray().reduce( function( obj, item ) {
767 if ( '[]' === item.name.slice( -2 ) ) {
768 var name = item.name.slice( 0, -2 );
769
770 if ( ! obj.hasOwnProperty( name ) ) {
771 obj[name] = [];
772 }
773
774 obj[name].push( item.value );
775 } else {
776 obj[ item.name ] = item.value;
777 }
778
779 return obj;
780 }, {} );
781
782 };
783
784 /**
785 * Returns all of the required fields.
786 *
787 * @return object
788 */
789 Donation_Form.prototype.get_required_fields = function() {
790 var fields = this.form.find( '.charitable-fieldset .required-field' ).not( '#charitable-gateway-fields .required-field' ),
791 method = this.get_payment_method();
792
793 if ( '' !== method ) {
794
795 var gateway_fields = this.form.find( '[data-gateway=' + method + '] .required-field' );
796
797 if ( gateway_fields.length ) {
798 fields = $.merge( fields, gateway_fields );
799 }
800
801 }
802
803 return fields;
804 };
805
806 /**
807 * Check whether the submitted amount is greater than the maximum permitted.
808 *
809 * @returns boolean
810 */
811 Donation_Form.prototype.subtotal_exceeds_maximum = function() {
812 return '' !== CHARITABLE_VARS.maximum_donation && this.get_subtotal() > parseFloat( CHARITABLE_VARS.maximum_donation );
813 }
814
815 /**
816 * Make sure that the submitted amount is valid.
817 *
818 * @return boolean
819 */
820 Donation_Form.prototype.is_valid_amount = function() {
821 var minimum = parseFloat( CHARITABLE_VARS.minimum_donation );
822
823 if ( this.subtotal_exceeds_maximum() ) {
824 return false;
825 }
826
827 return minimum > 0 || CHARITABLE_VARS.permit_0_donation
828 ? this.get_subtotal() >= minimum
829 : this.get_subtotal() > minimum;
830 };
831
832 /**
833 * Validate the amount. If not valid, set an error.
834 *
835 * @return boolean
836 */
837 Donation_Form.prototype.validate_amount = function() {
838 if ( false === this.is_valid_amount() ) {
839 if ( this.get_subtotal() > 0 && this.subtotal_exceeds_maximum() ) {
840 this.add_error( CHARITABLE_VARS.error_max_exceeded );
841 } else {
842 this.add_error( CHARITABLE_VARS.error_invalid_amount );
843 }
844 return false;
845 }
846
847 return true;
848 };
849
850 /**
851 * Verify that all required fields are filled out.
852 *
853 * @return boolean
854 */
855 Donation_Form.prototype.validate_required_fields = function() {
856 var has_all_required_fields = true;
857
858 this.get_required_fields().each( function() {
859 if ( '' === $( this ).find( 'input, select, textarea' ).val() ) {
860 has_all_required_fields = false;
861 }
862 });
863
864 if ( ! has_all_required_fields ) {
865 this.add_error( CHARITABLE_VARS.error_required_fields );
866 }
867
868 return has_all_required_fields;
869 };
870
871 /**
872 * Verifies the submission and returns true if it all looks ok.
873 *
874 * @param this.form The submitted form.
875 * @return boolean
876 */
877 Donation_Form.prototype.validate = function() {
878 /* First clear out the errors. */
879 this.clear_errors();
880
881 this.validate_amount();
882
883 this.validate_required_fields();
884
885 this.form.trigger( 'charitable:form:validate', this );
886
887 return this.errors.length === 0;
888 };
889
890 exports.Donation_Form = Donation_Form;
891
892 })( CHARITABLE, jQuery );
893
894 /**
895 * Set up Toggle object.
896 */
897 ( function( exports, $ ){
898 var Toggle = function() {
899
900 /**
901 * Hide toggle target.
902 */
903 var hide_target = function() {
904 get_target( $(this) ).addClass( 'charitable-hidden' );
905 };
906
907 /**
908 * Get the target element.
909 */
910 var get_target = function( $el ) {
911 var target = $el.data('charitable-toggle');
912
913 if ( target[0] !== '.' && target[0] !== '#' ) {
914 target = '#' + target;
915 }
916
917 return $( target );
918 }
919
920 /**
921 * Toggle event handler for any fields with the [data-charitable-toggle] attribute.
922 *
923 * @access private
924 */
925 var on_toggle = function() {
926 var $this = $( this ),
927 $target = get_target( $this );
928
929 $target.toggleClass( 'charitable-hidden', ( function(){
930 if ( $this.is( ':checkbox' ) ) {
931 return ! $this.is( ':checked' );
932 }
933 return false === $target.hasClass( 'charitable-hidden' );
934 })()
935 );
936
937 return false;
938 };
939
940 /**
941 * Initializing function.
942 */
943 var init = function() {
944 $( '[data-charitable-toggle]' ).each( hide_target );
945 };
946
947 // Initialization only required once.
948 $( 'body' ).on( 'click', '[data-charitable-toggle]', on_toggle );
949
950 // Check whether content is being loaded from the session.
951 if ( exports.content_loading ) {
952 var timer = setInterval(function(){
953 if ( false === exports.content_loading ) {
954 init();
955 clearInterval(timer);
956 }
957 }, 500);
958 }
959
960 // Initialization that will be performed everytime
961 return init;
962 }
963
964 exports.Toggle = Toggle();
965
966 })( CHARITABLE, jQuery );
967
968
969 /**
970 * Do a version check.
971 *
972 * @since 1.6.19
973 *
974 * @param string version The version we are comparing with.
975 * @param string compare If compare is left empty, use the Charitable version.
976 * @return integer|boolean
977 */
978 CHARITABLE.VersionCompare = function( version, compare ) {
979 compare = compare || CHARITABLE_VARS.version;
980
981 if ( typeof version + typeof compare != 'stringstring')
982 return false;
983
984 var a = version.split( '.' ),
985 b = compare.split( '.' ),
986 i = 0,
987 len = Math.max( a.length, b.length );
988
989 for ( ; i < len; i++ ) {
990 if ((a[i] && !b[i] && parseInt(a[i]) > 0) || (parseInt(a[i]) > parseInt(b[i]))) {
991 return 1;
992 } else if ((b[i] && !a[i] && parseInt(b[i]) > 0) || (parseInt(a[i]) < parseInt(b[i]))) {
993 return -1;
994 }
995 }
996
997 return 0;
998 };
999
1000 /***
1001 * Finally queue up all the scripts.
1002 */
1003 ( function( $ ) {
1004
1005 /**
1006 * Prevent re-initializing form handlers.
1007 */
1008 CHARITABLE.forms_initialized = false;
1009
1010 $( document ).ready( function() {
1011
1012 $( 'html' ).addClass( 'js' );
1013
1014 var forms = [];
1015
1016 $( '.charitable-donation-form' ).each( function() {
1017 forms.push( new CHARITABLE.Donation_Form( $( this ) ) );
1018 });
1019
1020 CHARITABLE.Toggle();
1021 });
1022
1023 })( jQuery );
1024