PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.0.0
GiveWP – Donation Plugin and Fundraising Platform v2.0.0
4.16.5.1 4.16.5 4.16.4 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
3071 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 window.setTimeout(Give_Updates.get_db_updates_info, 1000, $self );
1090 }
1091
1092 // Bailout.
1093 if ($self.el.update_link.hasClass('active')) {
1094 return;
1095 }
1096
1097 $self.el.update_link.on('click', '', function (e) {
1098 e.preventDefault();
1099
1100 $self.el.run_upload_container.find('.notice').remove();
1101 $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>');
1102 });
1103
1104 $('#give-db-updates').on('click', 'a.give-run-update-button', function (e) {
1105 e.preventDefault();
1106
1107 if ($(this).hasClass('active')) {
1108 return false;
1109 }
1110
1111 $(this).addClass('active').fadeOut();
1112 $self.el.update_link.addClass('active').fadeOut();
1113 $('#give-db-updates .give-run-update-containt').slideUp();
1114
1115 $self.el.progress_container.find('.notice-wrap').remove();
1116 $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>');
1117 $self.el.progress_main_container.removeClass('give-hidden');
1118
1119 $.ajax({
1120 type: 'POST',
1121 url: ajaxurl,
1122 data: {
1123 action: 'give_run_db_updates',
1124 run_db_update: 1
1125 },
1126 dataType: 'json',
1127 success: function (response) {
1128
1129 }
1130 });
1131
1132 window.setTimeout(Give_Updates.get_db_updates_info, 500, $self );
1133
1134 return false;
1135 });
1136 },
1137
1138 get_db_updates_info: function( $self ){
1139 $.ajax({
1140 type: 'POST',
1141 url: ajaxurl,
1142 data: {
1143 action: 'give_db_updates_info',
1144 },
1145 dataType: 'json',
1146 success: function (response) {
1147 // We need to get the actual in progress form, not all forms on the page.
1148 var notice_wrap = Give_Selector_Cache.get('.notice-wrap', $self.el.progress_container, true);
1149
1150 if (-1 !== $.inArray('success', Object.keys(response))) {
1151 if (response.success) {
1152 if ($self.el.update_progress_counter.length) {
1153 $self.el.update_progress_counter.text('100%');
1154 }
1155
1156 // Update steps info.
1157 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1158 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1159 }
1160
1161 $self.el.update_link.closest('p').remove();
1162 notice_wrap.html('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p><button type="button" class="notice-dismiss"></button></div>');
1163
1164 } else {
1165 // Update steps info.
1166 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1167 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1168 }
1169
1170 notice_wrap.html('<div class="notice notice-error"><p>' + response.data.message + '</p></div>');
1171
1172 setTimeout(function () {
1173 $self.el.update_link.removeClass('active').show();
1174 $self.el.progress_main_container.addClass('give-hidden');
1175 }, 1000);
1176 }
1177 } else {
1178 if (response && -1 !== $.inArray('percentage', Object.keys(response.data))) {
1179 if ($self.el.update_progress_counter.length) {
1180 $self.el.update_progress_counter.text(response.data.total_percentage + '%');
1181 }
1182
1183 // Update steps info.
1184 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1185 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1186 }
1187
1188 // Update progress.
1189 $('.give-progress div', '#give-db-updates').animate({
1190 width: response.data.percentage + '%',
1191 }, 50, function () {
1192 // Animation complete.
1193 });
1194
1195 window.setTimeout(Give_Updates.get_db_updates_info, 1000, $self );
1196 } else {
1197 notice_wrap.html('<div class="notice notice-error"><p>' + give_vars.updates.ajax_error + '</p></div>');
1198
1199 setTimeout(function () {
1200 $self.el.update_link.removeClass('active').show();
1201 $self.el.progress_main_container.addClass('give-hidden');
1202 }, 1000);
1203 }
1204 }
1205 }
1206 });
1207 },
1208
1209 process_step: function (step, update, $self) {
1210
1211 give_setting_edit = true;
1212
1213 $.ajax({
1214 type: 'POST',
1215 url: ajaxurl,
1216 data: {
1217 action: 'give_do_ajax_updates',
1218 step: parseInt(step),
1219 update: parseInt(update)
1220 },
1221 dataType: 'json',
1222 success: function (response) {
1223 give_setting_edit = false;
1224
1225 // We need to get the actual in progress form, not all forms on the page.
1226 var notice_wrap = Give_Selector_Cache.get('.notice-wrap', $self.el.progress_container, true);
1227
1228 if (-1 !== $.inArray('success', Object.keys(response))) {
1229 if (response.success) {
1230 // Update steps info.
1231 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1232 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1233 }
1234
1235 $self.el.update_link.closest('p').remove();
1236 notice_wrap.html('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p><button type="button" class="notice-dismiss"></button></div>');
1237
1238 } else {
1239 // Update steps info.
1240 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1241 $self.el.heading.html('<strong>' + response.data.heading + '</strong>');
1242 }
1243
1244 notice_wrap.html('<div class="notice notice-error"><p>' + response.data.message + '</p></div>');
1245
1246 setTimeout(function () {
1247 $self.el.update_link.removeClass('active').show();
1248 $self.el.progress_main_container.addClass('give-hidden');
1249 }, 5000);
1250 }
1251 } else {
1252 if (response && -1 !== $.inArray('percentage', Object.keys(response.data))) {
1253 // Update progress.
1254 $('.give-progress div', '#give-db-updates').animate({
1255 width: response.data.percentage + '%',
1256 }, 50, function () {
1257 // Animation complete.
1258 });
1259
1260 // Update steps info.
1261 if (-1 !== $.inArray('heading', Object.keys(response.data))) {
1262 $self.el.heading.html('<strong>' + response.data.heading.replace('{update_count}', $self.el.heading.data('update-count')) + '</strong>');
1263 }
1264
1265 $self.process_step(parseInt(response.data.step), response.data.update, $self);
1266 } else {
1267 notice_wrap.html('<div class="notice notice-error"><p>' + give_vars.updates.ajax_error + '</p></div>');
1268
1269 setTimeout(function () {
1270 $self.el.update_link.removeClass('active').show();
1271 $self.el.progress_main_container.addClass('give-hidden');
1272 }, 5000);
1273 }
1274 }
1275
1276 }
1277 }).fail(function (response) {
1278
1279 give_setting_edit = false;
1280
1281 if (window.console && window.console.log) {
1282 console.log(response);
1283 }
1284
1285 Give_Selector_Cache.get('.notice-wrap', self.el.progress_container).append(response.responseText);
1286
1287 }).always(function () {
1288 });
1289
1290 },
1291
1292 dismiss_message: function () {
1293 $('body').on('click', '#poststuff .notice-dismiss', function () {
1294 $(this).parent().slideUp('fast');
1295 });
1296 }
1297
1298 };
1299
1300 /**
1301 * Admin Status Select Field Change
1302 *
1303 * @description: Handle status switching
1304 * @since: 1.0
1305 */
1306 var handle_status_change = function () {
1307
1308 $('select[name="give-payment-status"]').on('change', function () {
1309
1310 var status = $(this).val();
1311
1312 $('.give-donation-status').removeClass(function (index, css) {
1313 return (css.match(/\bstatus-\S+/g) || []).join(' ');
1314 }).addClass('status-' + status);
1315
1316 });
1317
1318 };
1319
1320 /**
1321 * Donor management screen JS
1322 */
1323 var GiveDonor = {
1324
1325 init: function () {
1326 this.editDonor();
1327 this.add_email();
1328 this.removeUser();
1329 this.cancelEdit();
1330 this.add_note();
1331 this.delete_checked();
1332 this.addressesAction();
1333 this.unlockDonorFields();
1334 this.bulkDeleteDonor();
1335 $( 'body' ).on( 'click', '#give-donors-filter .bulkactions input[type="submit"]', this.handleBulkActions );
1336 },
1337
1338 unlockDonorFields: function (e) {
1339 $('body').on('click', '.give-lock-block', function (e) {
1340 alert(give_vars.unlock_donor_fields);
1341 e.preventDefault();
1342 });
1343 },
1344
1345 editDonor: function () {
1346 $('body').on('click', '#edit-donor', function (e) {
1347 e.preventDefault();
1348 $('#give-donor-card-wrapper .editable').hide();
1349 $('#give-donor-card-wrapper .edit-item').fadeIn().css('display', 'block');
1350 });
1351 },
1352
1353 removeUser: function () {
1354 $('body').on('click', '#disconnect-donor', function (e) {
1355 e.preventDefault();
1356
1357 if (!confirm(give_vars.disconnect_user)) {
1358 return false;
1359 }
1360
1361 var donorID = $('input[name="customerinfo[id]"]').val();
1362
1363 var postData = {
1364 give_action: 'disconnect-userid',
1365 customer_id: donorID,
1366 _wpnonce: $('#edit-donor-info #_wpnonce').val()
1367 };
1368
1369 $.post(ajaxurl, postData, function (response) {
1370 window.location.href = response.redirect;
1371 }, 'json');
1372
1373 });
1374 },
1375
1376 cancelEdit: function () {
1377 $('body').on('click', '#give-edit-donor-cancel', function (e) {
1378 e.preventDefault();
1379 $('#give-donor-card-wrapper .edit-item').hide();
1380 $('#give-donor-card-wrapper .editable').show();
1381 $('.give_user_search_results').html('');
1382 });
1383 },
1384
1385 add_note: function () {
1386 $('body').on('click', '#add-donor-note', function (e) {
1387 e.preventDefault();
1388 var postData = {
1389 give_action: 'add-donor-note',
1390 customer_id: $('#donor-id').val(),
1391 donor_note: $('#donor-note').val(),
1392 add_donor_note_nonce: $('#add_donor_note_nonce').val()
1393 };
1394
1395 if (postData.donor_note) {
1396
1397 $.ajax({
1398 type: 'POST',
1399 data: postData,
1400 url: ajaxurl,
1401 success: function (response) {
1402 $('#give-donor-notes').prepend(response);
1403 $('.give-no-donor-notes').hide();
1404 $('#donor-note').val('');
1405 }
1406 }).fail(function (data) {
1407 if (window.console && window.console.log) {
1408 console.log(data);
1409 }
1410 });
1411
1412 } else {
1413 var border_color = $('#donor-note').css('border-color');
1414 $('#donor-note').css('border-color', 'red');
1415 setTimeout(function () {
1416 $('#donor-note').css('border-color', border_color);
1417 }, 500);
1418 }
1419 });
1420 },
1421 delete_checked: function () {
1422 $('#give-donor-delete-confirm').change(function () {
1423 var records_input = $('#give-donor-delete-records');
1424 var submit_button = $('#give-delete-donor');
1425
1426 if ($(this).prop('checked')) {
1427 records_input.attr('disabled', false);
1428 submit_button.attr('disabled', false);
1429 } else {
1430 records_input.attr('disabled', true);
1431 records_input.prop('checked', false);
1432 submit_button.attr('disabled', true);
1433 }
1434 });
1435 },
1436 add_email: function () {
1437 if (!$('#add-donor-email').length) {
1438 return;
1439 }
1440
1441 $(document.body).on('click', '#add-donor-email', function (e) {
1442 e.preventDefault();
1443 var button = $(this);
1444 var wrapper = button.parent();
1445
1446 wrapper.parent().find('.notice-wrap').remove();
1447 wrapper.find('.spinner').css('visibility', 'visible');
1448 button.attr('disabled', true);
1449
1450 var customer_id = wrapper.find('input[name="donor-id"]').val();
1451 var email = wrapper.find('input[name="additional-email"]').val();
1452 var primary = wrapper.find('input[name="make-additional-primary"]').is(':checked');
1453 var nonce = wrapper.find('input[name="add_email_nonce"]').val();
1454
1455 var postData = {
1456 give_action: 'add_donor_email',
1457 customer_id: customer_id,
1458 email: email,
1459 primary: primary,
1460 _wpnonce: nonce
1461 };
1462
1463 $.post(ajaxurl, postData, function (response) {
1464
1465 if (true === response.success) {
1466 window.location.href = response.redirect;
1467 } else {
1468 button.attr('disabled', false);
1469 wrapper.after('<div class="notice-wrap"><div class="notice notice-error inline"><p>' + response.message + '</p></div></div>');
1470 wrapper.find('.spinner').css('visibility', 'hidden');
1471 }
1472
1473 }, 'json');
1474
1475 });
1476 },
1477
1478 addressesAction: function () {
1479 var $obj = this,
1480 $addressWrapper = $('#donor-address-wrapper'),
1481 $allAddress = $('.all-address', $addressWrapper),
1482 $noAddressMessageWrapper = $('.give-no-address-message', $addressWrapper),
1483 $allAddressParent = $($allAddress).parent(),
1484 $addressForm = $('.address-form', $addressWrapper),
1485 $addressFormCancelBtn = $('.js-cancel', $addressForm),
1486 $addressFormCountryField = $('select[name="country"]', $addressForm),
1487 $addNewAddressBtn = $('.add-new-address', $addressWrapper),
1488 donorID = parseInt($('input[name="donor-id"]').val());
1489
1490 $addressFormCountryField.on('change', function () {
1491 $(this).trigger('chosen:updated');
1492 });
1493
1494 // Edit current address button event.
1495 $allAddress.on('click', '.js-edit', function (e) {
1496 var $parent = $(this).closest('.address');
1497
1498 e.preventDefault();
1499
1500 // Remove notice.
1501 $('.notice', $allAddressParent).remove();
1502
1503 $obj.__set_address_form_val($parent);
1504 $obj.__set_address_form_action('update', $parent.data('address-id'));
1505
1506 $addNewAddressBtn.hide();
1507 $allAddress.addClass('give-hidden');
1508 $addressForm.removeClass('add-new-address-form-hidden');
1509 $addressForm.data('process', 'update');
1510 });
1511
1512 // Remove address button event.
1513 $allAddress.on('click', '.js-remove', function (e) {
1514 e.preventDefault();
1515
1516 var $parent = $(this).closest('.address');
1517
1518 // Remove notice.
1519 $('.notice', $allAddressParent).remove();
1520
1521 $addressForm.data('changed', true);
1522 $obj.__set_address_form_val($parent);
1523 $obj.__set_address_form_action('remove', $parent.data('address-id'));
1524
1525 $addressForm.trigger('submit');
1526 });
1527
1528 // Add new address button event.
1529 $addNewAddressBtn.on('click', function (e) {
1530 e.preventDefault();
1531
1532 // Remove notice.
1533 $('.notice', $allAddressParent).remove();
1534
1535 $(this).hide();
1536 $allAddress.addClass('give-hidden');
1537 $addressForm.removeClass('add-new-address-form-hidden');
1538 $obj.__set_address_form_action('add');
1539
1540
1541 $obj.__set_address_form_action();
1542 });
1543
1544 // Cancel add new address form button event.
1545 $addressFormCancelBtn.on('click', function (e) {
1546 e.preventDefault();
1547
1548 // Reset form.
1549 $addressForm.find('input[type="text"]').val('');
1550
1551 $addNewAddressBtn.show();
1552 $allAddress.removeClass('give-hidden');
1553 $addressForm.addClass('add-new-address-form-hidden');
1554 });
1555
1556 // Save address.
1557 $addressForm
1558 .on('change', function () {
1559 $(this).data('changed', true);
1560 })
1561 .on('submit', function (e) {
1562 e.preventDefault();
1563
1564 var $this = $(this);
1565
1566 // Remove notice.
1567 $('.notice', $allAddressParent).remove();
1568
1569 // Do not send ajax if form does not change.
1570 if (!$(this).data('changed')) {
1571 $addNewAddressBtn.show();
1572 $allAddress.removeClass('give-hidden');
1573 $addressForm.addClass('add-new-address-form-hidden');
1574
1575 return false;
1576 }
1577
1578 $.ajax({
1579 type: 'POST',
1580 url: ajaxurl,
1581 data: {
1582 action: 'donor_manage_addresses',
1583 donorID: donorID,
1584 form: $('form', $addressForm).serialize()
1585 },
1586 beforeSend: function () {
1587 giveAjaxLoader($addressWrapper, {show: true});
1588 },
1589 success: function (response) {
1590 giveAjaxLoader($addressWrapper);
1591
1592 if (response.success) {
1593 var parent;
1594
1595 switch (response.data.action) {
1596 case 'add':
1597 $('.give-grid-row', $allAddress).append(response.data.address_html);
1598
1599 if (!$noAddressMessageWrapper.hasClass('give-hidden') && $('div.give-grid-col-4', $allAddress).length) {
1600 $noAddressMessageWrapper.addClass('give-hidden');
1601 }
1602 break;
1603
1604 case 'remove':
1605 parent = $allAddress
1606 .find('div[data-address-id*="' + response.data.id + '"]').parent();
1607
1608 if (parent.length) {
1609 parent.animate(
1610 {'margin-left': '-999'},
1611 1000,
1612 function () {
1613 parent.remove();
1614
1615 if (
1616 $noAddressMessageWrapper.hasClass('give-hidden') &&
1617 !$('div.give-grid-col-4', $allAddress).length
1618 ) {
1619 $noAddressMessageWrapper.removeClass('give-hidden');
1620 }
1621 }
1622 );
1623 }
1624
1625 break;
1626
1627 case 'update':
1628 parent = $allAddress
1629 .find('div[data-address-id*="' + response.data.id + '"]').parent();
1630 var $prevParent = parent.prev(),
1631 $nextParent = {},
1632 is_address_added = false;
1633
1634 if (parseInt($('.give-grid-row>div', $allAddress).length) < 2) {
1635 $('.give-grid-row', $allAddress).append(response.data.address_html);
1636 } else {
1637 if ($prevParent.length) {
1638 $prevParent.after(response.data.address_html);
1639 is_address_added = true;
1640 }
1641
1642 if (!is_address_added) {
1643 $nextParent = parent.next();
1644
1645 if ($nextParent.length) {
1646 $nextParent.before(response.data.address_html);
1647 }
1648 }
1649 }
1650
1651 parent.remove();
1652
1653 break;
1654 }
1655
1656 $allAddressParent.prepend(response.data.success_msg);
1657
1658 } else {
1659 $allAddressParent.prepend(response.data.error_msg);
1660 }
1661 },
1662 dataType: 'json'
1663 }).always(function () {
1664 $this.data('changed', false);
1665
1666 // Reset form.
1667 $addressForm.find('input[type="text"]').val('');
1668
1669 $addNewAddressBtn.show();
1670 $allAddress.removeClass('give-hidden');
1671 $addressForm.addClass('add-new-address-form-hidden');
1672 });
1673
1674 return false;
1675 });
1676 },
1677
1678 __set_address_form_action: function (addressAction, addressID) {
1679 var $addressWrapper = $('#donor-address-wrapper'),
1680 $addressForm = $('.address-form', $addressWrapper),
1681 $addressActionField = $('input[name="address-action"]', $addressForm),
1682 $addressIDField = $('input[name="address-id"]', $addressForm);
1683
1684 addressAction = addressAction || 'add';
1685 addressID = addressID || 'billing';
1686
1687 $addressActionField.val(addressAction);
1688 $addressIDField.val(addressID);
1689 },
1690
1691 __set_address_form_val: function ($form) {
1692 var $addressWrapper = $('#donor-address-wrapper'),
1693 $addressForm = $('.address-form', $addressWrapper),
1694 state = $('[data-address-type="state"]', $form).text().substr(2).trim(); // State will be like ", HR".
1695
1696 if ($('select[name="country"]', $addressForm).val().trim() !== $('[data-address-type="country"]', $form).text().trim()) {
1697 $('select[name="country"]', $addressForm).val($('[data-address-type="country"]', $form).text().trim()).trigger('chosen:updated').change();
1698
1699 // Update state after some time because state load by ajax for each country.
1700 window.setTimeout(function () {
1701 $('[name="state"]', $addressForm).val(state).trigger('chosen:updated');
1702 }, 500);
1703 } else {
1704 $('[name="state"]', $addressForm).val(state).trigger('chosen:updated');
1705 }
1706
1707 $('input[name="line1"]', $addressForm).val($('[data-address-type="line1"]', $form).text().trim());
1708 $('input[name="line2"]', $addressForm).val($('[data-address-type="line2"]', $form).text().trim());
1709 $('input[name="city"]', $addressForm).val($('[data-address-type="city"]', $form).text().trim());
1710 $('input[name="zip"]', $addressForm).val($('[data-address-type="zip"]', $form).text().trim());
1711 },
1712
1713 bulkDeleteDonor: function() {
1714 var $body = $('body');
1715
1716 // Cancel button click event for donor.
1717 $body.on('click', '#give-bulk-delete-cancel', function (e) {
1718 $(this).closest('tr').hide();
1719 $('.give-skip-donor').trigger('click');
1720 e.preventDefault();
1721 });
1722
1723 // Select All checkbox.
1724 $body.on('click', '#cb-select-all-1, #cb-select-all-2', function () {
1725
1726 var selectAll = $(this);
1727
1728 // Loop through donor selector checkbox.
1729 $.each($('.donor-selector'), function () {
1730
1731 var donorId = $(this).val(),
1732 donorName = $(this).data('name'),
1733 donorHtml = '<div id="give-donor-' + donorId + '" data-id="' + donorId + '">' +
1734 '<a class="give-skip-donor" title="' + give_vars.remove_from_bulk_delete + '">X</a>' +
1735 donorName + '</div>';
1736
1737 if( selectAll.is( ':checked' ) && ! $( this ).is( ':checked' ) ) {
1738 $( '#give-bulk-donors' ).append( donorHtml );
1739 } else if ( ! selectAll.is( ':checked' ) ) {
1740 $( '#give-bulk-donors' ).find( '#give-donor-' + donorId ).remove();
1741 }
1742 });
1743 });
1744
1745 // On checking checkbox, add to bulk delete donor.
1746 $body.on('click', '.donor-selector', function () {
1747 var donorId = $(this).val(),
1748 donorName = $(this).data('name'),
1749 donorHtml = '<div id="give-donor-' + donorId + '" data-id="' + donorId + '">' +
1750 '<a class="give-skip-donor" title="' + give_vars.remove_from_bulk_delete + '">X</a>' +
1751 donorName + '</div>';
1752
1753 if ($(this).is(':checked')) {
1754 $('#give-bulk-donors').prepend(donorHtml);
1755 } else {
1756 $('#give-bulk-donors').find('#give-donor-' + donorId).remove();
1757 }
1758 });
1759
1760 // CheckBox click event to confirm deletion of donor.
1761 $body.on('click', '#give-delete-donor-confirm', function () {
1762 if ($(this).is(':checked')) {
1763 $('#give-bulk-delete-button').removeAttr('disabled');
1764 } else {
1765 $('#give-bulk-delete-button').attr('disabled', true);
1766 $('#give-delete-donor-records').removeAttr('checked');
1767 }
1768 });
1769
1770 // CheckBox click event to delete records with donor.
1771 $body.on('click', '#give-delete-donor-records', function () {
1772 if ($(this).is(':checked')) {
1773 $('#give-delete-donor-confirm').attr('checked', 'checked');
1774 $('#give-bulk-delete-button').removeAttr('disabled');
1775 }
1776 });
1777
1778 // Skip Donor from Bulk Delete List.
1779 $body.on('click', '.give-skip-donor', function () {
1780 var donorId = $(this).closest('div').data('id');
1781 $('#give-donor-' + donorId).remove();
1782 $('#donor-' + donorId).find('input[type="checkbox"]').removeAttr('checked');
1783 });
1784
1785 // Clicking Event to Delete Single Donor.
1786 $body.on( 'click', '.give-single-donor-delete', function( e ) {
1787 var donorId = $( this ).data( 'id' ),
1788 donorSelector = $( 'tr#donor-' + donorId ).find( '.donor-selector' ),
1789 selectAll = $( '[id^="cb-select-all-"]' ),
1790 bulkDeleteList = $('#give-bulk-donors'),
1791 donorName = donorSelector.data( 'name' ),
1792 donorHtml = '<div id="give-donor-' + donorId + '" data-id="' + donorId + '">' +
1793 '<a class="give-skip-donor" title="' + give_vars.remove_from_bulk_delete + '">X</a>' +
1794 donorName + '</div>';
1795
1796 // Reset Donors List.
1797 bulkDeleteList.html('');
1798
1799 // Check whether the select all donor checkbox is already set, then unset it.
1800 if ( selectAll.is( ':checked' ) ) {
1801 selectAll.removeAttr( 'checked' );
1802 }
1803
1804 // Select the donor checkbox for which delete is clicked and others should be de-selected.
1805 $( '.donor-selector' ).removeAttr( 'checked' );
1806 donorSelector.attr( 'checked', 'checked' );
1807
1808 // Add Donor to the Bulk Delete List, if donor doesn't exists in the list.
1809 if ( $( '#give-donor-' + donorId ).length === 0 ) {
1810 bulkDeleteList.prepend(donorHtml);
1811 $('#give-bulk-delete').slideDown();
1812 }
1813
1814 e.preventDefault();
1815 });
1816 },
1817
1818 handleBulkActions: function( e ) {
1819
1820 var currentAction = $( this ).closest( '.tablenav' ).find( 'select' ).val(),
1821 donors = [],
1822 selectBulkActionNotice = give_vars.donors_bulk_action.no_action_selected,
1823 confirmActionNotice = give_vars.donors_bulk_action.no_donor_selected;
1824
1825 $.each( $( ".donor-selector:checked" ), function() {
1826 donors.push( $( this ).val() );
1827 });
1828
1829 // If there is no bulk action selected then show an alert message.
1830 if ( '-1' === currentAction ) {
1831 alert( selectBulkActionNotice );
1832 return false;
1833 }
1834
1835 // If there is no donor selected then show an alert.
1836 if ( ! parseInt( donors ) ) {
1837 alert( confirmActionNotice );
1838 return false;
1839 }
1840
1841 if( 'delete' === currentAction ) {
1842 $( '#give-bulk-delete' ).slideDown();
1843 }
1844
1845 e.preventDefault();
1846 }
1847 };
1848
1849 /**
1850 * API screen JS
1851 */
1852 var API_Screen = {
1853
1854 init: function () {
1855 this.revoke_api_key();
1856 this.regenerate_api_key();
1857 },
1858
1859 revoke_api_key: function () {
1860 $('body').on('click', '.give-revoke-api-key', function (e) {
1861 return confirm(give_vars.revoke_api_key);
1862 });
1863 },
1864 regenerate_api_key: function () {
1865 $('body').on('click', '.give-regenerate-api-key', function (e) {
1866 return confirm(give_vars.regenerate_api_key);
1867 });
1868 }
1869 };
1870
1871 /**
1872 * Edit Donation form screen Js
1873 */
1874 var Edit_Form_Screen = {
1875 init: function () {
1876 var default_tab_id = $.query.get('give_tab').length ? $.query.get('give_tab') : 'form_field_options';
1877
1878 this.handle_metabox_tab_click();
1879 this.setup_colorpicker_fields();
1880 this.setup_media_fields();
1881 this.setup_repeatable_fields();
1882 this.handle_repeater_group_events();
1883
1884 // Multi level repeater field js.
1885 this.handle_multi_levels_repeater_group_events();
1886
1887 // Set active tab on page load.
1888 this.activate_tab($('a[href="#' + default_tab_id + '"]'));
1889 },
1890
1891 /**
1892 * Attach click event handler to tabs.
1893 */
1894 handle_metabox_tab_click: function () {
1895 var self = this;
1896 var $tab_links = $('.give-metabox-tabs a');
1897
1898 $tab_links.on('click', function (e) {
1899 e.preventDefault();
1900 $this = $(this);
1901 self.activate_tab($this);
1902 self.update_query($this);
1903 });
1904 },
1905
1906 /**
1907 * Set the active tab.
1908 */
1909 activate_tab: function ($tab_link) {
1910 var tab_id = $tab_link.data('tab-id'),
1911 $li_parent = $tab_link.parent(),
1912 $sub_field = $('ul.give-metabox-sub-tabs', $li_parent),
1913 has_sub_field = $sub_field.length,
1914 $tab_links = $('.give-metabox-tabs a'),
1915 $all_tab_links_li = $tab_links.parents('li'),
1916 $all_sub_fields = $('ul.give-metabox-sub-tabs'),
1917 in_sub_fields = $tab_link.parents('ul.give-metabox-sub-tabs').length;
1918
1919 // Update active tab hidden field to maintain tab after save.
1920 $('#give_form_active_tab').val(tab_id);
1921
1922 if (has_sub_field) {
1923 $li_parent.toggleClass('active');
1924 $sub_field.removeClass('give-hidden');
1925
1926 var $active_subtab_li = $('li.active', 'ul.give-metabox-sub-tabs');
1927
1928 // Show hide sub fields if any and exit.
1929 $all_sub_fields.not($sub_field).addClass('give-hidden');
1930 $all_tab_links_li.not($li_parent).removeClass('active');
1931
1932 $active_subtab_li.addClass('active');
1933 } else if (!in_sub_fields) {
1934 // Hide all tab and sub tabs.
1935 $all_tab_links_li.each(function (index, item) {
1936 item = $(item);
1937 item.removeClass('active');
1938
1939 if (item.hasClass('has-sub-fields')) {
1940 $('ul.give-metabox-sub-tabs', item).addClass('give-hidden');
1941 }
1942 });
1943 } else if (in_sub_fields) {
1944 // Hide all sub tabs.
1945 $('ul.give-metabox-sub-tabs').addClass('give-hidden');
1946 $all_tab_links_li.removeClass('active');
1947
1948 // Hide all tab inside sub tabs.
1949 $tab_link.parents('ul.give-metabox-sub-tabs')
1950 .removeClass('give-hidden')
1951 .children('li')
1952 .removeClass('active');
1953
1954 // Add active class to parent li.
1955 $tab_link.parents('li.has-sub-fields').addClass('active');
1956 }
1957
1958 // Add active class to current tab link.
1959 $tab_link.parent().addClass('active');
1960
1961 // Hide all tab contents.
1962 $('.give_options_panel').removeClass('active');
1963
1964 // Show tab content.
1965 $($tab_link.attr('href')).addClass('active');
1966 },
1967
1968 /**
1969 * Update query string with active tab ID.
1970 */
1971 update_query: function ($tab_link) {
1972 var tab_id = $tab_link.data('tab-id');
1973 var new_query = $.query.set('give_tab', tab_id).remove('message').toString();
1974
1975 if (history.replaceState) {
1976 history.replaceState(null, null, new_query);
1977 }
1978 },
1979
1980 /**
1981 * Initialize colorpicker.
1982 */
1983 setup_colorpicker_fields: function () {
1984 $(document).ready(function () {
1985 var $colorpicker_fields = $('.give-colorpicker');
1986
1987 if ($colorpicker_fields.length) {
1988 $colorpicker_fields.each(function (index, item) {
1989 var $item = $(item);
1990
1991 // Bailout: do not automatically initialize color picker for repeater field group template.
1992 if ($item.parents('.give-template').length) {
1993 return;
1994 }
1995
1996 $item.wpColorPicker();
1997 });
1998 }
1999 });
2000 },
2001
2002 setup_media_fields: function () {
2003 var give_media_uploader,
2004 $give_upload_button,
2005 $body = $('body');
2006
2007 /**
2008 * Set media modal.
2009 */
2010 $body.on('click', '.give-upload-button', function (e) {
2011 e.preventDefault();
2012 var $media_modal_config = {};
2013
2014 // Cache input field.
2015 $give_upload_button = $(this);
2016
2017 // Set modal config.
2018 switch ($(this).data('field-type')) {
2019 case 'media':
2020 $media_modal_config = {
2021 title: give_vars.metabox_fields.media.button_title,
2022 button: {text: give_vars.metabox_fields.media.button_title},
2023 multiple: false, // Set to true to allow multiple files to be selected.
2024 library: {type: 'image'}
2025 };
2026 break;
2027
2028 default:
2029 $media_modal_config = {
2030 title: give_vars.metabox_fields.file.button_title,
2031 button: {text: give_vars.metabox_fields.file.button_title},
2032 multiple: false
2033 };
2034 }
2035
2036 var editing = jQuery(this).closest('.give-field-wrap').find('.give-input-field').attr('editing');
2037 if ('undefined' !== typeof( editing )) {
2038 wp.media.controller.Library.prototype.defaults.contentUserSetting = false;
2039 }
2040
2041 var $library = jQuery(this).closest('.give-field-wrap').find('.give-input-field').attr('library');
2042 if ('undefined' !== typeof( $library ) && '' !== $library) {
2043 $media_modal_config.library = {type: $library};
2044 }
2045
2046 // Extend the wp.media object.
2047 give_media_uploader = wp.media($media_modal_config);
2048
2049 // When a file is selected, grab the URL and set it as the text field's value.
2050 give_media_uploader.on('select', function () {
2051 var attachment = give_media_uploader.state().get('selection').first().toJSON(),
2052 $input_field = $give_upload_button.prev(),
2053 fvalue = ( 'id' === $give_upload_button.data('fvalue') ? attachment.id : attachment.url );
2054
2055 $body.trigger('give_media_inserted', [attachment, $input_field]);
2056
2057 // Set input field value.
2058 $input_field.val(fvalue);
2059
2060 // Update attachment id field value if fvalue is not set to id.
2061 if ('id' !== $give_upload_button.data('fvalue')) {
2062 var attachment_id_field_name = 'input[name="' + $input_field.attr('name') + '_id"]',
2063 id_field = $input_field.closest('tr').next('tr').find(attachment_id_field_name);
2064
2065 if (id_field.length) {
2066 $input_field.closest('tr').next('tr').find(attachment_id_field_name).val(attachment.id);
2067 }
2068 }
2069 });
2070
2071 // Open the uploader dialog.
2072 give_media_uploader.open();
2073 });
2074
2075 /**
2076 * Show image preview.
2077 */
2078 $body.on('give_media_inserted', function (e, attachment) {
2079 var $parent = $give_upload_button.parents('.give-field-wrap'),
2080 $image_container = $('.give-image-thumb', $parent);
2081
2082 // Bailout.
2083 if (!$image_container.length) {
2084 return false;
2085 }
2086
2087 // Bailout and hide preview.
2088 if ('image' !== attachment.type) {
2089 $image_container.addClass('give-hidden');
2090 $('img', $image_container).attr('src', '');
2091 return false;
2092 }
2093
2094 // Set the attachment URL to our custom image input field.
2095 $image_container.find('img').attr('src', attachment.url);
2096
2097 // Hide the add image link.
2098 $image_container.removeClass('give-hidden');
2099 });
2100
2101 /**
2102 * Delete Image Link.
2103 */
2104 $('span.give-delete-image-thumb', '.give-image-thumb').on('click', function (event) {
2105
2106 event.preventDefault();
2107
2108 var $parent = $(this).parents('.give-field-wrap'),
2109 $image_container = $(this).parent(),
2110 $image_input_field = $('input[type="text"]', $parent);
2111
2112 // Clear out the preview image.
2113 $image_container.addClass('give-hidden');
2114
2115 // Remove image link from input field.
2116 $image_input_field.val('');
2117
2118 // Hide the add image link.
2119 $('img', $image_container).attr('src', '');
2120 });
2121 },
2122
2123 /**
2124 * Setup repeater field.
2125 */
2126 setup_repeatable_fields: function () {
2127 jQuery(function () {
2128 jQuery('.give-repeatable-field-section').each(function () {
2129 var $this = $(this);
2130
2131 // Note: Do not change option params, it can break repeatable fields functionality.
2132 var options = {
2133 wrapper: '.give-repeatable-fields-section-wrapper',
2134 container: '.container',
2135 row: '.give-row',
2136 add: '.give-add-repeater-field-section-row',
2137 remove: '.give-remove',
2138 move: '.give-move',
2139 template: '.give-template',
2140 confirm_before_remove_row: true,
2141 confirm_before_remove_row_text: give_vars.confirm_before_remove_row_text,
2142 is_sortable: true,
2143 before_add: null,
2144 after_add: handle_metabox_repeater_field_row_count,
2145 //after_add: after_add, Note: after_add is internal function in repeatable-fields.js. Uncomment this can cause of js error.
2146 before_remove: null,
2147 after_remove: handle_metabox_repeater_field_row_remove,
2148 sortable_options: {
2149 placeholder: 'give-ui-placeholder-state-highlight',
2150 start: function (event, ui) {
2151 $('body').trigger('repeater_field_sorting_start', [ui.item]);
2152 },
2153 stop: function (event, ui) {
2154 $('body').trigger('repeater_field_sorting_stop', [ui.item]);
2155 },
2156 update: function (event, ui) {
2157 // Do not allow any row at position 0.
2158 if (ui.item.next().hasClass('give-template')) {
2159 ui.item.next().after(ui.item);
2160 }
2161
2162 var $rows = $('.give-row', $this).not('.give-template');
2163
2164 if ($rows.length) {
2165 var row_count = 1;
2166 $rows.each(function (index, item) {
2167 // Set name for fields.
2168 var $fields = $('.give-field, label', $(item));
2169
2170 if ($fields.length) {
2171 $fields.each(function () {
2172 var $parent = $(this).parents('.give-field-wrap'),
2173 $currentElement = $(this);
2174
2175 $.each(this.attributes, function (index, element) {
2176 var old_class_name_prefix = this.value.replace(/\[/g, '_').replace(/]/g, ''),
2177 old_class_name = old_class_name_prefix + '_field',
2178 new_class_name = '',
2179 new_class_name_prefix = '';
2180
2181 // Bailout.
2182 if (!this.value) {
2183 return;
2184 }
2185
2186 // Reorder index.
2187 this.value = this.value.replace(/\[\d+\]/g, '[' + (row_count - 1) + ']');
2188 new_class_name_prefix = this.value.replace(/\[/g, '_').replace(/]/g, '');
2189
2190 // Update class name.
2191 if ($parent.hasClass(old_class_name)) {
2192 new_class_name = new_class_name_prefix + '_field';
2193 $parent.removeClass(old_class_name).addClass(new_class_name);
2194 }
2195
2196 // Update field id.
2197 if (old_class_name_prefix == $currentElement.attr('id')) {
2198 $currentElement.attr('id', new_class_name_prefix);
2199 }
2200 });
2201 });
2202 }
2203
2204 row_count++;
2205 });
2206
2207 // Fire event.
2208 $this.trigger('repeater_field_row_reordered', [ui.item]);
2209 }
2210 }
2211 }
2212 //row_count_placeholder: '{{row-count-placeholder}}' Note: do not modify this param otherwise it will break repeatable field functionality.
2213 };
2214
2215 jQuery(this).repeatable_fields(options);
2216 });
2217 });
2218 },
2219
2220 /**
2221 * Handle repeater field events.
2222 */
2223 handle_repeater_group_events: function () {
2224 var $repeater_fields = $('.give-repeatable-field-section'),
2225 $body = $('body');
2226
2227 // Auto toggle repeater group
2228 $body.on('click', '.give-row-head button', function () {
2229 var $parent = $(this).closest('tr');
2230 $parent.toggleClass('closed');
2231 $('.give-row-body', $parent).toggle();
2232 });
2233
2234 // Reset header title when new row added.
2235 $repeater_fields.on('repeater_field_new_row_added repeater_field_row_deleted repeater_field_row_reordered', function () {
2236 handle_repeater_group_add_number_suffix($(this));
2237 });
2238
2239 // Disable editor when sorting start.
2240 $body.on('repeater_field_sorting_start', function (e, row) {
2241 var $textarea = $('.wp-editor-area', row);
2242
2243 if ($textarea.length) {
2244 $textarea.each(function (index, item) {
2245 window.setTimeout(
2246 function () {
2247 tinyMCE.execCommand('mceRemoveEditor', true, $(item).attr('id'));
2248 },
2249 300
2250 );
2251 });
2252 }
2253 });
2254
2255 // Enable editor when sorting stop.
2256 $body.on('repeater_field_sorting_stop', function (e, row) {
2257 var $textarea = $('.wp-editor-area', row);
2258
2259 if ($textarea.length) {
2260 $textarea.each(function (index, item) {
2261 window.setTimeout(
2262 function () {
2263 var textarea_id = $(item).attr('id');
2264 tinyMCE.execCommand('mceAddEditor', true, textarea_id);
2265
2266 // Switch editor to tmce mode to fix some glitch which appear when you reorder rows.
2267 window.setTimeout(function () {
2268 // Hack to show tmce mode.
2269 switchEditors.go(textarea_id, 'html');
2270 $('#' + textarea_id + '-tmce').trigger('click');
2271 }, 100);
2272 },
2273 300
2274 );
2275 });
2276 }
2277 });
2278
2279 // Process jobs on document load for repeater fields.
2280 $repeater_fields.each(function (index, item) {
2281 // Reset title on document load for already exist groups.
2282 var $item = $(item);
2283 handle_repeater_group_add_number_suffix($item);
2284
2285 // Close all tabs when page load.
2286 if (parseInt($item.data('close-tabs'))) {
2287 $('.give-row-head button', $item).trigger('click');
2288 $('.give-template', $item).removeClass('closed');
2289 $('.give-template .give-row-body', $item).show();
2290 }
2291 });
2292
2293 // Setup colorpicker field when row added.
2294 $repeater_fields.on('repeater_field_new_row_added', function (e, container, new_row) {
2295 $('.give-colorpicker', $(this)).each(function (index, item) {
2296 var $item = $(item);
2297
2298 // Bailout: skip already init colorpocker fields.
2299 if ($item.parents('.wp-picker-container').length || $item.parents('.give-template').length) {
2300 return;
2301 }
2302
2303 $item.wpColorPicker();
2304 });
2305
2306 // Load WordPress editor by ajax.
2307 var wysiwyg_editor_container = $('div[data-wp-editor]', new_row);
2308
2309 if (wysiwyg_editor_container.length) {
2310 wysiwyg_editor_container.each(function (index, item) {
2311 var $item = $(item),
2312 wysiwyg_editor = $('.wp-editor-wrap', $item),
2313 textarea = $('textarea', $item),
2314 textarea_id = 'give_wysiwyg_unique_' + Math.random().toString().replace('.', '_'),
2315 wysiwyg_editor_label = wysiwyg_editor.prev();
2316
2317 textarea.attr('id', textarea_id);
2318
2319 $.post(
2320 ajaxurl,
2321 {
2322 action: 'give_load_wp_editor',
2323 wp_editor: $item.data('wp-editor'),
2324 wp_editor_id: textarea_id,
2325 textarea_name: $('textarea', $item).attr('name')
2326 },
2327 function (res) {
2328 wysiwyg_editor.remove();
2329 wysiwyg_editor_label.after(res);
2330
2331 // Setup qt data for editor.
2332 tinyMCEPreInit.qtInit[textarea.attr('id')] = $.extend(
2333 true,
2334 tinyMCEPreInit.qtInit['_give_agree_text'],
2335 {id: textarea_id}
2336 );
2337
2338 // Setup mce data for editor.
2339 tinyMCEPreInit.mceInit[textarea_id] = $.extend(
2340 true,
2341 tinyMCEPreInit.mceInit['_give_agree_text'],
2342 {
2343 body_class: textarea_id + ' post-type-give_forms post-status-publish locale-' + tinyMCEPreInit.mceInit['_give_agree_text']['wp_lang_attr'].toLowerCase(),
2344 selector: '#' + textarea_id
2345 }
2346 );
2347
2348 // Setup editor.
2349 tinymce.init(tinyMCEPreInit.mceInit[textarea_id]);
2350 quicktags(tinyMCEPreInit.qtInit[textarea_id]);
2351 QTags._buttonsInit();
2352
2353 window.setTimeout(function () {
2354 // Hack to show tmce mode.
2355 switchEditors.go(textarea_id, 'html');
2356 $('#' + textarea_id + '-tmce').trigger('click');
2357 }, 100);
2358
2359 if (!window.wpActiveEditor) {
2360 window.wpActiveEditor = textarea_id;
2361 }
2362 }
2363 );
2364 });
2365 }
2366
2367 });
2368
2369 },
2370
2371 /**
2372 * Handle events for multi level repeater group.
2373 */
2374 handle_multi_levels_repeater_group_events: function () {
2375 var $repeater_fields = $('#_give_donation_levels_field');
2376
2377 // Add level title as suffix to header title when admin add level title.
2378 $('body').on('keyup', '.give-multilevel-text-field', function () {
2379 var $parent = $(this).closest('tr'),
2380 $header_title_container = $('.give-row-head h2 span', $parent),
2381 donation_level_header_text_prefix = $header_title_container.data('header-title');
2382
2383 // Donation level header already set.
2384 if ($(this).val() && ( $(this).val() === $header_title_container.html() )) {
2385 return false;
2386 }
2387
2388 if ($(this).val()) {
2389 // Change donaiton level header text.
2390 $header_title_container.html(donation_level_header_text_prefix + ': ' + $(this).val());
2391 } else {
2392 // Reset donation level header heading text.
2393 $header_title_container.html(donation_level_header_text_prefix);
2394 }
2395 });
2396
2397 // Add level title as suffix to header title on document load.
2398 $('.give-multilevel-text-field').each(function (index, item) {
2399
2400 // Skip first element.
2401 if (!index) {
2402 return;
2403 }
2404
2405 // Check if item is jquery object or not.
2406 var $item = $(item);
2407
2408 var $parent = $item.closest('tr'),
2409 $header_title_container = $('.give-row-head h2 span', $parent),
2410 donation_level_header_text_prefix = $header_title_container.data('header-title');
2411
2412 // Donation level header already set.
2413 if ($item.val() && ( $item.val() === $header_title_container.html() )) {
2414 return false;
2415 }
2416
2417 if ($item.val()) {
2418 // Change donaiton level header text.
2419 $header_title_container.html(donation_level_header_text_prefix + ': ' + $item.val());
2420 } else {
2421 // Reset donation level header heading text.
2422 $header_title_container.html(donation_level_header_text_prefix);
2423 }
2424 });
2425
2426 // Handle row deleted event for levels repeater field.
2427 $repeater_fields.on('repeater_field_row_deleted', function () {
2428 var $this = $(this);
2429
2430 window.setTimeout(
2431 function () {
2432 var $parent = $this,
2433 $repeatable_rows = $('.give-row', $parent).not('.give-template'),
2434 $default_radio = $('.give-give_default_radio_inline', $repeatable_rows),
2435 number_of_level = $repeatable_rows.length;
2436
2437 if (number_of_level === 1) {
2438 $default_radio.prop('checked', true);
2439 }
2440 },
2441 200
2442 );
2443 });
2444
2445 // Handle row added event for levels repeater field.
2446 $repeater_fields.on('repeater_field_new_row_added', function (e, container, new_row) {
2447 var $this = $(this),
2448 max_level_id = 0;
2449
2450 // Auto set default level if no level set as default.
2451 window.setTimeout(
2452 function () {
2453 // Set first row as default if selected default row deleted.
2454 // When a row is removed containing the default selection then revert default to first repeatable row.
2455 if ($('.give-give_default_radio_inline', $this).is(':checked') === false) {
2456 $('.give-row', $this)
2457 .not('.give-template')
2458 .first()
2459 .find('.give-give_default_radio_inline')
2460 .prop('checked', true);
2461 }
2462 },
2463 200
2464 );
2465
2466 // Get max level id.
2467 $('input[type="hidden"].give-levels_id', $this).each(function (index, item) {
2468 var $item = $(item),
2469 current_level = parseInt($item.val());
2470 if (max_level_id < current_level) {
2471 max_level_id = current_level;
2472 }
2473 });
2474
2475 // Auto set level id for new setting level setting group.
2476 $('input[type="hidden"].give-levels_id', new_row).val(++max_level_id);
2477 });
2478 }
2479 };
2480
2481 /**
2482 * Handle row count and field count for repeatable field.
2483 */
2484 var handle_metabox_repeater_field_row_count = function (container, new_row) {
2485 var row_count = $(container).attr('data-rf-row-count'),
2486 $container = $(container),
2487 $parent = $container.parents('.give-repeatable-field-section');
2488
2489 row_count++;
2490
2491 // Set name for fields.
2492 $('*', new_row).each(function () {
2493 $.each(this.attributes, function (index, element) {
2494 this.value = this.value.replace('{{row-count-placeholder}}', row_count - 1);
2495 });
2496 });
2497
2498 // Set row counter.
2499 $(container).attr('data-rf-row-count', row_count);
2500
2501 // Fire event: Row added.
2502 $parent.trigger('repeater_field_new_row_added', [container, new_row]);
2503 };
2504
2505 /**
2506 * Handle row remove for repeatable field.
2507 */
2508 var handle_metabox_repeater_field_row_remove = function (container) {
2509 var $container = $(container),
2510 $parent = $container.parents('.give-repeatable-field-section'),
2511 row_count = $(container).attr('data-rf-row-count');
2512
2513 // Reduce row count.
2514 $container.attr('data-rf-row-count', --row_count);
2515
2516 // Fire event: Row deleted.
2517 $parent.trigger('repeater_field_row_deleted');
2518 };
2519
2520 /**
2521 * Add number suffix to repeater group.
2522 */
2523 var handle_repeater_group_add_number_suffix = function ($parent) {
2524
2525 // Bailout: check if auto group numbering is on or not.
2526 if (!parseInt($parent.data('group-numbering'))) {
2527 return;
2528 }
2529
2530 var $header_title_container = $('.give-row-head h2 span', $parent),
2531 header_text_prefix = $header_title_container.data('header-title');
2532
2533 $header_title_container.each(function (index, item) {
2534 var $item = $(item);
2535
2536 // Bailout: do not rename header title in fields template.
2537 if ($item.parents('.give-template').length) {
2538 return;
2539 }
2540
2541 $item.html(header_text_prefix + ': ' + index);
2542 });
2543 };
2544
2545 /**
2546 * Payment history listing page js
2547 */
2548 var GivePaymentHistory = {
2549 init: function () {
2550 $('body').on('click', '#give-payments-filter input[type="submit"]', this.handleBulkActions);
2551 },
2552
2553 handleBulkActions: function () {
2554 var currentAction = $(this).closest('.tablenav').find('select').val(),
2555 currentActionLabel = $(this).closest('.tablenav').find('option[value="' + currentAction + '"]').text(),
2556 $payments = $('input[name="payment[]"]:checked').length,
2557 isStatusTypeAction = ( -1 !== currentAction.indexOf('set-status-') ),
2558 confirmActionNotice = '',
2559 status = '';
2560
2561 // Set common action, if action type is status.
2562 currentAction = isStatusTypeAction ?
2563 'set-to-status' :
2564 currentAction;
2565
2566 if (Object.keys(give_vars.donations_bulk_action).length) {
2567 for (status in give_vars.donations_bulk_action) {
2568 if (status === currentAction) {
2569
2570 // Get status text if current action types is status.
2571 confirmActionNotice = isStatusTypeAction ?
2572 give_vars.donations_bulk_action[currentAction].zero.replace('{status}', currentActionLabel.replace('Set To ', '')) :
2573 give_vars.donations_bulk_action[currentAction].zero;
2574
2575 // Check if admin selected any donations or not.
2576 if (!parseInt($payments)) {
2577 alert(confirmActionNotice);
2578 return false;
2579 }
2580
2581 // Get message on basis of payment count.
2582 confirmActionNotice = ( 1 < $payments ) ?
2583 give_vars.donations_bulk_action[currentAction].multiple :
2584 give_vars.donations_bulk_action[currentAction].single;
2585
2586 // Trigger Admin Confirmation PopUp.
2587 return window.confirm(confirmActionNotice
2588 .replace('{payment_count}', $payments)
2589 .replace('{status}', currentActionLabel.replace('Set To ', ''))
2590 );
2591 }
2592 }
2593 }
2594
2595 return true;
2596 }
2597 };
2598
2599 // On DOM Ready.
2600 $(function () {
2601
2602 give_dismiss_notice();
2603 enable_admin_datepicker();
2604 handle_status_change();
2605 setup_chosen_give_selects();
2606 $.giveAjaxifyFields({type: 'country_state', debug: true});
2607 GiveListDonation.init();
2608 Give_Edit_Donation.init();
2609 Give_Settings.init();
2610 Give_Reports.init();
2611 GiveDonor.init();
2612 API_Screen.init();
2613 Give_Export.init();
2614 Give_Updates.init();
2615 Edit_Form_Screen.init();
2616 GivePaymentHistory.init();
2617
2618
2619 // Footer.
2620 $('a.give-rating-link').click(function () {
2621 jQuery(this).parent().text(jQuery(this).data('rated'));
2622 });
2623
2624 // Ajax user search.
2625 $('.give-ajax-user-search').on('keyup', function () {
2626 var user_search = $(this).val();
2627 var exclude = '';
2628
2629 if ($(this).data('exclude')) {
2630 exclude = $(this).data('exclude');
2631 }
2632
2633 $('.give-ajax').show();
2634 data = {
2635 action: 'give_search_users',
2636 user_name: user_search,
2637 exclude: exclude
2638 };
2639
2640 document.body.style.cursor = 'wait';
2641
2642 $.ajax({
2643 type: 'POST',
2644 data: data,
2645 dataType: 'json',
2646 url: ajaxurl,
2647 success: function (search_response) {
2648 $('.give-ajax').hide();
2649 $('.give_user_search_results').removeClass('hidden');
2650 $('.give_user_search_results span').html('');
2651 $(search_response.results).appendTo('.give_user_search_results span');
2652 document.body.style.cursor = 'default';
2653 }
2654 });
2655 });
2656
2657 $('body').on('click.giveSelectUser', '.give_user_search_results span a', function (e) {
2658 e.preventDefault();
2659 var login = $(this).data('login');
2660 $('.give-ajax-user-search').val(login);
2661 $('.give_user_search_results').addClass('hidden');
2662 $('.give_user_search_results span').html('');
2663 });
2664
2665 $('body').on('click.giveCancelUserSearch', '.give_user_search_results a.give-ajax-user-cancel', function (e) {
2666 e.preventDefault();
2667 $('.give-ajax-user-search').val('');
2668 $('.give_user_search_results').addClass('hidden');
2669 $('.give_user_search_results span').html('');
2670 });
2671
2672 // This function uses for adding qtip to money/price field.
2673 function give_add_qtip($fields) {
2674
2675 // Add qtip to all existing money input fields.
2676 $fields.each(function () {
2677 $(this).qtip({
2678 style: 'qtip-dark qtip-tipsy',
2679 content: {
2680 text: give_vars.price_format_guide.trim()
2681 },
2682 show: '',
2683 position: {
2684 my: 'bottom center',
2685 at: 'top center'
2686 }
2687 });
2688 });
2689 }
2690
2691 var $poststuff = $( '#poststuff' ),
2692 thousand_separator = give_vars.thousands_separator,
2693 decimal_separator = give_vars.decimal_separator,
2694 thousand_separator_count = '',
2695 alphabet_count = '',
2696 price_string = '',
2697
2698 // Thousand separation limit in price depends upon decimal separator symbol.
2699 // If thousand separator is equal to decimal separator then price does not have more then 1 thousand separator otherwise limit is zero.
2700 thousand_separator_limit = ( decimal_separator === thousand_separator ? 1 : 0 );
2701
2702 // Check & show message on keyup event.
2703 $poststuff.on('keyup', 'input.give-money-field, input.give-price-field', function () {
2704 var tootltip_setting = {
2705 label: give_vars.price_format_guide.trim()
2706 };
2707
2708 // Count thousand separator in price string.
2709 thousand_separator_count = ( $(this).val().match(new RegExp(thousand_separator, 'g')) || [] ).length;
2710 alphabet_count = ( $(this).val().match(new RegExp('[a-z]', 'g')) || [] ).length;
2711
2712 // Show qtip conditionally if thousand separator detected on price string.
2713 if (( -1 !== $(this).val().indexOf(thousand_separator) ) && ( thousand_separator_limit < thousand_separator_count )) {
2714 $(this).giveHintCss('show', tootltip_setting);
2715 } else if (alphabet_count) {
2716 $(this).giveHintCss('show', tootltip_setting);
2717 } else {
2718 $(this).giveHintCss('hide', tootltip_setting);
2719 }
2720
2721 // Reset thousand separator count.
2722 thousand_separator_count = alphabet_count = '';
2723 });
2724
2725 // Format price sting of input field on focusout.
2726 $poststuff.on('focusout', 'input.give-money-field, input.give-price-field', function () {
2727 price_string = give_unformat_currency($(this).val(), false);
2728
2729 // Back out.
2730 if (give_unformat_currency('0', false) === give_unformat_currency($(this).val(), false)) {
2731 var default_amount = $(this).attr('placeholder');
2732 default_amount = !default_amount ? '0' : default_amount;
2733
2734 $(this).val(default_amount);
2735
2736 return false;
2737 }
2738
2739 // Replace dot decimal separator with user defined decimal separator.
2740 price_string = price_string.replace('.', decimal_separator);
2741
2742 // Check if current number is negative or not.
2743 if (-1 !== price_string.indexOf('-')) {
2744 price_string = price_string.replace('-', '');
2745 }
2746
2747 // Update format price string in input field.
2748 $(this).val(price_string);
2749 });
2750
2751 // Set default value to 1 even if user inputs empty or negative number of donations.
2752 $poststuff.on( 'focusout', '#_give_number_of_donation_goal', function() {
2753 if ( 1 > $( this ).val() ) {
2754 $( this ).val( 1 );
2755 }
2756 });
2757
2758 /**
2759 * Responsive setting tab features.
2760 */
2761
2762 // Show/Hide sub tab nav.
2763 $('.give-settings-page').on('click', '#give-show-sub-nav', function (e) {
2764 e.preventDefault();
2765
2766 var $sub_tab_nav = $(this).next();
2767
2768 if (!$sub_tab_nav.is(':hover')) {
2769 $sub_tab_nav.toggleClass('give-hidden');
2770 }
2771
2772 return false;
2773 }).on('blur', '#give-show-sub-nav', function () {
2774 var $sub_tab_nav = $(this).next();
2775
2776 if (!$sub_tab_nav.is(':hover')) {
2777 $sub_tab_nav.addClass('give-hidden');
2778 }
2779 });
2780
2781 /**
2782 * Automatically show/hide email setting fields.
2783 */
2784 $('.give_email_api_notification_status_setting input').change(function () {
2785 // Bailout.
2786 var value = $(this).val(),
2787 is_enabled = ( 'enabled' === value ),
2788 $setting_fields = {};
2789
2790 // Get setting fields.
2791 if ($(this).closest('.give_options_panel').length) {
2792 $setting_fields = $(this).closest('.give_options_panel').children('.give-field-wrap:not(.give_email_api_notification_status_setting), .give-repeatable-field-section' );
2793 } else if ($(this).closest('table').length) {
2794 $setting_fields = $(this).closest('table').find('tr:not(.give_email_api_notification_status_setting)');
2795 }
2796
2797 if (-1 === jQuery.inArray(value, ['enabled', 'disabled', 'global'])) {
2798 return false;
2799 }
2800
2801 // Bailout.
2802 if (!$setting_fields.length) {
2803 return false;
2804 }
2805
2806 // Show hide setting fields.
2807 is_enabled ? $setting_fields.show() : $setting_fields.hide();
2808 });
2809
2810 $('.give_email_api_notification_status_setting input:checked').change();
2811
2812 // Render setting tab.
2813 give_render_responsive_tabs();
2814 });
2815 })(jQuery);
2816
2817 /**
2818 * Responsive js.
2819 */
2820 jQuery(window).resize(function () {
2821 give_render_responsive_tabs();
2822 });
2823
2824 /**
2825 * Render responsive tabs
2826 */
2827 function give_render_responsive_tabs() {
2828 var $setting_page_form = jQuery( '.give-settings-page' ),
2829 $main_tab_nav = jQuery( 'h2.give-nav-tab-wrapper' ),
2830 setting_page_form_width = $setting_page_form.width(),
2831 $sub_tab_nav_wrapper = jQuery( '.give-sub-nav-tab-wrapper' ),
2832 $sub_tab_nav = jQuery( 'nav', $sub_tab_nav_wrapper ),
2833 $setting_tab_links = jQuery( 'div.give-nav-tab-wrapper > a:not(give-not-tab)' ),
2834 $show_tabs = [],
2835 $hide_tabs = [],
2836 tab_width = 0;
2837
2838 if ( 600 < jQuery( window ).outerWidth() ) {
2839 tab_width = 200;
2840 }
2841
2842 // Bailout.
2843 if ( ! $setting_page_form.length ) {
2844 return false;
2845 }
2846
2847 // Update tab wrapper css.
2848 $main_tab_nav.css({
2849 height: 'auto',
2850 overflow: 'visible'
2851 });
2852
2853 // Show all tab if anyone hidden to calculate correct tab width.
2854 $setting_tab_links.removeClass( 'give-hidden' );
2855
2856 var refactor_tabs = new Promise(
2857 function( resolve, reject ) {
2858
2859 // Collect tabs to show or hide.
2860 jQuery.each( $setting_tab_links, function( index, $tab_link ) {
2861 $tab_link = jQuery( $tab_link );
2862 tab_width = tab_width + parseInt( $tab_link.outerWidth() );
2863
2864 if ( tab_width < setting_page_form_width ) {
2865 $show_tabs.push( $tab_link );
2866 } else {
2867 $hide_tabs.push( $tab_link );
2868 }
2869 });
2870
2871 resolve( true );
2872 }
2873 );
2874
2875 refactor_tabs.then( function( is_refactor_tabs ) {
2876
2877 // 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.
2878 if ( $hide_tabs.length && ( -1 !== window.location.search.indexOf( '&tab=' ) ) ) {
2879 var $current_tab_nav = {},
2880 query_params = get_url_params();
2881
2882 $hide_tabs = $hide_tabs.filter( function( $tab_link ) {
2883 var is_current_nav_item = ( -1 !== parseInt( $tab_link.attr( 'href' ).indexOf( '&tab=' + query_params['tab'] ) ) );
2884
2885 if ( is_current_nav_item ) {
2886 $current_tab_nav = $tab_link;
2887 }
2888
2889 return ( ! is_current_nav_item );
2890 });
2891
2892 if ( $current_tab_nav.length ) {
2893 $hide_tabs.unshift( $show_tabs.pop() );
2894 $show_tabs.push( $current_tab_nav );
2895 }
2896 }
2897
2898 var show_tabs = new Promise( function( resolve, reject ) {
2899
2900 // Show main menu tabs.
2901 if ( $show_tabs.length ) {
2902 jQuery.each( $show_tabs, function( index, $tab_link ) {
2903 $tab_link = jQuery( $tab_link );
2904
2905 if ( $tab_link.hasClass( 'give-hidden' ) ) {
2906 $tab_link.removeClass( 'give-hidden' );
2907 }
2908 });
2909 }
2910
2911 resolve( true );
2912 });
2913
2914 show_tabs.then( function( is_show_tabs ) {
2915
2916 // Hide sub menu tabs.
2917 if ( $hide_tabs.length ) {
2918 $sub_tab_nav.html( '' );
2919
2920 jQuery.each( $hide_tabs, function( index, $tab_link ) {
2921 $tab_link = jQuery( $tab_link );
2922 if ( ! $tab_link.hasClass( 'nav-tab-active' ) ) {
2923 $tab_link.addClass( 'give-hidden' );
2924 }
2925 $tab_link.clone().removeClass().appendTo( $sub_tab_nav );
2926 });
2927
2928 if ( ! jQuery( '.give-sub-nav-tab-wrapper', $main_tab_nav ).length ) {
2929 $main_tab_nav.append( $sub_tab_nav_wrapper );
2930 }
2931
2932 $sub_tab_nav_wrapper.show();
2933 } else {
2934 $sub_tab_nav_wrapper.hide();
2935 }
2936 });
2937 });
2938 }
2939
2940 /**
2941 * Get url query params.
2942 *
2943 * @returns {Array}
2944 */
2945 function get_url_params() {
2946 var vars = [], hash;
2947 var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
2948 for (var i = 0; i < hashes.length; i++) {
2949 hash = hashes[i].split('=');
2950 vars[hash[0]] = hash[1];
2951 }
2952 return vars;
2953 }
2954
2955 /**
2956 * Run when user click on submit button.
2957 *
2958 * @since 1.8.17
2959 */
2960 function give_on_core_settings_import_start() {
2961 var $form = jQuery('form.tools-setting-page-import');
2962 var progress = $form.find('.give-progress');
2963
2964 give_setting_edit = true;
2965
2966 jQuery.ajax({
2967 type: 'POST',
2968 url: ajaxurl,
2969 data: {
2970 action: give_vars.core_settings_import,
2971 fields: $form.serialize()
2972 },
2973 dataType: 'json',
2974 success: function (response) {
2975 give_setting_edit = false;
2976 if (true === response.success) {
2977 jQuery(progress).find('div').width(response.percentage + '%');
2978 } else {
2979 alert(give_vars.error_message);
2980 }
2981 window.location = response.url;
2982 },
2983 error: function () {
2984 give_setting_edit = false;
2985 alert(give_vars.error_message);
2986 }
2987 });
2988 }
2989
2990 /**
2991 * Run when user click on upload CSV.
2992 *
2993 * @since 1.8.13
2994 */
2995 function give_on_donation_import_start() {
2996 give_on_donation_import_ajax();
2997 }
2998
2999 /**
3000 * Upload CSV ajax
3001 *
3002 * @since 1.8.13
3003 */
3004 function give_on_donation_import_ajax() {
3005 var $form = jQuery('form.tools-setting-page-import');
3006
3007 /**
3008 * Do not allow user to reload the page
3009 *
3010 * @since 1.8.14
3011 */
3012 give_setting_edit = true;
3013
3014 var progress = $form.find('.give-progress');
3015
3016 var total_ajax = jQuery(progress).data('total_ajax'),
3017 current = jQuery(progress).data('current'),
3018 start = jQuery(progress).data('start'),
3019 end = jQuery(progress).data('end'),
3020 next = jQuery(progress).data('next'),
3021 total = jQuery(progress).data('total'),
3022 per_page = jQuery(progress).data('per_page');
3023
3024 jQuery.ajax({
3025 type: 'POST',
3026 url: ajaxurl,
3027 data: {
3028 action: give_vars.give_donation_import,
3029 total_ajax: total_ajax,
3030 current: current,
3031 start: start,
3032 end: end,
3033 next: next,
3034 total: total,
3035 per_page: per_page,
3036 fields: $form.serialize()
3037 },
3038 dataType: 'json',
3039 success: function (response) {
3040 jQuery(progress).data('current', response.current);
3041 jQuery(progress).find('div').width(response.percentage + '%');
3042
3043 if (response.next == true) {
3044 jQuery(progress).data('start', response.start);
3045 jQuery(progress).data('end', response.end);
3046
3047 if (response.last == true) {
3048 jQuery(progress).data('next', false);
3049 }
3050 give_on_donation_import_ajax();
3051 } else {
3052 /**
3053 * Now user is allow to reload the page.
3054 *
3055 * @since 1.8.14
3056 */
3057 give_setting_edit = false;
3058 window.location = response.url;
3059 }
3060 },
3061 error: function () {
3062 /**
3063 * Now user is allow to reload the page.
3064 *
3065 * @since 1.8.14
3066 */
3067 give_setting_edit = false;
3068 alert(give_vars.error_message);
3069 }
3070 });
3071 }