PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.0.1
GiveWP – Donation Plugin and Fundraising Platform v2.0.1
4.16.3 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 / assets / js / admin / admin-scripts.js
give / assets / js / admin Last commit date
tinymce 9 years ago admin-forms.js 8 years ago admin-forms.min.js 8 years ago admin-scripts.js 8 years ago admin-scripts.min.js 8 years ago admin-settings.js 8 years ago admin-settings.min.js 8 years ago admin-shortcodes.js 9 years ago admin-shortcodes.min.js 9 years ago admin-widgets.js 8 years ago admin-widgets.min.js 8 years ago
admin-scripts.js
3074 lines
1 /*!
2 * Give Admin JS
3 *
4 * @description: The Give Admin scripts
5 * @package: Give
6 * @subpackage: Assets/JS
7 * @copyright: Copyright (c) 2016, WordImpress
8 * @license: http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 */
10
11 jQuery.noConflict();
12 // Provided access to global level.
13 var give_setting_edit = false;
14 (function ($) {
15 /**
16 * Show/Hide ajax loader.
17 *
18 * @since 2.0
19 *
20 * @param $parent
21 * @param args
22 */
23 var giveAjaxLoader = function ($parent, args) {
24 args = jQuery.extend(
25 {
26 wrapper: true,
27 show: false
28 },
29 args
30 );
31
32 var $loaderParent = args.wrapper ? $('.give-spinner-wrapper', $parent) : {},
33 $loader = $('.give-spinner', $parent);
34
35 // Show loader.
36 if (args.show) {
37 if ($loaderParent.length) {
38 $loaderParent.addClass('is-active');
39 }
40
41 $loader.addClass('is-active');
42 return;
43 }
44
45 // Hide loader.
46 if ($loaderParent.length) {
47 $loaderParent.removeClass('is-active');
48 }
49
50 $loader.removeClass('is-active');
51 };
52
53 /**
54 * Onclick remove give-message parameter from url
55 *
56 * @since 1.8.14
57 */
58 var give_dismiss_notice = function () {
59 $('body').on('click', 'button.notice-dismiss', function () {
60 if ('give-invalid-license' !== jQuery(this).closest('div.give-notice').data('notice-id')) {
61 give_remove_give_message();
62 }
63 });
64 };
65
66 /**
67 * Remove give-message parameter from URL.
68 *
69 * @since 1.8.14
70 */
71 var give_remove_give_message = function () {
72 var parameter = 'give-message',
73 url = document.location.href,
74 urlparts = url.split('?');
75
76 if (urlparts.length >= 2) {
77 var urlBase = urlparts.shift();
78 var queryString = urlparts.join("?");
79
80 var prefix = encodeURIComponent(parameter) + '=';
81 var pars = queryString.split(/[&;]/g);
82 for (var i = pars.length; i-- > 0;) {
83 if (pars[i].lastIndexOf(prefix, 0) !== -1) {
84 pars.splice(i, 1);
85 }
86 }
87 url = urlBase + '?' + pars.join('&');
88 window.history.pushState('', document.title, url); // added this line to push the new url directly to url bar .
89 }
90 return url;
91 };
92
93 /**
94 * Setup Admin Datepicker
95 * @since: 1.0
96 */
97 var enable_admin_datepicker = function () {
98
99 // Date picker.
100 if ($('.give_datepicker').length > 0) {
101 var dateFormat = 'mm/dd/yy';
102 $('.give_datepicker').datepicker({
103 dateFormat: dateFormat
104 });
105 }
106 };
107
108 /**
109 * Setup Pretty Chosen Select Fields
110 */
111 var setup_chosen_give_selects = function () {
112
113 // Setup Chosen Selects.
114 var $give_chosen_containers = $('.give-select-chosen');
115
116 // Add loader with each input field.
117 $give_chosen_containers.on('chosen:ready', function () {
118 $(this).next('.chosen-container')
119 .find('input.chosen-search-input')
120 .after('<span class="spinner"></span>');
121 });
122
123 // No results returned from search trigger.
124 $give_chosen_containers.on('chosen:no_results', function () {
125 var $container = $(this).next('.chosen-container'),
126 $no_results_li = $container.find('li.no-results'),
127 error_string = '';
128
129 if ($container.hasClass('give-select-chosen-ajax') && $no_results_li.length) {
130 error_string = give_vars.chosen.ajax_search_msg.replace('{search_term}', '"' + $('input', $container).val() + '"');
131 } else {
132 error_string = give_vars.chosen.no_results_msg.replace('{search_term}', '"' + $('input', $container).val() + '"');
133 }
134
135 $no_results_li.html(error_string);
136
137 });
138
139 // Initiate chosen.
140 $give_chosen_containers.chosen({
141 inherit_select_classes: true,
142 placeholder_text_single: give_vars.one_option,
143 placeholder_text_multiple: give_vars.one_or_more_option
144 });
145
146 // Fix: Chosen JS - Zero Width Issue.
147 // @see https://github.com/harvesthq/chosen/issues/472#issuecomment-344414059
148 $( '.chosen-container' ).each( function() {
149 if ( 0 === $( this ).width() ) {
150 $( this ).css( 'width', '100%' );
151 }
152 });
153
154 // This fixes the Chosen box being 0px wide when the thickbox is opened.
155 $( '#post' ).on( 'click', '.give-thickbox', function() {
156 $( '.give-select-chosen', '#choose-give-form' ).css( 'width', '100%' );
157 });
158
159 // Variables for setting up the typing timer.
160 var typingTimer; // Timer identifier.
161 var doneTypingInterval = 342; // Time in ms, Slow - 521ms, Moderate - 342ms, Fast - 300ms.
162
163 // Replace options with search results.
164 $(document.body).on('keyup', '.give-select.chosen-container .chosen-search input, .give-select.chosen-container .search-field input', function (e) {
165
166 var val = $(this).val(),
167 $container = $(this).closest('.give-select-chosen'),
168 select = $container.prev(),
169 $search_field = $container.find('input[type="text"]'),
170 variations = $container.hasClass('variations'),
171 lastKey = e.which,
172 search_type = 'give_forms_search';
173
174 // Detect if we have a defined search type, otherwise default to donation forms.
175 if ($container.prev().data('search-type')) {
176
177 // Don't trigger AJAX if this select has all options loaded.
178 if ('no_ajax' === select.data('search-type')) {
179 return;
180 }
181
182 search_type = 'give_' + select.data('search-type') + '_search';
183 }
184
185 // Don't fire if short or is a modifier key (shift, ctrl, apple command key, or arrow keys).
186 if (
187 val.length <= 3 ||
188 !search_type.length ||
189 (
190 ( 9 === lastKey ) || // Tab.
191 ( 13 === lastKey ) || // Enter.
192 ( 16 === lastKey ) || // Shift.
193 ( 17 === lastKey ) || // Ctrl.
194 ( 18 === lastKey ) || // Alt.
195 ( 19 === lastKey ) || // Pause, Break.
196 ( 20 === lastKey ) || // CapsLock.
197 ( 27 === lastKey ) || // Esc.
198 ( 33 === lastKey ) || // Page Up.
199 ( 34 === lastKey ) || // Page Down.
200 ( 35 === lastKey ) || // End.
201 ( 36 === lastKey ) || // Home.
202 ( 37 === lastKey ) || // Left arrow.
203 ( 38 === lastKey ) || // Up arrow.
204 ( 39 === lastKey ) || // Right arrow.
205 ( 40 === lastKey ) || // Down arrow.
206 ( 44 === lastKey ) || // PrntScrn.
207 ( 45 === lastKey ) || // Insert.
208 ( 144 === lastKey ) || // NumLock.
209 ( 145 === lastKey ) || // ScrollLock.
210 ( 91 === lastKey ) || // WIN Key (Start).
211 ( 93 === lastKey ) || // WIN Menu.
212 ( 224 === lastKey ) || // Command key.
213 ( 112 <= lastKey && 123 >= lastKey ) // F1 to F12 lastKey.
214 )
215 ) {
216 return;
217 }
218 clearTimeout(typingTimer);
219 $container.addClass('give-select-chosen-ajax');
220
221 typingTimer = setTimeout(
222 function () {
223 $.ajax({
224 type: 'GET',
225 url: ajaxurl,
226 data: {
227 action: search_type,
228 s: val
229 },
230 dataType: 'json',
231 beforeSend: function () {
232 select.closest('ul.chosen-results').empty();
233 $search_field.prop('disabled', true);
234 },
235 success: function (data) {
236
237 $container.removeClass('give-select-chosen-ajax');
238
239 // Remove all options but those that are selected.
240 $('option:not(:selected)', select).remove();
241
242 if (data.length) {
243 $.each(data, function (key, item) {
244
245 // Add any option that doesn't already exist.
246 if (!$('option[value="' + item.id + '"]', select).length) {
247 select.prepend('<option value="' + item.id + '">' + item.name + '</option>');
248 }
249 });
250
251 // Trigger update event.
252 $container.prev('select.give-select-chosen').trigger('chosen:updated');
253
254 } else {
255
256 // Trigger no result message event.
257 $container.prev('select.give-select-chosen').trigger('chosen:no_results');
258 }
259
260 // Ensure the original query is retained within the search input.
261 $search_field.prop('disabled', false);
262 $search_field.val(val).focus();
263
264 }
265 }).fail(function (response) {
266 if (window.console && window.console.log) {
267 console.log(response);
268 }
269 }).done(function (response) {
270 $search_field.prop('disabled', false);
271 });
272 },
273 doneTypingInterval
274 );
275 });
276
277 $('.give-select-chosen .chosen-search input').each(function () {
278 var type = $(this).parent().parent().parent().prev('select.give-select-chosen').data('search-type');
279 var placeholder = '';
280
281 if ('form' === type) {
282 placeholder = give_vars.search_placeholder;
283 } else {
284 type = 'search_placeholder_' + type;
285 if (give_vars[type]) {
286 placeholder = give_vars[type];
287 }
288 }
289 $(this).attr('placeholder', placeholder);
290
291 });
292
293 };
294
295 /**
296 * Unformat Currency
297 *
298 * @use string give_vars.currency_decimals Number of decimals
299 *
300 * @param {string} price Price
301 * @param {number|bool} dp Number of decimals
302 *
303 * @returns {string}
304 */
305 function give_unformat_currency(price, dp) {
306 price = accounting.unformat(price, give_vars.decimal_separator).toString();
307 dp = ( 'undefined' === dp ? false : dp );
308
309 // Set default value for number of decimals.
310 if (false !== dp) {
311 price = parseFloat(price).toFixed(dp);
312 } else {
313
314 // If price do not have decimal value then set default number of decimals.
315 price = parseFloat(price).toFixed(give_vars.currency_decimals);
316 }
317
318 return price;
319 }
320
321 /**
322 * List donation screen JS
323 */
324
325 var GiveListDonation = {
326
327 init: function () {
328 this.deleteSingleDonation();
329 this.resendSingleDonationReceipt();
330 },
331
332 deleteSingleDonation: function () {
333 $('body').on('click', '.delete-single-donation', function () {
334 return confirm(give_vars.delete_payment);
335 });
336 },
337
338 resendSingleDonationReceipt: function () {
339 $('body').on('click', '.resend-single-donation-receipt', function () {
340 return confirm(give_vars.resend_receipt);
341 });
342 }
343
344 };
345
346 /**
347 * Edit donation screen JS
348 */
349 var Give_Edit_Donation = {
350
351 init: function () {
352 this.edit_address();
353 this.add_note();
354 this.remove_note();
355 this.new_donor();
356 this.resend_receipt();
357 this.variable_price_list();
358 },
359
360 edit_address: function () {
361
362 // Update base state field based on selected base country.
363 $('select[name="give-payment-address[0][country]"]').change(function () {
364 var $this = $(this);
365
366 data = {
367 action: 'give_get_states',
368 country: $this.val(),
369 field_name: 'give-payment-address[0][state]'
370 };
371 $.post(ajaxurl, data, function (response) {
372
373 // Show the states dropdown menu.
374 $this.closest('.column-container').find('#give-order-address-state-wrap').removeClass('give-hidden');
375
376 // Add support to zip fields.
377 $this.closest( '.column-container' ).find( '.give-column' ).removeClass( 'column-full' );
378 $this.closest( '.column-container' ).find( '.give-column' ).addClass( 'column' );
379
380 var state_wrap = $( '#give-order-address-state-wrap' );
381 state_wrap.find( '*' ).not( '.order-data-address-line' ).remove();
382 if ( typeof ( response.states_found ) !== undefined && true === response.states_found ) {
383 state_wrap.append( response.data );
384 state_wrap.find( 'select' ).chosen();
385 } else {
386 state_wrap.append( '<input type="text" name="give-payment-address[0][state]" value="' + response.default_state + '" class="give-edit-toggles medium-text"/>' );
387
388 if ( typeof ( response.show_field ) !== undefined && false === response.show_field ) {
389 // Hide the states dropdown menu.
390 $this.closest( '.column-container' ).find( '#give-order-address-state-wrap' ).addClass( 'give-hidden' );
391
392 // Add support to zip fields.
393 $this.closest( '.column-container' ).find( '.give-column' ).addClass( 'column-full' );
394 $this.closest( '.column-container' ).find( '.give-column' ).removeClass( 'column' );
395 }
396 }
397 });
398
399 return false;
400 });
401
402 },
403
404 add_note: function () {
405
406 $('#give-add-payment-note').on('click', function (e) {
407 e.preventDefault();
408 var postData = {
409 action: 'give_insert_payment_note',
410 payment_id: $(this).data('payment-id'),
411 note: $('#give-payment-note').val()
412 };
413
414 if (postData.note) {
415
416 $.ajax({
417 type: 'POST',
418 data: postData,
419 url: ajaxurl,
420 success: function (response) {
421 $('#give-payment-notes-inner').append(response);
422 $('.give-no-payment-notes').hide();
423 $('#give-payment-note').val('');
424 }
425 }).fail(function (data) {
426 if (window.console && window.console.log) {
427 console.log(data);
428 }
429 });
430
431 } else {
432 var border_color = $('#give-payment-note').css('border-color');
433 $('#give-payment-note').css('border-color', 'red');
434 setTimeout(function () {
435 $('#give-payment-note').css('border-color', border_color);
436 }, 500);
437 }
438
439 });
440
441 },
442
443 remove_note: function () {
444
445 $('body').on('click', '.give-delete-payment-note', function (e) {
446
447 e.preventDefault();
448
449 if (confirm(give_vars.delete_payment_note)) {
450
451 var postData = {
452 action: 'give_delete_payment_note',
453 payment_id: $(this).data('payment-id'),
454 note_id: $(this).data('note-id')
455 };
456
457 $.ajax({
458 type: 'POST',
459 data: postData,
460 url: ajaxurl,
461 success: function (response) {
462 $('#give-payment-note-' + postData.note_id).remove();
463 if (!$('.give-payment-note').length) {
464 $('.give-no-payment-notes').show();
465 }
466 return false;
467 }
468 }).fail(function (data) {
469 if (window.console && window.console.log) {
470 console.log(data);
471 }
472 });
473 return true;
474 }
475
476 });
477
478 },
479
480 new_donor: function () {
481
482 $('#give-donor-details').on('click', '.give-payment-new-donor, .give-payment-new-donor-cancel', function (e) {
483 e.preventDefault();
484 $('.donor-info').toggle();
485 $('.new-donor').toggle();
486
487 if ($('.new-donor').is(':visible')) {
488 $('#give-new-donor').val(1);
489 } else {
490 $('#give-new-donor').val(0);
491 }
492
493 });
494
495 },
496
497 resend_receipt: function () {
498 $('body').on('click', '#give-resend-receipt', function (e) {
499 return confirm(give_vars.resend_receipt);
500 });
501 },
502
503
504 variable_price_list: function () {
505 // Update variable price list when form changes.
506 $('#give_payment_form_select').chosen().change(function () {
507 var give_form_id,
508 variable_prices_html_container = $('.give-donation-level');
509
510 // Check for form ID.
511 if (!( give_form_id = $(this).val() )) {
512 return false;
513 }
514
515 // Bailout.
516 if (!variable_prices_html_container.length) {
517 return false;
518 }
519
520 // Ajax.
521 $.ajax({
522 type: 'POST',
523 url: ajaxurl,
524 data: {
525 form_id: give_form_id,
526 payment_id: $('input[name="give_payment_id"]').val(),
527 action: 'give_check_for_form_price_variations_html'
528 },
529 success: function (response) {
530 response = response.trim();
531 if (response) {
532
533 // Update Variable price html.
534 variable_prices_html_container.html(response);
535
536 // Add chosen feature to select tag.
537 $('select[name="give-variable-price"]').chosen().change();
538 } else {
539 // Update Variable price html.
540 variable_prices_html_container.html('');
541 }
542 }
543 });
544 });
545
546 // Add total donation amount if level changes.
547 $( '#give-donation-overview' ).on( 'change', 'select[name="give-variable-price"]', function () {
548 var prices = jQuery( this ).data( 'prices' ),
549 $total_amount = $( '#give-payment-total' );
550
551 if ( '' !== prices && $( this ).val() in prices ) {
552
553 $total_amount.val( prices[ $( this ).val() ] ).css( 'background-color', 'yellow' );
554
555 window.setTimeout(
556 function () {
557 $total_amount.css( 'background-color', 'white' );
558 },
559 1000
560 );
561 }
562 } );
563 }
564
565 };
566
567 /**
568 * Settings screen JS
569 */
570 var Give_Settings = {
571
572 init: function () {
573 this.setting_change_country();
574 this.toggle_options();
575 this.main_setting_update_notice();
576 this.verify_settings();
577 this.saveButtonTriggered();
578 this.changeAlert();
579 this.detectSettingsChange();
580 },
581
582 /**
583 * Fire when user change the country from the dropdown
584 *
585 * @since 1.8.14
586 */
587 setting_change_country: function () {
588 $('select[name="base_country"]').change(function () {
589 var $this = $(this);
590 var data = {
591 action: 'give_get_states',
592 country: $this.val(),
593 field_name: 'base_state',
594 };
595
596 $.post(ajaxurl, data, function (response) {
597 // Show the states dropdown menu.
598 $this.closest('tr').next().show()
599 if (typeof ( response.states_found ) != undefined && true == response.states_found) {
600 $(':input[name="base_state"]').replaceWith(response.data);
601 } else {
602 if (typeof ( response.show_field ) != undefined && false == response.show_field) {
603 // Hide the states dropdown menu.
604 $this.closest('tr').next().hide();
605 }
606 $(':input[name="base_state"]').replaceWith('<input type="text" name="' + data.field_name + '" value="' + response.default_state + '" class="give-edit-toggles medium-text"/>');
607 }
608 });
609 return false;
610 });
611 },
612
613 toggle_options: function() {
614
615 /**
616 * Email access
617 */
618 var emailAccess = $( 'input[name="email_access"]', '.give-setting-tab-body-general' );
619 emailAccess.on( 'change', function() {
620 var fieldValue = $( 'input[name="email_access"]:checked', '.give-setting-tab-body-general' ).val();
621 if ( 'enabled' === fieldValue ) {
622 $( '#recaptcha_key' ).parents( 'tr' ).show();
623 $( '#recaptcha_secret' ).parents( 'tr' ).show();
624 } else {
625 $( '#recaptcha_key' ).parents( 'tr' ).hide();
626 $( '#recaptcha_secret' ).parents( 'tr' ).hide();
627 }
628 }).change();
629
630 /**
631 * Form featured image
632 */
633 var form_featured_image = $('input[name="form_featured_img"]', '.give-setting-tab-body-display');
634 form_featured_image.on('change', function () {
635 var field_value = $('input[name="form_featured_img"]:checked', '.give-setting-tab-body-display').val();
636 if ('enabled' === field_value) {
637 $('#featured_image_size').parents('tr').show();
638 } else {
639 $('#featured_image_size').parents('tr').hide();
640 }
641 }).change();
642
643 /**
644 * Terms and Conditions
645 */
646 var terms_and_conditions = $('input[name="terms"]', '.give-setting-tab-body-display');
647 terms_and_conditions.on('change', function () {
648 var field_value = $('input[name="terms"]:checked', '.give-setting-tab-body-display').val();
649 if ('enabled' === field_value) {
650 $('#agree_to_terms_label').parents('tr').show();
651 $('#wp-agreement_text-wrap').parents('tr').show();
652 } else {
653 $('#agree_to_terms_label').parents('tr').hide();
654 $('#wp-agreement_text-wrap').parents('tr').hide();
655 }
656 }).change();
657
658 /**
659 * Disable admin notification
660 */
661 var admin_notification = $('input[name="admin_notices"]', '.give-setting-tab-body-emails');
662 admin_notification.on('change', function () {
663 var field_value = $('input[name="admin_notices"]:checked', '.give-setting-tab-body-emails').val();
664 if ('enabled' === field_value) {
665 $('#donation_notification_subject').parents('tr').show();
666 $('#wp-donation_notification-wrap').parents('tr').show();
667 $('#admin_notice_emails').parents('tr').show();
668 } else {
669 $('#donation_notification_subject').parents('tr').hide();
670 $('#wp-donation_notification-wrap').parents('tr').hide();
671 $('#admin_notice_emails').parents('tr').hide();
672 }
673 }).change();
674 },
675
676 main_setting_update_notice: function () {
677 var $setting_message = $('#setting-error-give-setting-updated');
678 if ($setting_message.length) {
679
680 // auto hide setting message in 5 seconds.
681 window.setTimeout(
682 function () {
683 $setting_message.slideUp();
684 },
685 5000
686 );
687 }
688 },
689
690 verify_settings: function () {
691 var success_setting = $('#success_page');
692 var failure_setting = $('#failure_page');
693
694 /**
695 * Verify success and failure page.
696 */
697 success_setting.add(failure_setting).change(function () {
698 if (success_setting.val() === failure_setting.val()) {
699 var notice_html = '<div id="setting-error-give-matched-success-failure-page" class="updated settings-error notice is-dismissible"> <p><strong>' + give_vars.matched_success_failure_page + '</strong></p> <button type="button" class="notice-dismiss"><span class="screen-reader-text">' + give_vars.dismiss_notice_text + '</span></button> </div>',
700 $notice_container = $('#setting-error-give-matched-success-failure-page');
701
702 // Unset setting field.
703 $(this).val('');
704
705 // Bailout.
706 if ($notice_container.length) {
707 return false;
708 }
709
710 // Add html.
711 $('h1', '#give-mainform').after(notice_html);
712 $notice_container = $('#setting-error-give-matched-success-failure-page');
713
714 // Add event to dismiss button.
715 $('.notice-dismiss', $notice_container).click(function () {
716 $notice_container.remove();
717 });
718 }
719 }).change();
720 },
721
722 saveButtonTriggered: function() {
723 $( '.give-settings-setting-page' ).on( 'click', '.give-save-button', function() {
724 $( window ).unbind( 'beforeunload' );
725 });
726 },
727
728 /**
729 * Show alert when admin try to reload the page with saving the changes.
730 *
731 * @since 1.8.14
732 */
733 changeAlert: function () {
734
735 $( window ).bind( 'beforeunload', function ( e ) {
736
737 var confirmationMessage = give_vars.setting_not_save_message;
738
739 if ( give_setting_edit ) {
740 ( e || window.event ).returnValue = confirmationMessage; //Gecko + IE.
741 return confirmationMessage; //Webkit, Safari, Chrome.
742 }
743 });
744 },
745
746 /**
747 * Display alert in setting page of give if user try to reload the page with saving the changes.
748 *
749 * @since 1.8.14
750 */
751 detectSettingsChange: function() {
752
753 var settingsPage = $( '.give-settings-setting-page' );
754
755 // Check if it give setting page or not.
756 if ( settingsPage.length > 0 ) {
757
758 // Get the default value.
759 var on_load_value = $( '#give-mainform' ).serialize();
760
761 /**
762 * Keyup event add to support to text box and textarea.
763 * blur event add to support to dropdown.
764 * Change event add to support to rest all element.
765 */
766 settingsPage.on( 'change keyup blur', 'form', function() {
767 // Get the form value after change.
768 var on_change_value = $( '#give-mainform' ).serialize();
769
770 // If both the value are same then no change has being made else change has being made.
771 give_setting_edit = ( on_load_value !== on_change_value ) ? true : false;
772
773 } );
774 }
775 }
776
777 };
778
779 /**
780 * Reports / Exports / Tools screen JS
781 */
782 var Give_Reports = {
783
784 init: function () {
785 this.date_options();
786 this.donors_export();
787 this.recount_stats();
788 },
789
790 date_options: function () {
791
792 // Show hide extended date options.
793 $('#give-graphs-date-options').change(function () {
794 var $this = $(this);
795 if ('other' === $this.val()) {
796 $('#give-date-range-options').show();
797 } else {
798 $('#give-date-range-options').hide();
799 }
800 });
801
802 },
803
804 donors_export: function () {
805
806 // Show / hide Donation Form option when exporting donors.
807 $('#give_donor_export_form').change(function () {
808
809 var $this = $(this),
810 form_id = $('option:selected', $this).val(),
811 customer_export_option = $('#give_customer_export_option');
812
813 if ('0' === $this.val()) {
814 customer_export_option.show();
815 } else {
816 customer_export_option.hide();
817 }
818
819 var price_options_select = $('.give_price_options_select');
820
821 // On Form Select, Check if Variable Prices Exist.
822 if (parseInt(form_id) != 0) {
823 var data = {
824 action: 'give_check_for_form_price_variations',
825 form_id: form_id,
826 all_prices: true
827 };
828
829 $.post(ajaxurl, data, function (response) {
830 price_options_select.remove();
831 $('#give_donor_export_form_chosen').after(response);
832 });
833 } else {
834 price_options_select.remove();
835 }
836
837 });
838
839 },
840
841 recount_stats: function () {
842
843 $('body').on('change', '#recount-stats-type', function () {
844
845 var export_form = $('#give-tools-recount-form');
846 var selected_type = $('option:selected', this).data('type');
847 var submit_button = $('#recount-stats-submit');
848 var forms = $('.tools-form-dropdown');
849
850 // Reset the form
851 export_form.find('.notice-wrap').remove();
852 submit_button.removeClass('button-disabled').attr('disabled', false);
853 forms.hide();
854 $('.give-recount-stats-descriptions span').hide();
855
856 if ('reset-stats' === selected_type) {
857 export_form.append('<div class="notice-wrap"></div>');
858 var notice_wrap = export_form.find('.notice-wrap');
859 notice_wrap.html('<div class="notice notice-warning"><p><input type="checkbox" id="confirm-reset" name="confirm_reset_store" value="1" /> <label for="confirm-reset">' + give_vars.reset_stats_warn + '</label></p></div>');
860 submit_button.addClass('button-disabled').attr('disabled', 'disabled');
861
862 // Add check when admin try to delete all the test donors.
863 } else if ('delete-test-donors' === selected_type) {
864 export_form.append('<div class="notice-wrap"></div>');
865 var notice_wrap = export_form.find('.notice-wrap');
866 notice_wrap.html('<div class="notice notice-warning"><p><input type="checkbox" id="confirm-reset" name="confirm_reset_store" value="1" /> <label for="confirm-reset">' + give_vars.delete_test_donor + '</label></p></div>');
867 submit_button.addClass('button-disabled').attr('disabled', 'disabled');
868 // Add check when admin try to delete all the imported donations.
869 } else if ('delete-import-donors' === selected_type) {
870
871 export_form.append('<div class="notice-wrap"></div>');
872 var notice_wrap = export_form.find('.notice-wrap');
873 notice_wrap.html('<div class="notice notice-warning"><p><input type="checkbox" id="confirm-reset" name="confirm_reset_store" value="1" /> <label for="confirm-reset">' + give_vars.delete_import_donor + '</label></p></div>');
874 submit_button.addClass('button-disabled').attr('disabled', 'disabled');
875 } else {
876 forms.hide();
877 forms.val(0);
878 }
879
880 current_forms = $('.tools-form-dropdown-' + selected_type);
881 current_forms.show();
882 current_forms.find('.give-select-chosen').css({
883 'width': 'auto',
884 'min-width': '250px'
885 });
886 $('#' + selected_type).show();
887 });
888
889 $('body').on('change', '#confirm-reset', function () {
890 var checked = $(this).is(':checked');
891 if (checked) {
892 $('#recount-stats-submit').removeClass('button-disabled').removeAttr('disabled');
893 } else {
894 $('#recount-stats-submit').addClass('button-disabled').attr('disabled', 'disabled');
895 }
896 });
897
898 $('#give-tools-recount-form').submit(function (e) {
899 var selection = $('#recount-stats-type').val();
900 var export_form = $(this);
901 var selected_type = $('option:selected', this).data('type');
902
903 if ('reset-stats' === selected_type) {
904 var is_confirmed = $('#confirm-reset').is(':checked');
905 if (is_confirmed) {
906 return true;
907 } else {
908 has_errors = true;
909 }
910 }
911
912 export_form.find('.notice-wrap').remove();
913
914 export_form.append('<div class="notice-wrap"></div>');
915 var notice_wrap = export_form.find('.notice-wrap');
916 var has_errors = false;
917
918 if (null === selection || 0 === selection) {
919 // Needs to pick a method give_vars.batch_export_no_class.
920 notice_wrap.html('<div class="updated error"><p>' + give_vars.batch_export_no_class + '</p></div>');
921 has_errors = true;
922 }
923
924 if ('recount-form' === selected_type) {
925
926 var selected_form = $('select[name="form_id"]').val();
927 if (selected_form == 0) {
928 // Needs to pick give_vars.batch_export_no_reqs.
929 notice_wrap.html('<div class="updated error"><p>' + give_vars.batch_export_no_reqs + '</p></div>');
930 has_errors = true;
931 }
932
933 }
934
935 if (has_errors) {
936 export_form.find('.button-disabled').removeClass('button-disabled');
937 return false;
938 }
939 });
940 }
941
942 };
943
944 /**
945 * Export screen JS
946 */
947 var Give_Export = {
948
949 init: function () {
950 this.submit();
951 this.dismiss_message();
952 },
953
954 submit: function () {
955
956 var self = this;
957
958 $(document.body).on('submit', '.give-export-form', function (e) {
959 e.preventDefault();
960
961 var submitButton = $(this).find('input[type="submit"]');
962
963 if (!submitButton.hasClass('button-disabled')) {
964
965 var data = $(this).serialize();
966
967 submitButton.addClass('button-disabled');
968 $( 'form.give-export-form select' ).attr( 'disabled', true ).trigger("chosen:updated");
969 $(this).find('.notice-wrap').remove();
970 $(this).append('<div class="notice-wrap give-clearfix"><span class="spinner is-active"></span><div class="give-progress"><div></div></div></div>');
971
972 // start the process
973 self.process_step(1, data, self);
974
975 }
976
977 });
978 },
979
980 process_step: function (step, data, self) {
981 /**
982 * Do not allow user to reload the page
983 *
984 * @since 1.8.14
985 */
986 give_setting_edit = true;
987
988 var reset_form = false;
989
990 $.ajax({
991 type: 'POST',
992 url: ajaxurl,
993 data: {
994 form: data,
995 action: 'give_do_ajax_export',
996 step: step,
997 },
998 dataType: 'json',
999 success: function (response) {
1000 if ('done' == response.step || response.error || response.success) {
1001
1002 /**
1003 * Now allow user to reload the page
1004 *
1005 * @since 1.8.14
1006 */
1007 give_setting_edit = false;
1008
1009 reset_form = true;
1010
1011 // We need to get the actual in progress form, not all forms on the page
1012 var export_form = $('.give-export-form').find('.give-progress').parent().parent();
1013 var notice_wrap = export_form.find('.notice-wrap');
1014 export_form.find('.button-disabled').removeClass('button-disabled');
1015 $( 'form.give-export-form select' ).attr( 'disabled', false ).trigger("chosen:updated");
1016 if (response.error) {
1017 var error_message = response.message;
1018 notice_wrap.html('<div class="updated error"><p>' + error_message + '</p></div>');
1019 } else if (response.success) {
1020 var success_message = response.message;
1021 notice_wrap.html('<div id="give-batch-success" class="updated notice is-dismissible"><p>' + success_message + '<span class="notice-dismiss"></span></p></div>');
1022 } else {
1023 notice_wrap.remove();
1024 window.location = response.url;
1025 }
1026 } else {
1027 $('.give-progress div').animate({
1028 width: response.percentage + '%',
1029 }, 50, function () {
1030 // Animation complete.
1031 });
1032 self.process_step(parseInt(response.step), data, self);
1033 }
1034
1035 if ( true === reset_form ) {
1036 // Reset the form for preventing multiple ajax request.
1037 $( '#give-tools-recount-form' )[ 0 ].reset();
1038 $( '#give-tools-recount-form .tools-form-dropdown' ).hide();
1039 $( '#give-tools-recount-form .tools-form-dropdown-recount-form-select' ).val('0').trigger('chosen:updated');
1040 }
1041 }
1042 }).fail(function (response) {
1043 /**
1044 * Now allow user to reload the page
1045 *
1046 * @since 1.8.14
1047 */
1048 give_setting_edit = false;
1049
1050 if (window.console && window.console.log) {
1051 console.log(response);
1052 }
1053 $('.notice-wrap').append(response.responseText);
1054 });
1055 },
1056
1057 dismiss_message: function () {
1058 $('body').on('click', '#give-batch-success .notice-dismiss', function () {
1059 $('#give-batch-success').parent().slideUp('fast');
1060 });
1061 }
1062
1063 };
1064
1065 /**
1066 * Updates screen JS
1067 */
1068 var Give_Updates = {
1069 el: {},
1070
1071 init: function () {
1072 this.submit();
1073 this.dismiss_message();
1074 },
1075
1076 submit: function () {
1077 var $self = this, step = 1, resume_update_step = 0;
1078
1079 $self.el.main_container = Give_Selector_Cache.get('#give-db-updates');
1080 $self.el.update_link = Give_Selector_Cache.get('.give-update-button a', $self.el.main_container);
1081 $self.el.run_upload_container = Give_Selector_Cache.get('.give-run-database-update', $self.el.progress_main_container);
1082 $self.el.progress_main_container = Give_Selector_Cache.get('.progress-container', $self.el.main_container);
1083 $self.el.heading = Give_Selector_Cache.get('.update-message', $self.el.progress_main_container);
1084 $self.el.progress_container = Give_Selector_Cache.get('.progress-content', $self.el.progress_main_container);
1085 $self.el.update_progress_counter = Give_Selector_Cache.get( $( '.give-update-progress-count') );
1086
1087 if( $self.el.main_container.data('resume-update') ) {
1088 $self.el.update_link.addClass('active').hide().removeClass('give-hidden');
1089
1090 if( ! $('#give-restart-upgrades').length ) {
1091 window.setTimeout(Give_Updates.get_db_updates_info, 1000, $self );
1092 }
1093 }
1094
1095 // Bailout.
1096 if ($self.el.update_link.hasClass('active')) {
1097 return;
1098 }
1099
1100 $self.el.update_link.on('click', '', function (e) {
1101 e.preventDefault();
1102
1103 $self.el.run_upload_container.find('.notice').remove();
1104 $self.el.run_upload_container.append('<div class="notice notice-error non-dismissible give-run-update-containt"><p> <a href="#" class="give-run-update-button button">' + give_vars.db_update_confirmation_msg_button + '</a> ' + give_vars.db_update_confirmation_msg + '</p></div>');
1105 });
1106
1107 $('#give-db-updates').on('click', 'a.give-run-update-button', function (e) {
1108 e.preventDefault();
1109
1110 if ($(this).hasClass('active')) {
1111 return false;
1112 }
1113
1114 $(this).addClass('active').fadeOut();
1115 $self.el.update_link.addClass('active').fadeOut();
1116 $('#give-db-updates .give-run-update-containt').slideUp();
1117
1118 $self.el.progress_container.find('.notice-wrap').remove();
1119 $self.el.progress_container.append('<div class="notice-wrap give-clearfix"><span class="spinner is-active"></span><div class="give-progress"><div></div></div></div>');
1120 $self.el.progress_main_container.removeClass('give-hidden');
1121
1122 $.ajax({
1123 type: 'POST',
1124 url: ajaxurl,
1125 data: {
1126 action: 'give_run_db_updates',
1127 run_db_update: 1
1128 },
1129 dataType: 'json',
1130 success: function (response) {
1131
1132 }
1133 });
1134
1135 window.setTimeout(Give_Updates.get_db_updates_info, 500, $self );
1136
1137 return false;
1138 });
1139 },
1140
1141 get_db_updates_info: function( $self ){
1142 $.ajax({
1143 type: 'POST',
1144 url: ajaxurl,
1145 data: {
1146 action: 'give_db_updates_info',
1147 },
1148 dataType: 'json',
1149 success: function (response) {
1150 // We need to get the actual in progress form, not all forms on the page.
1151 var notice_wrap = Give_Selector_Cache.get('.notice-wrap', $self.el.progress_container, true);
1152
1153 if (-1 !== $.inArray('success', Object.keys(response))) {
1154 if (response.success) {
1155 if ($self.el.update_progress_counter.length) {
1156 $self.el.update_progress_counter.text('100%');
1157 }
1158
1159 // Update steps info.
1160 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1161 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1162 }
1163
1164 $self.el.update_link.closest('p').remove();
1165 notice_wrap.html('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p><button type="button" class="notice-dismiss"></button></div>');
1166
1167 } else {
1168 // Update steps info.
1169 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1170 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1171 }
1172
1173 notice_wrap.html('<div class="notice notice-error"><p>' + response.data.message + '</p></div>');
1174
1175 setTimeout(function () {
1176 $self.el.update_link.removeClass('active').show();
1177 $self.el.progress_main_container.addClass('give-hidden');
1178 }, 1000);
1179 }
1180 } else {
1181 if (response && -1 !== $.inArray('percentage', Object.keys(response.data))) {
1182 if ($self.el.update_progress_counter.length) {
1183 $self.el.update_progress_counter.text(response.data.total_percentage + '%');
1184 }
1185
1186 // Update steps info.
1187 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1188 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1189 }
1190
1191 // Update progress.
1192 $('.give-progress div', '#give-db-updates').animate({
1193 width: response.data.percentage + '%',
1194 }, 50, function () {
1195 // Animation complete.
1196 });
1197
1198 window.setTimeout(Give_Updates.get_db_updates_info, 1000, $self );
1199 } else {
1200 notice_wrap.html('<div class="notice notice-error"><p>' + give_vars.updates.ajax_error + '</p></div>');
1201
1202 setTimeout(function () {
1203 $self.el.update_link.removeClass('active').show();
1204 $self.el.progress_main_container.addClass('give-hidden');
1205 }, 1000);
1206 }
1207 }
1208 }
1209 });
1210 },
1211
1212 process_step: function (step, update, $self) {
1213
1214 give_setting_edit = true;
1215
1216 $.ajax({
1217 type: 'POST',
1218 url: ajaxurl,
1219 data: {
1220 action: 'give_do_ajax_updates',
1221 step: parseInt(step),
1222 update: parseInt(update)
1223 },
1224 dataType: 'json',
1225 success: function (response) {
1226 give_setting_edit = false;
1227
1228 // We need to get the actual in progress form, not all forms on the page.
1229 var notice_wrap = Give_Selector_Cache.get('.notice-wrap', $self.el.progress_container, true);
1230
1231 if (-1 !== $.inArray('success', Object.keys(response))) {
1232 if (response.success) {
1233 // Update steps info.
1234 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1235 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1236 }
1237
1238 $self.el.update_link.closest('p').remove();
1239 notice_wrap.html('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p><button type="button" class="notice-dismiss"></button></div>');
1240
1241 } else {
1242 // Update steps info.
1243 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1244 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1245 }
1246
1247 notice_wrap.html('<div class="notice notice-error"><p>' + response.data.message + '</p></div>');
1248
1249 setTimeout(function () {
1250 $self.el.update_link.removeClass('active').show();
1251 $self.el.progress_main_container.addClass('give-hidden');
1252 }, 5000);
1253 }
1254 } else {
1255 if (response && -1 !== $.inArray('percentage', Object.keys(response.data))) {
1256 // Update progress.
1257 $('.give-progress div', '#give-db-updates').animate({
1258 width: response.data.percentage + '%',
1259 }, 50, function () {
1260 // Animation complete.
1261 });
1262
1263 // Update steps info.
1264 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1265 $self.el.heading.html('<strong>' + response.data.heading.replace('{update_count}', $self.el.heading.data('update-count')) + '</strong>');
1266 }
1267
1268 $self.process_step(parseInt(response.data.step), response.data.update, $self);
1269 } else {
1270 notice_wrap.html('<div class="notice notice-error"><p>' + give_vars.updates.ajax_error + '</p></div>');
1271
1272 setTimeout(function () {
1273 $self.el.update_link.removeClass('active').show();
1274 $self.el.progress_main_container.addClass('give-hidden');
1275 }, 5000);
1276 }
1277 }
1278
1279 }
1280 }).fail(function (response) {
1281
1282 give_setting_edit = false;
1283
1284 if (window.console && window.console.log) {
1285 console.log(response);
1286 }
1287
1288 Give_Selector_Cache.get('.notice-wrap', self.el.progress_container).append(response.responseText);
1289
1290 }).always(function () {
1291 });
1292
1293 },
1294
1295 dismiss_message: function () {
1296 $('body').on('click', '#poststuff .notice-dismiss', function () {
1297 $(this).parent().slideUp('fast');
1298 });
1299 }
1300
1301 };
1302
1303 /**
1304 * Admin Status Select Field Change
1305 *
1306 * @description: Handle status switching
1307 * @since: 1.0
1308 */
1309 var handle_status_change = function () {
1310
1311 $('select[name="give-payment-status"]').on('change', function () {
1312
1313 var status = $(this).val();
1314
1315 $('.give-donation-status').removeClass(function (index, css) {
1316 return (css.match(/\bstatus-\S+/g) || []).join(' ');
1317 }).addClass('status-' + status);
1318
1319 });
1320
1321 };
1322
1323 /**
1324 * Donor management screen JS
1325 */
1326 var GiveDonor = {
1327
1328 init: function () {
1329 this.editDonor();
1330 this.add_email();
1331 this.removeUser();
1332 this.cancelEdit();
1333 this.add_note();
1334 this.delete_checked();
1335 this.addressesAction();
1336 this.unlockDonorFields();
1337 this.bulkDeleteDonor();
1338 $( 'body' ).on( 'click', '#give-donors-filter .bulkactions input[type="submit"]', this.handleBulkActions );
1339 },
1340
1341 unlockDonorFields: function (e) {
1342 $('body').on('click', '.give-lock-block', function (e) {
1343 alert(give_vars.unlock_donor_fields);
1344 e.preventDefault();
1345 });
1346 },
1347
1348 editDonor: function () {
1349 $('body').on('click', '#edit-donor', function (e) {
1350 e.preventDefault();
1351 $('#give-donor-card-wrapper .editable').hide();
1352 $('#give-donor-card-wrapper .edit-item').fadeIn().css('display', 'block');
1353 });
1354 },
1355
1356 removeUser: function () {
1357 $('body').on('click', '#disconnect-donor', function (e) {
1358 e.preventDefault();
1359
1360 if (!confirm(give_vars.disconnect_user)) {
1361 return false;
1362 }
1363
1364 var donorID = $('input[name="customerinfo[id]"]').val();
1365
1366 var postData = {
1367 give_action: 'disconnect-userid',
1368 customer_id: donorID,
1369 _wpnonce: $('#edit-donor-info #_wpnonce').val()
1370 };
1371
1372 $.post(ajaxurl, postData, function (response) {
1373 window.location.href = response.redirect;
1374 }, 'json');
1375
1376 });
1377 },
1378
1379 cancelEdit: function () {
1380 $('body').on('click', '#give-edit-donor-cancel', function (e) {
1381 e.preventDefault();
1382 $('#give-donor-card-wrapper .edit-item').hide();
1383 $('#give-donor-card-wrapper .editable').show();
1384 $('.give_user_search_results').html('');
1385 });
1386 },
1387
1388 add_note: function () {
1389 $('body').on('click', '#add-donor-note', function (e) {
1390 e.preventDefault();
1391 var postData = {
1392 give_action: 'add-donor-note',
1393 customer_id: $('#donor-id').val(),
1394 donor_note: $('#donor-note').val(),
1395 add_donor_note_nonce: $('#add_donor_note_nonce').val()
1396 };
1397
1398 if (postData.donor_note) {
1399
1400 $.ajax({
1401 type: 'POST',
1402 data: postData,
1403 url: ajaxurl,
1404 success: function (response) {
1405 $('#give-donor-notes').prepend(response);
1406 $('.give-no-donor-notes').hide();
1407 $('#donor-note').val('');
1408 }
1409 }).fail(function (data) {
1410 if (window.console && window.console.log) {
1411 console.log(data);
1412 }
1413 });
1414
1415 } else {
1416 var border_color = $('#donor-note').css('border-color');
1417 $('#donor-note').css('border-color', 'red');
1418 setTimeout(function () {
1419 $('#donor-note').css('border-color', border_color);
1420 }, 500);
1421 }
1422 });
1423 },
1424 delete_checked: function () {
1425 $('#give-donor-delete-confirm').change(function () {
1426 var records_input = $('#give-donor-delete-records');
1427 var submit_button = $('#give-delete-donor');
1428
1429 if ($(this).prop('checked')) {
1430 records_input.attr('disabled', false);
1431 submit_button.attr('disabled', false);
1432 } else {
1433 records_input.attr('disabled', true);
1434 records_input.prop('checked', false);
1435 submit_button.attr('disabled', true);
1436 }
1437 });
1438 },
1439 add_email: function () {
1440 if (!$('#add-donor-email').length) {
1441 return;
1442 }
1443
1444 $(document.body).on('click', '#add-donor-email', function (e) {
1445 e.preventDefault();
1446 var button = $(this);
1447 var wrapper = button.parent();
1448
1449 wrapper.parent().find('.notice-wrap').remove();
1450 wrapper.find('.spinner').css('visibility', 'visible');
1451 button.attr('disabled', true);
1452
1453 var customer_id = wrapper.find('input[name="donor-id"]').val();
1454 var email = wrapper.find('input[name="additional-email"]').val();
1455 var primary = wrapper.find('input[name="make-additional-primary"]').is(':checked');
1456 var nonce = wrapper.find('input[name="add_email_nonce"]').val();
1457
1458 var postData = {
1459 give_action: 'add_donor_email',
1460 customer_id: customer_id,
1461 email: email,
1462 primary: primary,
1463 _wpnonce: nonce
1464 };
1465
1466 $.post(ajaxurl, postData, function (response) {
1467
1468 if (true === response.success) {
1469 window.location.href = response.redirect;
1470 } else {
1471 button.attr('disabled', false);
1472 wrapper.after('<div class="notice-wrap"><div class="notice notice-error inline"><p>' + response.message + '</p></div></div>');
1473 wrapper.find('.spinner').css('visibility', 'hidden');
1474 }
1475
1476 }, 'json');
1477
1478 });
1479 },
1480
1481 addressesAction: function () {
1482 var $obj = this,
1483 $addressWrapper = $('#donor-address-wrapper'),
1484 $allAddress = $('.all-address', $addressWrapper),
1485 $noAddressMessageWrapper = $('.give-no-address-message', $addressWrapper),
1486 $allAddressParent = $($allAddress).parent(),
1487 $addressForm = $('.address-form', $addressWrapper),
1488 $addressFormCancelBtn = $('.js-cancel', $addressForm),
1489 $addressFormCountryField = $('select[name="country"]', $addressForm),
1490 $addNewAddressBtn = $('.add-new-address', $addressWrapper),
1491 donorID = parseInt($('input[name="donor-id"]').val());
1492
1493 $addressFormCountryField.on('change', function () {
1494 $(this).trigger('chosen:updated');
1495 });
1496
1497 // Edit current address button event.
1498 $allAddress.on('click', '.js-edit', function (e) {
1499 var $parent = $(this).closest('.address');
1500
1501 e.preventDefault();
1502
1503 // Remove notice.
1504 $('.notice', $allAddressParent).remove();
1505
1506 $obj.__set_address_form_val($parent);
1507 $obj.__set_address_form_action('update', $parent.data('address-id'));
1508
1509 $addNewAddressBtn.hide();
1510 $allAddress.addClass('give-hidden');
1511 $addressForm.removeClass('add-new-address-form-hidden');
1512 $addressForm.data('process', 'update');
1513 });
1514
1515 // Remove address button event.
1516 $allAddress.on('click', '.js-remove', function (e) {
1517 e.preventDefault();
1518
1519 var $parent = $(this).closest('.address');
1520
1521 // Remove notice.
1522 $('.notice', $allAddressParent).remove();
1523
1524 $addressForm.data('changed', true);
1525 $obj.__set_address_form_val($parent);
1526 $obj.__set_address_form_action('remove', $parent.data('address-id'));
1527
1528 $addressForm.trigger('submit');
1529 });
1530
1531 // Add new address button event.
1532 $addNewAddressBtn.on('click', function (e) {
1533 e.preventDefault();
1534
1535 // Remove notice.
1536 $('.notice', $allAddressParent).remove();
1537
1538 $(this).hide();
1539 $allAddress.addClass('give-hidden');
1540 $addressForm.removeClass('add-new-address-form-hidden');
1541 $obj.__set_address_form_action('add');
1542
1543
1544 $obj.__set_address_form_action();
1545 });
1546
1547 // Cancel add new address form button event.
1548 $addressFormCancelBtn.on('click', function (e) {
1549 e.preventDefault();
1550
1551 // Reset form.
1552 $addressForm.find('input[type="text"]').val('');
1553
1554 $addNewAddressBtn.show();
1555 $allAddress.removeClass('give-hidden');
1556 $addressForm.addClass('add-new-address-form-hidden');
1557 });
1558
1559 // Save address.
1560 $addressForm
1561 .on('change', function () {
1562 $(this).data('changed', true);
1563 })
1564 .on('submit', function (e) {
1565 e.preventDefault();
1566
1567 var $this = $(this);
1568
1569 // Remove notice.
1570 $('.notice', $allAddressParent).remove();
1571
1572 // Do not send ajax if form does not change.
1573 if (!$(this).data('changed')) {
1574 $addNewAddressBtn.show();
1575 $allAddress.removeClass('give-hidden');
1576 $addressForm.addClass('add-new-address-form-hidden');
1577
1578 return false;
1579 }
1580
1581 $.ajax({
1582 type: 'POST',
1583 url: ajaxurl,
1584 data: {
1585 action: 'donor_manage_addresses',
1586 donorID: donorID,
1587 form: $('form', $addressForm).serialize()
1588 },
1589 beforeSend: function () {
1590 giveAjaxLoader($addressWrapper, {show: true});
1591 },
1592 success: function (response) {
1593 giveAjaxLoader($addressWrapper);
1594
1595 if (response.success) {
1596 var parent;
1597
1598 switch (response.data.action) {
1599 case 'add':
1600 $('.give-grid-row', $allAddress).append(response.data.address_html);
1601
1602 if (!$noAddressMessageWrapper.hasClass('give-hidden') && $('div.give-grid-col-4', $allAddress).length) {
1603 $noAddressMessageWrapper.addClass('give-hidden');
1604 }
1605 break;
1606
1607 case 'remove':
1608 parent = $allAddress
1609 .find('div[data-address-id*="' + response.data.id + '"]').parent();
1610
1611 if (parent.length) {
1612 parent.animate(
1613 {'margin-left': '-999'},
1614 1000,
1615 function () {
1616 parent.remove();
1617
1618 if (
1619 $noAddressMessageWrapper.hasClass('give-hidden') &&
1620 !$('div.give-grid-col-4', $allAddress).length
1621 ) {
1622 $noAddressMessageWrapper.removeClass('give-hidden');
1623 }
1624 }
1625 );
1626 }
1627
1628 break;
1629
1630 case 'update':
1631 parent = $allAddress
1632 .find('div[data-address-id*="' + response.data.id + '"]').parent();
1633 var $prevParent = parent.prev(),
1634 $nextParent = {},
1635 is_address_added = false;
1636
1637 if (parseInt($('.give-grid-row>div', $allAddress).length) < 2) {
1638 $('.give-grid-row', $allAddress).append(response.data.address_html);
1639 } else {
1640 if ($prevParent.length) {
1641 $prevParent.after(response.data.address_html);
1642 is_address_added = true;
1643 }
1644
1645 if (!is_address_added) {
1646 $nextParent = parent.next();
1647
1648 if ($nextParent.length) {
1649 $nextParent.before(response.data.address_html);
1650 }
1651 }
1652 }
1653
1654 parent.remove();
1655
1656 break;
1657 }
1658
1659 $allAddressParent.prepend(response.data.success_msg);
1660
1661 } else {
1662 $allAddressParent.prepend(response.data.error_msg);
1663 }
1664 },
1665 dataType: 'json'
1666 }).always(function () {
1667 $this.data('changed', false);
1668
1669 // Reset form.
1670 $addressForm.find('input[type="text"]').val('');
1671
1672 $addNewAddressBtn.show();
1673 $allAddress.removeClass('give-hidden');
1674 $addressForm.addClass('add-new-address-form-hidden');
1675 });
1676
1677 return false;
1678 });
1679 },
1680
1681 __set_address_form_action: function (addressAction, addressID) {
1682 var $addressWrapper = $('#donor-address-wrapper'),
1683 $addressForm = $('.address-form', $addressWrapper),
1684 $addressActionField = $('input[name="address-action"]', $addressForm),
1685 $addressIDField = $('input[name="address-id"]', $addressForm);
1686
1687 addressAction = addressAction || 'add';
1688 addressID = addressID || 'billing';
1689
1690 $addressActionField.val(addressAction);
1691 $addressIDField.val(addressID);
1692 },
1693
1694 __set_address_form_val: function ($form) {
1695 var $addressWrapper = $('#donor-address-wrapper'),
1696 $addressForm = $('.address-form', $addressWrapper),
1697 state = $('[data-address-type="state"]', $form).text().substr(2).trim(); // State will be like ", HR".
1698
1699 if ($('select[name="country"]', $addressForm).val().trim() !== $('[data-address-type="country"]', $form).text().trim()) {
1700 $('select[name="country"]', $addressForm).val($('[data-address-type="country"]', $form).text().trim()).trigger('chosen:updated').change();
1701
1702 // Update state after some time because state load by ajax for each country.
1703 window.setTimeout(function () {
1704 $('[name="state"]', $addressForm).val(state).trigger('chosen:updated');
1705 }, 500);
1706 } else {
1707 $('[name="state"]', $addressForm).val(state).trigger('chosen:updated');
1708 }
1709
1710 $('input[name="line1"]', $addressForm).val($('[data-address-type="line1"]', $form).text().trim());
1711 $('input[name="line2"]', $addressForm).val($('[data-address-type="line2"]', $form).text().trim());
1712 $('input[name="city"]', $addressForm).val($('[data-address-type="city"]', $form).text().trim());
1713 $('input[name="zip"]', $addressForm).val($('[data-address-type="zip"]', $form).text().trim());
1714 },
1715
1716 bulkDeleteDonor: function() {
1717 var $body = $('body');
1718
1719 // Cancel button click event for donor.
1720 $body.on('click', '#give-bulk-delete-cancel', function (e) {
1721 $(this).closest('tr').hide();
1722 $('.give-skip-donor').trigger('click');
1723 e.preventDefault();
1724 });
1725
1726 // Select All checkbox.
1727 $body.on('click', '#cb-select-all-1, #cb-select-all-2', function () {
1728
1729 var selectAll = $(this);
1730
1731 // Loop through donor selector checkbox.
1732 $.each($('.donor-selector'), function () {
1733
1734 var donorId = $(this).val(),
1735 donorName = $(this).data('name'),
1736 donorHtml = '<div id="give-donor-' + donorId + '" data-id="' + donorId + '">' +
1737 '<a class="give-skip-donor" title="' + give_vars.remove_from_bulk_delete + '">X</a>' +
1738 donorName + '</div>';
1739
1740 if( selectAll.is( ':checked' ) && ! $( this ).is( ':checked' ) ) {
1741 $( '#give-bulk-donors' ).append( donorHtml );
1742 } else if ( ! selectAll.is( ':checked' ) ) {
1743 $( '#give-bulk-donors' ).find( '#give-donor-' + donorId ).remove();
1744 }
1745 });
1746 });
1747
1748 // On checking checkbox, add to bulk delete donor.
1749 $body.on('click', '.donor-selector', function () {
1750 var donorId = $(this).val(),
1751 donorName = $(this).data('name'),
1752 donorHtml = '<div id="give-donor-' + donorId + '" data-id="' + donorId + '">' +
1753 '<a class="give-skip-donor" title="' + give_vars.remove_from_bulk_delete + '">X</a>' +
1754 donorName + '</div>';
1755
1756 if ($(this).is(':checked')) {
1757 $('#give-bulk-donors').prepend(donorHtml);
1758 } else {
1759 $('#give-bulk-donors').find('#give-donor-' + donorId).remove();
1760 }
1761 });
1762
1763 // CheckBox click event to confirm deletion of donor.
1764 $body.on('click', '#give-delete-donor-confirm', function () {
1765 if ($(this).is(':checked')) {
1766 $('#give-bulk-delete-button').removeAttr('disabled');
1767 } else {
1768 $('#give-bulk-delete-button').attr('disabled', true);
1769 $('#give-delete-donor-records').removeAttr('checked');
1770 }
1771 });
1772
1773 // CheckBox click event to delete records with donor.
1774 $body.on('click', '#give-delete-donor-records', function () {
1775 if ($(this).is(':checked')) {
1776 $('#give-delete-donor-confirm').attr('checked', 'checked');
1777 $('#give-bulk-delete-button').removeAttr('disabled');
1778 }
1779 });
1780
1781 // Skip Donor from Bulk Delete List.
1782 $body.on('click', '.give-skip-donor', function () {
1783 var donorId = $(this).closest('div').data('id');
1784 $('#give-donor-' + donorId).remove();
1785 $('#donor-' + donorId).find('input[type="checkbox"]').removeAttr('checked');
1786 });
1787
1788 // Clicking Event to Delete Single Donor.
1789 $body.on( 'click', '.give-single-donor-delete', function( e ) {
1790 var donorId = $( this ).data( 'id' ),
1791 donorSelector = $( 'tr#donor-' + donorId ).find( '.donor-selector' ),
1792 selectAll = $( '[id^="cb-select-all-"]' ),
1793 bulkDeleteList = $('#give-bulk-donors'),
1794 donorName = donorSelector.data( 'name' ),
1795 donorHtml = '<div id="give-donor-' + donorId + '" data-id="' + donorId + '">' +
1796 '<a class="give-skip-donor" title="' + give_vars.remove_from_bulk_delete + '">X</a>' +
1797 donorName + '</div>';
1798
1799 // Reset Donors List.
1800 bulkDeleteList.html('');
1801
1802 // Check whether the select all donor checkbox is already set, then unset it.
1803 if ( selectAll.is( ':checked' ) ) {
1804 selectAll.removeAttr( 'checked' );
1805 }
1806
1807 // Select the donor checkbox for which delete is clicked and others should be de-selected.
1808 $( '.donor-selector' ).removeAttr( 'checked' );
1809 donorSelector.attr( 'checked', 'checked' );
1810
1811 // Add Donor to the Bulk Delete List, if donor doesn't exists in the list.
1812 if ( $( '#give-donor-' + donorId ).length === 0 ) {
1813 bulkDeleteList.prepend(donorHtml);
1814 $('#give-bulk-delete').slideDown();
1815 }
1816
1817 e.preventDefault();
1818 });
1819 },
1820
1821 handleBulkActions: function( e ) {
1822
1823 var currentAction = $( this ).closest( '.tablenav' ).find( 'select' ).val(),
1824 donors = [],
1825 selectBulkActionNotice = give_vars.donors_bulk_action.no_action_selected,
1826 confirmActionNotice = give_vars.donors_bulk_action.no_donor_selected;
1827
1828 $.each( $( ".donor-selector:checked" ), function() {
1829 donors.push( $( this ).val() );
1830 });
1831
1832 // If there is no bulk action selected then show an alert message.
1833 if ( '-1' === currentAction ) {
1834 alert( selectBulkActionNotice );
1835 return false;
1836 }
1837
1838 // If there is no donor selected then show an alert.
1839 if ( ! parseInt( donors ) ) {
1840 alert( confirmActionNotice );
1841 return false;
1842 }
1843
1844 if( 'delete' === currentAction ) {
1845 $( '#give-bulk-delete' ).slideDown();
1846 }
1847
1848 e.preventDefault();
1849 }
1850 };
1851
1852 /**
1853 * API screen JS
1854 */
1855 var API_Screen = {
1856
1857 init: function () {
1858 this.revoke_api_key();
1859 this.regenerate_api_key();
1860 },
1861
1862 revoke_api_key: function () {
1863 $('body').on('click', '.give-revoke-api-key', function (e) {
1864 return confirm(give_vars.revoke_api_key);
1865 });
1866 },
1867 regenerate_api_key: function () {
1868 $('body').on('click', '.give-regenerate-api-key', function (e) {
1869 return confirm(give_vars.regenerate_api_key);
1870 });
1871 }
1872 };
1873
1874 /**
1875 * Edit Donation form screen Js
1876 */
1877 var Edit_Form_Screen = {
1878 init: function () {
1879 var default_tab_id = $.query.get('give_tab').length ? $.query.get('give_tab') : 'form_field_options';
1880
1881 this.handle_metabox_tab_click();
1882 this.setup_colorpicker_fields();
1883 this.setup_media_fields();
1884 this.setup_repeatable_fields();
1885 this.handle_repeater_group_events();
1886
1887 // Multi level repeater field js.
1888 this.handle_multi_levels_repeater_group_events();
1889
1890 // Set active tab on page load.
1891 this.activate_tab($('a[href="#' + default_tab_id + '"]'));
1892 },
1893
1894 /**
1895 * Attach click event handler to tabs.
1896 */
1897 handle_metabox_tab_click: function () {
1898 var self = this;
1899 var $tab_links = $('.give-metabox-tabs a');
1900
1901 $tab_links.on('click', function (e) {
1902 e.preventDefault();
1903 $this = $(this);
1904 self.activate_tab($this);
1905 self.update_query($this);
1906 });
1907 },
1908
1909 /**
1910 * Set the active tab.
1911 */
1912 activate_tab: function ($tab_link) {
1913 var tab_id = $tab_link.data('tab-id'),
1914 $li_parent = $tab_link.parent(),
1915 $sub_field = $('ul.give-metabox-sub-tabs', $li_parent),
1916 has_sub_field = $sub_field.length,
1917 $tab_links = $('.give-metabox-tabs a'),
1918 $all_tab_links_li = $tab_links.parents('li'),
1919 $all_sub_fields = $('ul.give-metabox-sub-tabs'),
1920 in_sub_fields = $tab_link.parents('ul.give-metabox-sub-tabs').length;
1921
1922 // Update active tab hidden field to maintain tab after save.
1923 $('#give_form_active_tab').val(tab_id);
1924
1925 if (has_sub_field) {
1926 $li_parent.toggleClass('active');
1927 $sub_field.removeClass('give-hidden');
1928
1929 var $active_subtab_li = $('li.active', 'ul.give-metabox-sub-tabs');
1930
1931 // Show hide sub fields if any and exit.
1932 $all_sub_fields.not($sub_field).addClass('give-hidden');
1933 $all_tab_links_li.not($li_parent).removeClass('active');
1934
1935 $active_subtab_li.addClass('active');
1936 } else if (!in_sub_fields) {
1937 // Hide all tab and sub tabs.
1938 $all_tab_links_li.each(function (index, item) {
1939 item = $(item);
1940 item.removeClass('active');
1941
1942 if (item.hasClass('has-sub-fields')) {
1943 $('ul.give-metabox-sub-tabs', item).addClass('give-hidden');
1944 }
1945 });
1946 } else if (in_sub_fields) {
1947 // Hide all sub tabs.
1948 $('ul.give-metabox-sub-tabs').addClass('give-hidden');
1949 $all_tab_links_li.removeClass('active');
1950
1951 // Hide all tab inside sub tabs.
1952 $tab_link.parents('ul.give-metabox-sub-tabs')
1953 .removeClass('give-hidden')
1954 .children('li')
1955 .removeClass('active');
1956
1957 // Add active class to parent li.
1958 $tab_link.parents('li.has-sub-fields').addClass('active');
1959 }
1960
1961 // Add active class to current tab link.
1962 $tab_link.parent().addClass('active');
1963
1964 // Hide all tab contents.
1965 $('.give_options_panel').removeClass('active');
1966
1967 // Show tab content.
1968 $($tab_link.attr('href')).addClass('active');
1969 },
1970
1971 /**
1972 * Update query string with active tab ID.
1973 */
1974 update_query: function ($tab_link) {
1975 var tab_id = $tab_link.data('tab-id');
1976 var new_query = $.query.set('give_tab', tab_id).remove('message').toString();
1977
1978 if (history.replaceState) {
1979 history.replaceState(null, null, new_query);
1980 }
1981 },
1982
1983 /**
1984 * Initialize colorpicker.
1985 */
1986 setup_colorpicker_fields: function () {
1987 $(document).ready(function () {
1988 var $colorpicker_fields = $('.give-colorpicker');
1989
1990 if ($colorpicker_fields.length) {
1991 $colorpicker_fields.each(function (index, item) {
1992 var $item = $(item);
1993
1994 // Bailout: do not automatically initialize color picker for repeater field group template.
1995 if ($item.parents('.give-template').length) {
1996 return;
1997 }
1998
1999 $item.wpColorPicker();
2000 });
2001 }
2002 });
2003 },
2004
2005 setup_media_fields: function () {
2006 var give_media_uploader,
2007 $give_upload_button,
2008 $body = $('body');
2009
2010 /**
2011 * Set media modal.
2012 */
2013 $body.on('click', '.give-upload-button', function (e) {
2014 e.preventDefault();
2015 var $media_modal_config = {};
2016
2017 // Cache input field.
2018 $give_upload_button = $(this);
2019
2020 // Set modal config.
2021 switch ($(this).data('field-type')) {
2022 case 'media':
2023 $media_modal_config = {
2024 title: give_vars.metabox_fields.media.button_title,
2025 button: {text: give_vars.metabox_fields.media.button_title},
2026 multiple: false, // Set to true to allow multiple files to be selected.
2027 library: {type: 'image'}
2028 };
2029 break;
2030
2031 default:
2032 $media_modal_config = {
2033 title: give_vars.metabox_fields.file.button_title,
2034 button: {text: give_vars.metabox_fields.file.button_title},
2035 multiple: false
2036 };
2037 }
2038
2039 var editing = jQuery(this).closest('.give-field-wrap').find('.give-input-field').attr('editing');
2040 if ('undefined' !== typeof( editing )) {
2041 wp.media.controller.Library.prototype.defaults.contentUserSetting = false;
2042 }
2043
2044 var $library = jQuery(this).closest('.give-field-wrap').find('.give-input-field').attr('library');
2045 if ('undefined' !== typeof( $library ) && '' !== $library) {
2046 $media_modal_config.library = {type: $library};
2047 }
2048
2049 // Extend the wp.media object.
2050 give_media_uploader = wp.media($media_modal_config);
2051
2052 // When a file is selected, grab the URL and set it as the text field's value.
2053 give_media_uploader.on('select', function () {
2054 var attachment = give_media_uploader.state().get('selection').first().toJSON(),
2055 $input_field = $give_upload_button.prev(),
2056 fvalue = ( 'id' === $give_upload_button.data('fvalue') ? attachment.id : attachment.url );
2057
2058 $body.trigger('give_media_inserted', [attachment, $input_field]);
2059
2060 // Set input field value.
2061 $input_field.val(fvalue);
2062
2063 // Update attachment id field value if fvalue is not set to id.
2064 if ('id' !== $give_upload_button.data('fvalue')) {
2065 var attachment_id_field_name = 'input[name="' + $input_field.attr('name') + '_id"]',
2066 id_field = $input_field.closest('tr').next('tr').find(attachment_id_field_name);
2067
2068 if (id_field.length) {
2069 $input_field.closest('tr').next('tr').find(attachment_id_field_name).val(attachment.id);
2070 }
2071 }
2072 });
2073
2074 // Open the uploader dialog.
2075 give_media_uploader.open();
2076 });
2077
2078 /**
2079 * Show image preview.
2080 */
2081 $body.on('give_media_inserted', function (e, attachment) {
2082 var $parent = $give_upload_button.parents('.give-field-wrap'),
2083 $image_container = $('.give-image-thumb', $parent);
2084
2085 // Bailout.
2086 if (!$image_container.length) {
2087 return false;
2088 }
2089
2090 // Bailout and hide preview.
2091 if ('image' !== attachment.type) {
2092 $image_container.addClass('give-hidden');
2093 $('img', $image_container).attr('src', '');
2094 return false;
2095 }
2096
2097 // Set the attachment URL to our custom image input field.
2098 $image_container.find('img').attr('src', attachment.url);
2099
2100 // Hide the add image link.
2101 $image_container.removeClass('give-hidden');
2102 });
2103
2104 /**
2105 * Delete Image Link.
2106 */
2107 $('span.give-delete-image-thumb', '.give-image-thumb').on('click', function (event) {
2108
2109 event.preventDefault();
2110
2111 var $parent = $(this).parents('.give-field-wrap'),
2112 $image_container = $(this).parent(),
2113 $image_input_field = $('input[type="text"]', $parent);
2114
2115 // Clear out the preview image.
2116 $image_container.addClass('give-hidden');
2117
2118 // Remove image link from input field.
2119 $image_input_field.val('');
2120
2121 // Hide the add image link.
2122 $('img', $image_container).attr('src', '');
2123 });
2124 },
2125
2126 /**
2127 * Setup repeater field.
2128 */
2129 setup_repeatable_fields: function () {
2130 jQuery(function () {
2131 jQuery('.give-repeatable-field-section').each(function () {
2132 var $this = $(this);
2133
2134 // Note: Do not change option params, it can break repeatable fields functionality.
2135 var options = {
2136 wrapper: '.give-repeatable-fields-section-wrapper',
2137 container: '.container',
2138 row: '.give-row',
2139 add: '.give-add-repeater-field-section-row',
2140 remove: '.give-remove',
2141 move: '.give-move',
2142 template: '.give-template',
2143 confirm_before_remove_row: true,
2144 confirm_before_remove_row_text: give_vars.confirm_before_remove_row_text,
2145 is_sortable: true,
2146 before_add: null,
2147 after_add: handle_metabox_repeater_field_row_count,
2148 //after_add: after_add, Note: after_add is internal function in repeatable-fields.js. Uncomment this can cause of js error.
2149 before_remove: null,
2150 after_remove: handle_metabox_repeater_field_row_remove,
2151 sortable_options: {
2152 placeholder: 'give-ui-placeholder-state-highlight',
2153 start: function (event, ui) {
2154 $('body').trigger('repeater_field_sorting_start', [ui.item]);
2155 },
2156 stop: function (event, ui) {
2157 $('body').trigger('repeater_field_sorting_stop', [ui.item]);
2158 },
2159 update: function (event, ui) {
2160 // Do not allow any row at position 0.
2161 if (ui.item.next().hasClass('give-template')) {
2162 ui.item.next().after(ui.item);
2163 }
2164
2165 var $rows = $('.give-row', $this).not('.give-template');
2166
2167 if ($rows.length) {
2168 var row_count = 1;
2169 $rows.each(function (index, item) {
2170 // Set name for fields.
2171 var $fields = $('.give-field, label', $(item));
2172
2173 if ($fields.length) {
2174 $fields.each(function () {
2175 var $parent = $(this).parents('.give-field-wrap'),
2176 $currentElement = $(this);
2177
2178 $.each(this.attributes, function (index, element) {
2179 var old_class_name_prefix = this.value.replace(/\[/g, '_').replace(/]/g, ''),
2180 old_class_name = old_class_name_prefix + '_field',
2181 new_class_name = '',
2182 new_class_name_prefix = '';
2183
2184 // Bailout.
2185 if (!this.value) {
2186 return;
2187 }
2188
2189 // Reorder index.
2190 this.value = this.value.replace(/\[\d+\]/g, '[' + (row_count - 1) + ']');
2191 new_class_name_prefix = this.value.replace(/\[/g, '_').replace(/]/g, '');
2192
2193 // Update class name.
2194 if ($parent.hasClass(old_class_name)) {
2195 new_class_name = new_class_name_prefix + '_field';
2196 $parent.removeClass(old_class_name).addClass(new_class_name);
2197 }
2198
2199 // Update field id.
2200 if (old_class_name_prefix == $currentElement.attr('id')) {
2201 $currentElement.attr('id', new_class_name_prefix);
2202 }
2203 });
2204 });
2205 }
2206
2207 row_count++;
2208 });
2209
2210 // Fire event.
2211 $this.trigger('repeater_field_row_reordered', [ui.item]);
2212 }
2213 }
2214 }
2215 //row_count_placeholder: '{{row-count-placeholder}}' Note: do not modify this param otherwise it will break repeatable field functionality.
2216 };
2217
2218 jQuery(this).repeatable_fields(options);
2219 });
2220 });
2221 },
2222
2223 /**
2224 * Handle repeater field events.
2225 */
2226 handle_repeater_group_events: function () {
2227 var $repeater_fields = $('.give-repeatable-field-section'),
2228 $body = $('body');
2229
2230 // Auto toggle repeater group
2231 $body.on('click', '.give-row-head button', function () {
2232 var $parent = $(this).closest('tr');
2233 $parent.toggleClass('closed');
2234 $('.give-row-body', $parent).toggle();
2235 });
2236
2237 // Reset header title when new row added.
2238 $repeater_fields.on('repeater_field_new_row_added repeater_field_row_deleted repeater_field_row_reordered', function () {
2239 handle_repeater_group_add_number_suffix($(this));
2240 });
2241
2242 // Disable editor when sorting start.
2243 $body.on('repeater_field_sorting_start', function (e, row) {
2244 var $textarea = $('.wp-editor-area', row);
2245
2246 if ($textarea.length) {
2247 $textarea.each(function (index, item) {
2248 window.setTimeout(
2249 function () {
2250 tinyMCE.execCommand('mceRemoveEditor', true, $(item).attr('id'));
2251 },
2252 300
2253 );
2254 });
2255 }
2256 });
2257
2258 // Enable editor when sorting stop.
2259 $body.on('repeater_field_sorting_stop', function (e, row) {
2260 var $textarea = $('.wp-editor-area', row);
2261
2262 if ($textarea.length) {
2263 $textarea.each(function (index, item) {
2264 window.setTimeout(
2265 function () {
2266 var textarea_id = $(item).attr('id');
2267 tinyMCE.execCommand('mceAddEditor', true, textarea_id);
2268
2269 // Switch editor to tmce mode to fix some glitch which appear when you reorder rows.
2270 window.setTimeout(function () {
2271 // Hack to show tmce mode.
2272 switchEditors.go(textarea_id, 'html');
2273 $('#' + textarea_id + '-tmce').trigger('click');
2274 }, 100);
2275 },
2276 300
2277 );
2278 });
2279 }
2280 });
2281
2282 // Process jobs on document load for repeater fields.
2283 $repeater_fields.each(function (index, item) {
2284 // Reset title on document load for already exist groups.
2285 var $item = $(item);
2286 handle_repeater_group_add_number_suffix($item);
2287
2288 // Close all tabs when page load.
2289 if (parseInt($item.data('close-tabs'))) {
2290 $('.give-row-head button', $item).trigger('click');
2291 $('.give-template', $item).removeClass('closed');
2292 $('.give-template .give-row-body', $item).show();
2293 }
2294 });
2295
2296 // Setup colorpicker field when row added.
2297 $repeater_fields.on('repeater_field_new_row_added', function (e, container, new_row) {
2298 $('.give-colorpicker', $(this)).each(function (index, item) {
2299 var $item = $(item);
2300
2301 // Bailout: skip already init colorpocker fields.
2302 if ($item.parents('.wp-picker-container').length || $item.parents('.give-template').length) {
2303 return;
2304 }
2305
2306 $item.wpColorPicker();
2307 });
2308
2309 // Load WordPress editor by ajax.
2310 var wysiwyg_editor_container = $('div[data-wp-editor]', new_row);
2311
2312 if (wysiwyg_editor_container.length) {
2313 wysiwyg_editor_container.each(function (index, item) {
2314 var $item = $(item),
2315 wysiwyg_editor = $('.wp-editor-wrap', $item),
2316 textarea = $('textarea', $item),
2317 textarea_id = 'give_wysiwyg_unique_' + Math.random().toString().replace('.', '_'),
2318 wysiwyg_editor_label = wysiwyg_editor.prev();
2319
2320 textarea.attr('id', textarea_id);
2321
2322 $.post(
2323 ajaxurl,
2324 {
2325 action: 'give_load_wp_editor',
2326 wp_editor: $item.data('wp-editor'),
2327 wp_editor_id: textarea_id,
2328 textarea_name: $('textarea', $item).attr('name')
2329 },
2330 function (res) {
2331 wysiwyg_editor.remove();
2332 wysiwyg_editor_label.after(res);
2333
2334 // Setup qt data for editor.
2335 tinyMCEPreInit.qtInit[textarea.attr('id')] = $.extend(
2336 true,
2337 tinyMCEPreInit.qtInit['_give_agree_text'],
2338 {id: textarea_id}
2339 );
2340
2341 // Setup mce data for editor.
2342 tinyMCEPreInit.mceInit[textarea_id] = $.extend(
2343 true,
2344 tinyMCEPreInit.mceInit['_give_agree_text'],
2345 {
2346 body_class: textarea_id + ' post-type-give_forms post-status-publish locale-' + tinyMCEPreInit.mceInit['_give_agree_text']['wp_lang_attr'].toLowerCase(),
2347 selector: '#' + textarea_id
2348 }
2349 );
2350
2351 // Setup editor.
2352 tinymce.init(tinyMCEPreInit.mceInit[textarea_id]);
2353 quicktags(tinyMCEPreInit.qtInit[textarea_id]);
2354 QTags._buttonsInit();
2355
2356 window.setTimeout(function () {
2357 // Hack to show tmce mode.
2358 switchEditors.go(textarea_id, 'html');
2359 $('#' + textarea_id + '-tmce').trigger('click');
2360 }, 100);
2361
2362 if (!window.wpActiveEditor) {
2363 window.wpActiveEditor = textarea_id;
2364 }
2365 }
2366 );
2367 });
2368 }
2369
2370 });
2371
2372 },
2373
2374 /**
2375 * Handle events for multi level repeater group.
2376 */
2377 handle_multi_levels_repeater_group_events: function () {
2378 var $repeater_fields = $('#_give_donation_levels_field');
2379
2380 // Add level title as suffix to header title when admin add level title.
2381 $('body').on('keyup', '.give-multilevel-text-field', function () {
2382 var $parent = $(this).closest('tr'),
2383 $header_title_container = $('.give-row-head h2 span', $parent),
2384 donation_level_header_text_prefix = $header_title_container.data('header-title');
2385
2386 // Donation level header already set.
2387 if ($(this).val() && ( $(this).val() === $header_title_container.html() )) {
2388 return false;
2389 }
2390
2391 if ($(this).val()) {
2392 // Change donaiton level header text.
2393 $header_title_container.html(donation_level_header_text_prefix + ': ' + $(this).val());
2394 } else {
2395 // Reset donation level header heading text.
2396 $header_title_container.html(donation_level_header_text_prefix);
2397 }
2398 });
2399
2400 // Add level title as suffix to header title on document load.
2401 $('.give-multilevel-text-field').each(function (index, item) {
2402
2403 // Skip first element.
2404 if (!index) {
2405 return;
2406 }
2407
2408 // Check if item is jquery object or not.
2409 var $item = $(item);
2410
2411 var $parent = $item.closest('tr'),
2412 $header_title_container = $('.give-row-head h2 span', $parent),
2413 donation_level_header_text_prefix = $header_title_container.data('header-title');
2414
2415 // Donation level header already set.
2416 if ($item.val() && ( $item.val() === $header_title_container.html() )) {
2417 return false;
2418 }
2419
2420 if ($item.val()) {
2421 // Change donaiton level header text.
2422 $header_title_container.html(donation_level_header_text_prefix + ': ' + $item.val());
2423 } else {
2424 // Reset donation level header heading text.
2425 $header_title_container.html(donation_level_header_text_prefix);
2426 }
2427 });
2428
2429 // Handle row deleted event for levels repeater field.
2430 $repeater_fields.on('repeater_field_row_deleted', function () {
2431 var $this = $(this);
2432
2433 window.setTimeout(
2434 function () {
2435 var $parent = $this,
2436 $repeatable_rows = $('.give-row', $parent).not('.give-template'),
2437 $default_radio = $('.give-give_default_radio_inline', $repeatable_rows),
2438 number_of_level = $repeatable_rows.length;
2439
2440 if (number_of_level === 1) {
2441 $default_radio.prop('checked', true);
2442 }
2443 },
2444 200
2445 );
2446 });
2447
2448 // Handle row added event for levels repeater field.
2449 $repeater_fields.on('repeater_field_new_row_added', function (e, container, new_row) {
2450 var $this = $(this),
2451 max_level_id = 0;
2452
2453 // Auto set default level if no level set as default.
2454 window.setTimeout(
2455 function () {
2456 // Set first row as default if selected default row deleted.
2457 // When a row is removed containing the default selection then revert default to first repeatable row.
2458 if ($('.give-give_default_radio_inline', $this).is(':checked') === false) {
2459 $('.give-row', $this)
2460 .not('.give-template')
2461 .first()
2462 .find('.give-give_default_radio_inline')
2463 .prop('checked', true);
2464 }
2465 },
2466 200
2467 );
2468
2469 // Get max level id.
2470 $('input[type="hidden"].give-levels_id', $this).each(function (index, item) {
2471 var $item = $(item),
2472 current_level = parseInt($item.val());
2473 if (max_level_id < current_level) {
2474 max_level_id = current_level;
2475 }
2476 });
2477
2478 // Auto set level id for new setting level setting group.
2479 $('input[type="hidden"].give-levels_id', new_row).val(++max_level_id);
2480 });
2481 }
2482 };
2483
2484 /**
2485 * Handle row count and field count for repeatable field.
2486 */
2487 var handle_metabox_repeater_field_row_count = function (container, new_row) {
2488 var row_count = $(container).attr('data-rf-row-count'),
2489 $container = $(container),
2490 $parent = $container.parents('.give-repeatable-field-section');
2491
2492 row_count++;
2493
2494 // Set name for fields.
2495 $('*', new_row).each(function () {
2496 $.each(this.attributes, function (index, element) {
2497 this.value = this.value.replace('{{row-count-placeholder}}', row_count - 1);
2498 });
2499 });
2500
2501 // Set row counter.
2502 $(container).attr('data-rf-row-count', row_count);
2503
2504 // Fire event: Row added.
2505 $parent.trigger('repeater_field_new_row_added', [container, new_row]);
2506 };
2507
2508 /**
2509 * Handle row remove for repeatable field.
2510 */
2511 var handle_metabox_repeater_field_row_remove = function (container) {
2512 var $container = $(container),
2513 $parent = $container.parents('.give-repeatable-field-section'),
2514 row_count = $(container).attr('data-rf-row-count');
2515
2516 // Reduce row count.
2517 $container.attr('data-rf-row-count', --row_count);
2518
2519 // Fire event: Row deleted.
2520 $parent.trigger('repeater_field_row_deleted');
2521 };
2522
2523 /**
2524 * Add number suffix to repeater group.
2525 */
2526 var handle_repeater_group_add_number_suffix = function ($parent) {
2527
2528 // Bailout: check if auto group numbering is on or not.
2529 if (!parseInt($parent.data('group-numbering'))) {
2530 return;
2531 }
2532
2533 var $header_title_container = $('.give-row-head h2 span', $parent),
2534 header_text_prefix = $header_title_container.data('header-title');
2535
2536 $header_title_container.each(function (index, item) {
2537 var $item = $(item);
2538
2539 // Bailout: do not rename header title in fields template.
2540 if ($item.parents('.give-template').length) {
2541 return;
2542 }
2543
2544 $item.html(header_text_prefix + ': ' + index);
2545 });
2546 };
2547
2548 /**
2549 * Payment history listing page js
2550 */
2551 var GivePaymentHistory = {
2552 init: function () {
2553 $('body').on('click', '#give-payments-filter input[type="submit"]', this.handleBulkActions);
2554 },
2555
2556 handleBulkActions: function () {
2557 var currentAction = $(this).closest('.tablenav').find('select').val(),
2558 currentActionLabel = $(this).closest('.tablenav').find('option[value="' + currentAction + '"]').text(),
2559 $payments = $('input[name="payment[]"]:checked').length,
2560 isStatusTypeAction = ( -1 !== currentAction.indexOf('set-status-') ),
2561 confirmActionNotice = '',
2562 status = '';
2563
2564 // Set common action, if action type is status.
2565 currentAction = isStatusTypeAction ?
2566 'set-to-status' :
2567 currentAction;
2568
2569 if (Object.keys(give_vars.donations_bulk_action).length) {
2570 for (status in give_vars.donations_bulk_action) {
2571 if (status === currentAction) {
2572
2573 // Get status text if current action types is status.
2574 confirmActionNotice = isStatusTypeAction ?
2575 give_vars.donations_bulk_action[currentAction].zero.replace('{status}', currentActionLabel.replace('Set To ', '')) :
2576 give_vars.donations_bulk_action[currentAction].zero;
2577
2578 // Check if admin selected any donations or not.
2579 if (!parseInt($payments)) {
2580 alert(confirmActionNotice);
2581 return false;
2582 }
2583
2584 // Get message on basis of payment count.
2585 confirmActionNotice = ( 1 < $payments ) ?
2586 give_vars.donations_bulk_action[currentAction].multiple :
2587 give_vars.donations_bulk_action[currentAction].single;
2588
2589 // Trigger Admin Confirmation PopUp.
2590 return window.confirm(confirmActionNotice
2591 .replace('{payment_count}', $payments)
2592 .replace('{status}', currentActionLabel.replace('Set To ', ''))
2593 );
2594 }
2595 }
2596 }
2597
2598 return true;
2599 }
2600 };
2601
2602 // On DOM Ready.
2603 $(function () {
2604
2605 give_dismiss_notice();
2606 enable_admin_datepicker();
2607 handle_status_change();
2608 setup_chosen_give_selects();
2609 $.giveAjaxifyFields({type: 'country_state', debug: true});
2610 GiveListDonation.init();
2611 Give_Edit_Donation.init();
2612 Give_Settings.init();
2613 Give_Reports.init();
2614 GiveDonor.init();
2615 API_Screen.init();
2616 Give_Export.init();
2617 Give_Updates.init();
2618 Edit_Form_Screen.init();
2619 GivePaymentHistory.init();
2620
2621
2622 // Footer.
2623 $('a.give-rating-link').click(function () {
2624 jQuery(this).parent().text(jQuery(this).data('rated'));
2625 });
2626
2627 // Ajax user search.
2628 $('.give-ajax-user-search').on('keyup', function () {
2629 var user_search = $(this).val();
2630 var exclude = '';
2631
2632 if ($(this).data('exclude')) {
2633 exclude = $(this).data('exclude');
2634 }
2635
2636 $('.give-ajax').show();
2637 data = {
2638 action: 'give_search_users',
2639 user_name: user_search,
2640 exclude: exclude
2641 };
2642
2643 document.body.style.cursor = 'wait';
2644
2645 $.ajax({
2646 type: 'POST',
2647 data: data,
2648 dataType: 'json',
2649 url: ajaxurl,
2650 success: function (search_response) {
2651 $('.give-ajax').hide();
2652 $('.give_user_search_results').removeClass('hidden');
2653 $('.give_user_search_results span').html('');
2654 $(search_response.results).appendTo('.give_user_search_results span');
2655 document.body.style.cursor = 'default';
2656 }
2657 });
2658 });
2659
2660 $('body').on('click.giveSelectUser', '.give_user_search_results span a', function (e) {
2661 e.preventDefault();
2662 var login = $(this).data('login');
2663 $('.give-ajax-user-search').val(login);
2664 $('.give_user_search_results').addClass('hidden');
2665 $('.give_user_search_results span').html('');
2666 });
2667
2668 $('body').on('click.giveCancelUserSearch', '.give_user_search_results a.give-ajax-user-cancel', function (e) {
2669 e.preventDefault();
2670 $('.give-ajax-user-search').val('');
2671 $('.give_user_search_results').addClass('hidden');
2672 $('.give_user_search_results span').html('');
2673 });
2674
2675 // This function uses for adding qtip to money/price field.
2676 function give_add_qtip($fields) {
2677
2678 // Add qtip to all existing money input fields.
2679 $fields.each(function () {
2680 $(this).qtip({
2681 style: 'qtip-dark qtip-tipsy',
2682 content: {
2683 text: give_vars.price_format_guide.trim()
2684 },
2685 show: '',
2686 position: {
2687 my: 'bottom center',
2688 at: 'top center'
2689 }
2690 });
2691 });
2692 }
2693
2694 var $poststuff = $( '#poststuff' ),
2695 thousand_separator = give_vars.thousands_separator,
2696 decimal_separator = give_vars.decimal_separator,
2697 thousand_separator_count = '',
2698 alphabet_count = '',
2699 price_string = '',
2700
2701 // Thousand separation limit in price depends upon decimal separator symbol.
2702 // If thousand separator is equal to decimal separator then price does not have more then 1 thousand separator otherwise limit is zero.
2703 thousand_separator_limit = ( decimal_separator === thousand_separator ? 1 : 0 );
2704
2705 // Check & show message on keyup event.
2706 $poststuff.on('keyup', 'input.give-money-field, input.give-price-field', function () {
2707 var tootltip_setting = {
2708 label: give_vars.price_format_guide.trim()
2709 };
2710
2711 // Count thousand separator in price string.
2712 thousand_separator_count = ( $(this).val().match(new RegExp(thousand_separator, 'g')) || [] ).length;
2713 alphabet_count = ( $(this).val().match(new RegExp('[a-z]', 'g')) || [] ).length;
2714
2715 // Show qtip conditionally if thousand separator detected on price string.
2716 if (( -1 !== $(this).val().indexOf(thousand_separator) ) && ( thousand_separator_limit < thousand_separator_count )) {
2717 $(this).giveHintCss('show', tootltip_setting);
2718 } else if (alphabet_count) {
2719 $(this).giveHintCss('show', tootltip_setting);
2720 } else {
2721 $(this).giveHintCss('hide', tootltip_setting);
2722 }
2723
2724 // Reset thousand separator count.
2725 thousand_separator_count = alphabet_count = '';
2726 });
2727
2728 // Format price sting of input field on focusout.
2729 $poststuff.on('focusout', 'input.give-money-field, input.give-price-field', function () {
2730 price_string = give_unformat_currency($(this).val(), false);
2731
2732 // Back out.
2733 if (give_unformat_currency('0', false) === give_unformat_currency($(this).val(), false)) {
2734 var default_amount = $(this).attr('placeholder');
2735 default_amount = !default_amount ? '0' : default_amount;
2736
2737 $(this).val(default_amount);
2738
2739 return false;
2740 }
2741
2742 // Replace dot decimal separator with user defined decimal separator.
2743 price_string = price_string.replace('.', decimal_separator);
2744
2745 // Check if current number is negative or not.
2746 if (-1 !== price_string.indexOf('-')) {
2747 price_string = price_string.replace('-', '');
2748 }
2749
2750 // Update format price string in input field.
2751 $(this).val(price_string);
2752 });
2753
2754 // Set default value to 1 even if user inputs empty or negative number of donations.
2755 $poststuff.on( 'focusout', '#_give_number_of_donation_goal', function() {
2756 if ( 1 > $( this ).val() ) {
2757 $( this ).val( 1 );
2758 }
2759 });
2760
2761 /**
2762 * Responsive setting tab features.
2763 */
2764
2765 // Show/Hide sub tab nav.
2766 $('.give-settings-page').on('click', '#give-show-sub-nav', function (e) {
2767 e.preventDefault();
2768
2769 var $sub_tab_nav = $(this).next();
2770
2771 if (!$sub_tab_nav.is(':hover')) {
2772 $sub_tab_nav.toggleClass('give-hidden');
2773 }
2774
2775 return false;
2776 }).on('blur', '#give-show-sub-nav', function () {
2777 var $sub_tab_nav = $(this).next();
2778
2779 if (!$sub_tab_nav.is(':hover')) {
2780 $sub_tab_nav.addClass('give-hidden');
2781 }
2782 });
2783
2784 /**
2785 * Automatically show/hide email setting fields.
2786 */
2787 $('.give_email_api_notification_status_setting input').change(function () {
2788 // Bailout.
2789 var value = $(this).val(),
2790 is_enabled = ( 'enabled' === value ),
2791 $setting_fields = {};
2792
2793 // Get setting fields.
2794 if ($(this).closest('.give_options_panel').length) {
2795 $setting_fields = $(this).closest('.give_options_panel').children('.give-field-wrap:not(.give_email_api_notification_status_setting), .give-repeatable-field-section' );
2796 } else if ($(this).closest('table').length) {
2797 $setting_fields = $(this).closest('table').find('tr:not(.give_email_api_notification_status_setting)');
2798 }
2799
2800 if (-1 === jQuery.inArray(value, ['enabled', 'disabled', 'global'])) {
2801 return false;
2802 }
2803
2804 // Bailout.
2805 if (!$setting_fields.length) {
2806 return false;
2807 }
2808
2809 // Show hide setting fields.
2810 is_enabled ? $setting_fields.show() : $setting_fields.hide();
2811 });
2812
2813 $('.give_email_api_notification_status_setting input:checked').change();
2814
2815 // Render setting tab.
2816 give_render_responsive_tabs();
2817 });
2818 })(jQuery);
2819
2820 /**
2821 * Responsive js.
2822 */
2823 jQuery(window).resize(function () {
2824 give_render_responsive_tabs();
2825 });
2826
2827 /**
2828 * Render responsive tabs
2829 */
2830 function give_render_responsive_tabs() {
2831 var $setting_page_form = jQuery( '.give-settings-page' ),
2832 $main_tab_nav = jQuery( 'h2.give-nav-tab-wrapper' ),
2833 setting_page_form_width = $setting_page_form.width(),
2834 $sub_tab_nav_wrapper = jQuery( '.give-sub-nav-tab-wrapper' ),
2835 $sub_tab_nav = jQuery( 'nav', $sub_tab_nav_wrapper ),
2836 $setting_tab_links = jQuery( 'div.give-nav-tab-wrapper > a:not(give-not-tab)' ),
2837 $show_tabs = [],
2838 $hide_tabs = [],
2839 tab_width = 0;
2840
2841 if ( 600 < jQuery( window ).outerWidth() ) {
2842 tab_width = 200;
2843 }
2844
2845 // Bailout.
2846 if ( ! $setting_page_form.length ) {
2847 return false;
2848 }
2849
2850 // Update tab wrapper css.
2851 $main_tab_nav.css({
2852 height: 'auto',
2853 overflow: 'visible'
2854 });
2855
2856 // Show all tab if anyone hidden to calculate correct tab width.
2857 $setting_tab_links.removeClass( 'give-hidden' );
2858
2859 var refactor_tabs = new Promise(
2860 function( resolve, reject ) {
2861
2862 // Collect tabs to show or hide.
2863 jQuery.each( $setting_tab_links, function( index, $tab_link ) {
2864 $tab_link = jQuery( $tab_link );
2865 tab_width = tab_width + parseInt( $tab_link.outerWidth() );
2866
2867 if ( tab_width < setting_page_form_width ) {
2868 $show_tabs.push( $tab_link );
2869 } else {
2870 $hide_tabs.push( $tab_link );
2871 }
2872 });
2873
2874 resolve( true );
2875 }
2876 );
2877
2878 refactor_tabs.then( function( is_refactor_tabs ) {
2879
2880 // Remove current tab from sub menu and add this to main menu if exist and get last tab from main menu and add this to sub menu.
2881 if ( $hide_tabs.length && ( -1 !== window.location.search.indexOf( '&tab=' ) ) ) {
2882 var $current_tab_nav = {},
2883 query_params = get_url_params();
2884
2885 $hide_tabs = $hide_tabs.filter( function( $tab_link ) {
2886 var is_current_nav_item = ( -1 !== parseInt( $tab_link.attr( 'href' ).indexOf( '&tab=' + query_params['tab'] ) ) );
2887
2888 if ( is_current_nav_item ) {
2889 $current_tab_nav = $tab_link;
2890 }
2891
2892 return ( ! is_current_nav_item );
2893 });
2894
2895 if ( $current_tab_nav.length ) {
2896 $hide_tabs.unshift( $show_tabs.pop() );
2897 $show_tabs.push( $current_tab_nav );
2898 }
2899 }
2900
2901 var show_tabs = new Promise( function( resolve, reject ) {
2902
2903 // Show main menu tabs.
2904 if ( $show_tabs.length ) {
2905 jQuery.each( $show_tabs, function( index, $tab_link ) {
2906 $tab_link = jQuery( $tab_link );
2907
2908 if ( $tab_link.hasClass( 'give-hidden' ) ) {
2909 $tab_link.removeClass( 'give-hidden' );
2910 }
2911 });
2912 }
2913
2914 resolve( true );
2915 });
2916
2917 show_tabs.then( function( is_show_tabs ) {
2918
2919 // Hide sub menu tabs.
2920 if ( $hide_tabs.length ) {
2921 $sub_tab_nav.html( '' );
2922
2923 jQuery.each( $hide_tabs, function( index, $tab_link ) {
2924 $tab_link = jQuery( $tab_link );
2925 if ( ! $tab_link.hasClass( 'nav-tab-active' ) ) {
2926 $tab_link.addClass( 'give-hidden' );
2927 }
2928 $tab_link.clone().removeClass().appendTo( $sub_tab_nav );
2929 });
2930
2931 if ( ! jQuery( '.give-sub-nav-tab-wrapper', $main_tab_nav ).length ) {
2932 $main_tab_nav.append( $sub_tab_nav_wrapper );
2933 }
2934
2935 $sub_tab_nav_wrapper.show();
2936 } else {
2937 $sub_tab_nav_wrapper.hide();
2938 }
2939 });
2940 });
2941 }
2942
2943 /**
2944 * Get url query params.
2945 *
2946 * @returns {Array}
2947 */
2948 function get_url_params() {
2949 var vars = [], hash;
2950 var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
2951 for (var i = 0; i < hashes.length; i++) {
2952 hash = hashes[i].split('=');
2953 vars[hash[0]] = hash[1];
2954 }
2955 return vars;
2956 }
2957
2958 /**
2959 * Run when user click on submit button.
2960 *
2961 * @since 1.8.17
2962 */
2963 function give_on_core_settings_import_start() {
2964 var $form = jQuery('form.tools-setting-page-import');
2965 var progress = $form.find('.give-progress');
2966
2967 give_setting_edit = true;
2968
2969 jQuery.ajax({
2970 type: 'POST',
2971 url: ajaxurl,
2972 data: {
2973 action: give_vars.core_settings_import,
2974 fields: $form.serialize()
2975 },
2976 dataType: 'json',
2977 success: function (response) {
2978 give_setting_edit = false;
2979 if (true === response.success) {
2980 jQuery(progress).find('div').width(response.percentage + '%');
2981 } else {
2982 alert(give_vars.error_message);
2983 }
2984 window.location = response.url;
2985 },
2986 error: function () {
2987 give_setting_edit = false;
2988 alert(give_vars.error_message);
2989 }
2990 });
2991 }
2992
2993 /**
2994 * Run when user click on upload CSV.
2995 *
2996 * @since 1.8.13
2997 */
2998 function give_on_donation_import_start() {
2999 give_on_donation_import_ajax();
3000 }
3001
3002 /**
3003 * Upload CSV ajax
3004 *
3005 * @since 1.8.13
3006 */
3007 function give_on_donation_import_ajax() {
3008 var $form = jQuery('form.tools-setting-page-import');
3009
3010 /**
3011 * Do not allow user to reload the page
3012 *
3013 * @since 1.8.14
3014 */
3015 give_setting_edit = true;
3016
3017 var progress = $form.find('.give-progress');
3018
3019 var total_ajax = jQuery(progress).data('total_ajax'),
3020 current = jQuery(progress).data('current'),
3021 start = jQuery(progress).data('start'),
3022 end = jQuery(progress).data('end'),
3023 next = jQuery(progress).data('next'),
3024 total = jQuery(progress).data('total'),
3025 per_page = jQuery(progress).data('per_page');
3026
3027 jQuery.ajax({
3028 type: 'POST',
3029 url: ajaxurl,
3030 data: {
3031 action: give_vars.give_donation_import,
3032 total_ajax: total_ajax,
3033 current: current,
3034 start: start,
3035 end: end,
3036 next: next,
3037 total: total,
3038 per_page: per_page,
3039 fields: $form.serialize()
3040 },
3041 dataType: 'json',
3042 success: function (response) {
3043 jQuery(progress).data('current', response.current);
3044 jQuery(progress).find('div').width(response.percentage + '%');
3045
3046 if (response.next == true) {
3047 jQuery(progress).data('start', response.start);
3048 jQuery(progress).data('end', response.end);
3049
3050 if (response.last == true) {
3051 jQuery(progress).data('next', false);
3052 }
3053 give_on_donation_import_ajax();
3054 } else {
3055 /**
3056 * Now user is allow to reload the page.
3057 *
3058 * @since 1.8.14
3059 */
3060 give_setting_edit = false;
3061 window.location = response.url;
3062 }
3063 },
3064 error: function () {
3065 /**
3066 * Now user is allow to reload the page.
3067 *
3068 * @since 1.8.14
3069 */
3070 give_setting_edit = false;
3071 alert(give_vars.error_message);
3072 }
3073 });
3074 }