PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.6
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.6
8.0.6 8.0.5 8.0.4 8.0.3 8.0.1 8.0.2 8.0.0 7.9.9.7 7.9.9.6 7.9.9.5 7.9.9.4 7.9.9.3 7.9.9.2 7.9.9.1 7.9.9 7.9.8 7.9.7 7.9.6 7.9.5 7.9.4 7.9.3 7.9.2 7.9.1 7.9.0 7.8.9 All 48 releases
gamipress / assets / js / gamipress-requirements-ui.js

gamipress-requirements-ui.js in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 8.0.6, at assets/js/gamipress-requirements-ui.js

817 lines 32.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 var gamipress_requirements_unsaved_changes = false;
2
3
4 (function($) {
5
6 // Hide requirements meta box if unnecessary
7 $('body').on('change', '#_gamipress_earned_by', function() {
8 if ( 'triggers' == $(this).val() )
9 $('#gamipress-requirements-ui').show();
10 else
11 $('#gamipress-requirements-ui').hide();
12 }).trigger('change');
13
14 // Make requirements list sortable
15 $('.requirements-list').sortable({
16 cancel: 'input, select, textarea, .gamipress-no-grab',
17 // When the list order is updated
18 update : function ( e, ui ) {
19
20 // Loop through each element
21 $(e.target).find('li').each(function( index, value ) {
22
23 // Write it's current position to our hidden input value
24 $(this).find('input[name="order"]').val( index );
25
26 });
27
28 // Trigger change on sequential input to update the requirements order display
29 $("#_gamipress_sequential").trigger('change');
30
31 }
32 });
33
34 // Click add requirement
35 $('body').on('click', '.gamipress-add-requirement', function(e) {
36 gamipress_add_requirement( e.target, $(e.target).data('post-id'), $(e.target).data('requirement-type') );
37 });
38
39 // Click save requirements
40 $('body').on('click', '.gamipress-save-requirements', function(e) {
41 gamipress_update_requirements( e.target );
42 });
43
44 // On change sequential requirements, add order display on all requirements
45 $('body').on('change', '#_gamipress_sequential', function() {
46
47 $('.requirements-list .requirement-header-title .requirement-order').remove();
48
49 if( $(this).prop('checked') ) {
50 var index = 1;
51
52 $('.requirements-list .requirement-published .requirement-header-title').each(function() {
53 $(this).prepend('<span class="requirement-order">' + index + ' -</span>');
54
55 index++;
56 });
57 }
58
59 });
60
61 // Change status action
62 $('.requirements-list').on( 'change', '.requirement-action.requirement-action-change-status input', function() {
63
64 var $this = $(this);
65 var requirement = $this.closest('.requirement-row');
66
67 // Enable/Disable all inputs
68 requirement.find('input:not([id="' + $this.attr('id') + '"]), select, textarea').prop( 'disabled', ! $this.prop('checked') );
69
70 if( $this.prop('checked') ) {
71 // Remove a custom class to the requirement
72 requirement.removeClass('requirement-disabled');
73 requirement.addClass('requirement-published');
74
75 // Change action title
76 $this.attr('title', $this.data('enabled-title'));
77 } else {
78 // Add a custom class to the requirement
79 requirement.addClass('requirement-disabled');
80 requirement.removeClass('requirement-published');
81
82 // Change action title
83 $this.attr('title', $this.data('disabled-title'));
84 }
85
86 // Trigger change event on sequential input to update the order again
87 $("#_gamipress_sequential").trigger('change');
88 });
89
90 // Duplicate action
91 $('.requirements-list').on( 'click', '.requirement-action.requirement-action-duplicate', function(e) {
92 e.preventDefault();
93
94 // Bail if already clicked
95 if( $(this).hasClass('requirement-action-active') )
96 return;
97
98 // Add a custom class to meet that has been clicked
99 $(this).addClass('requirement-action-active');
100
101 gamipress_duplicate_requirement( this, $(this).closest('.requirement-row').attr('data-requirement-id') );
102 });
103
104 // Delete action
105 $('.requirements-list').on( 'click', '.requirement-action.requirement-action-delete', function(e) {
106 e.preventDefault();
107
108 gamipress_delete_requirement( this, $(this).closest('.requirement-row').attr('data-requirement-id') );
109 });
110
111 // On change requirement title, also update requirement header title
112 $('.requirements-list').on( 'change keyup', '.requirement-title input', function() {
113 $(this).closest('.requirement-row').find('.requirement-header-title strong').html(gamipress_strip_scripts($(this).val()));
114 });
115
116 // Listen for our change to our trigger type selectors
117 $('.requirements-list').on( 'change', '.select-trigger-type', function() {
118
119 // Initialize select 2 on select trigger type
120 if( ! $(this).hasClass('select2-hidden-accessible') ) {
121 $(this).gamipress_select2({
122 theme: 'default gamipress-select2 gamipress-trigger-type-selector',
123 matcher: gamipress_select2_optgroup_matcher,
124 });
125 }
126
127 // Grab our selected trigger type and achievement selector
128 var trigger_type = $(this).val();
129
130 // Common selectors for points and rank trigger types
131 var count = $(this).siblings('.count');
132 var count_text = $(this).siblings('.count-text');
133 var limit_text = $(this).siblings('.limit-text');
134 var limit = $(this).siblings('.limit');
135 var limit_type = $(this).siblings('.limit-type');
136
137 if ( gamipress_requirements_ui.triggers_excluded_from_limit.indexOf( trigger_type ) !== -1 ) {
138 // Hide limit fields
139 count.hide();
140 count_text.hide();
141 limit_text.hide();
142 limit.hide();
143 limit_type.hide();
144 } else {
145 // Show limit fields
146 count.show();
147 count_text.show();
148 limit_text.show();
149
150 if( limit_type.val() !== 'unlimited' ) {
151 limit.show();
152 } else {
153 limit.hide();
154 }
155
156 limit_type.show();
157 }
158
159 // Points condition
160 var points_condition_selector = $(this).siblings('.select-points-condition');
161
162 if ( trigger_type === 'points-balance' ) {
163 // Show points condition field
164 points_condition_selector.show();
165 } else {
166 // Hide points condition field
167 points_condition_selector.hide();
168 }
169
170 // Metas condition
171 var meta_key_selector = $(this).siblings('.meta-key-required');
172
173 if( trigger_type === 'gamipress_update_post_meta_any_value'
174 || trigger_type === 'gamipress_update_user_meta_any_value'
175 || trigger_type === 'gamipress_update_post_meta_specific_value'
176 || trigger_type === 'gamipress_update_user_meta_specific_value' ) {
177 // Show meta key field
178 meta_key_selector.show();
179 } else {
180 // Hide meta key field
181 meta_key_selector.hide();
182 }
183
184 var meta_value_selector = $(this).siblings('.meta-value-required');
185
186 if( trigger_type === 'gamipress_update_post_meta_specific_value'
187 || trigger_type === 'gamipress_update_user_meta_specific_value' ) {
188 // Show meta value field
189 meta_value_selector.show();
190 } else {
191 // Hide meta value field
192 meta_value_selector.hide();
193 }
194
195 // Required points
196 var points_selector_required = $(this).siblings('.points-required');
197 var points_type_selector_required = $(this).siblings('.select-points-type-required');
198
199 if ( gamipress_requirements_ui.points_triggers.indexOf( trigger_type ) !== -1 ) {
200 // Show required points fields
201 points_selector_required.show();
202 points_type_selector_required.show();
203 } else {
204 // Hide required points fields
205 points_selector_required.hide();
206 points_type_selector_required.hide();
207 }
208
209 // Required rank
210 var rank_type_selector_required = $(this).siblings('.select-rank-type-required');
211 var rank_selector_required = $(this).siblings('.select-rank-required');
212
213 if ( gamipress_requirements_ui.rank_type_triggers.indexOf( trigger_type ) !== -1 ) {
214 // Show required rank fields
215 rank_type_selector_required.show();
216
217 // Trigger a change to the rank type selector to determine if it should show
218 rank_type_selector_required.trigger('change');
219 } else {
220 // Hide required rank fields
221 rank_type_selector_required.hide();
222 rank_selector_required.hide();
223 }
224
225 // Achievement type
226 var achievement_type_selector = $(this).siblings('.select-achievement-type');
227 var achievement_post_selector = $(this).siblings('.select-achievement-post');
228
229 // If we're working with achievements, show the achievement type selector (otherwise, hide it)
230 if ( gamipress_requirements_ui.achievement_type_triggers.indexOf( trigger_type ) !== -1 ) {
231 achievement_type_selector.show();
232
233 // Trigger a change to the achievement type selector to determine if it should show
234 achievement_type_selector.trigger('change');
235 } else {
236 // Hide achievement type and post selector
237 achievement_type_selector.hide();
238 achievement_post_selector.hide();
239 }
240
241 // Post type
242 var post_type_selector_required = $(this).siblings('.select-post-type-required');
243
244 if ( gamipress_requirements_ui.post_type_triggers.indexOf( trigger_type ) !== -1 ) {
245 post_type_selector_required.show();
246 } else {
247 post_type_selector_required.hide();
248 }
249
250 // User role
251 var user_role_selector_required = $(this).siblings('.select-user-role-required');
252
253 if ( gamipress_requirements_ui.user_role_triggers.indexOf( trigger_type ) !== -1 ) {
254 user_role_selector_required.show();
255 } else {
256 user_role_selector_required.hide();
257 }
258
259 var post_selector = $(this).siblings('.select-post');
260
261 // Lets to check if there is a specific activity trigger
262 if ( gamipress_requirements_ui.specific_activity_triggers[trigger_type] !== undefined ) {
263 // Show select post
264 post_selector
265 .show()
266 .data( 'trigger-type', trigger_type )
267 .data( 'post-type', gamipress_requirements_ui.specific_activity_triggers[trigger_type].join(',') )
268 ;
269
270 // Check if post selector Select2 has been initialized
271 if( post_selector.hasClass('select2-hidden-accessible') ) {
272 post_selector
273 .val('').trigger('change') // Reset value
274 .next().show(); // Show Select2 container
275 } else {
276 post_selector.gamipress_select2({
277 ajax: {
278 url: ajaxurl,
279 dataType: 'json',
280 delay: 250,
281 type: 'POST',
282 data: function( params ) {
283 return {
284 q: params.term,
285 page: params.page || 1,
286 action: 'gamipress_get_posts',
287 nonce: gamipress_requirements_ui.nonce,
288 post_type: $(this).data('post-type').split(','),
289 trigger_type: $(this).data('trigger-type'),
290 };
291 },
292 processResults: gamipress_select2_posts_process_results
293 },
294 escapeMarkup: function ( markup ) { return markup; }, // Let our custom formatter work
295 templateResult: gamipress_select2_posts_template_result,
296 theme: 'default gamipress-select2',
297 placeholder: gamipress_requirements_ui.post_placeholder,
298 allowClear: true,
299 multiple: false
300 });
301
302 post_selector.on('select2:select', function (e) {
303 var item = e.params.data;
304
305 // If site ID is defined, then update the hidden field
306 if( item.site_id !== undefined ) {
307 $(this).siblings('.select-post-site-id').val( item.site_id );
308 }
309 });
310 }
311 } else {
312 // Hide select post
313 post_selector.hide();
314
315 if( post_selector.hasClass('select2-hidden-accessible') ) {
316 post_selector.next().hide(); // Hide select2 container
317 }
318 }
319
320 });
321
322 // Listen for a change to our achievement type selectors
323 $('.requirements-list').on( 'change', '.select-achievement-type', function() {
324
325 // Setup our necessary variables
326 var $this = $(this);
327 var achievement_post = $this.siblings('.select-achievement-post');
328 var achievement_type = $this.val();
329 var requirement_id = $this.parent('li').attr('data-requirement-id');
330 var requirement_type = $this.siblings('input[name="requirement_type"]').val();
331 var excluded_posts = [$this.siblings('input[name="post_id"]').val()];
332 var trigger_type = $this.siblings('.select-trigger-type').val();
333 var events = [ 'specific-achievement', 'revoke-specific-achievement' ];
334
335 // If we've selected a *specific* achievement type, show our post selector and populate it w/ the corresponding achievement posts
336 if ( '' !== achievement_type && events.indexOf( trigger_type ) !== -1 ) {
337 // Add the loader
338 $('<span class="achievement-type-spinner spinner is-active" style="float: none; margin: 0 2px 0 4px;"></span>').insertAfter($this);
339
340 achievement_post.hide();
341
342 $.post(
343 ajaxurl,
344 {
345 action: 'gamipress_get_achievements_options_html',
346 nonce: gamipress_requirements_ui.nonce,
347 requirement_id: requirement_id,
348 requirement_type: requirement_type,
349 achievement_type: achievement_type,
350 excluded_posts: excluded_posts
351 },
352 function( response ) {
353
354 // Remove the loader
355 $this.next('.achievement-type-spinner').remove();
356
357 // Add the new options and show the input again
358 achievement_post.html( response );
359 achievement_post.show();
360 }
361 );
362 } else {
363 achievement_post.hide();
364 }
365 });
366
367 // Listen for a change to our rank type selectors
368 $('.requirements-list').on( 'change', '.select-rank-type-required', function() {
369
370 // Setup our necessary variables
371 var $this = $(this);
372 var rank_selector = $this.siblings('.select-rank-required');
373 var rank_type = $this.val();
374 var requirement_id = $this.parent('li').attr('data-requirement-id');
375 var trigger_type = $this.siblings('.select-trigger-type').val();
376 var events = [ 'earn-rank', 'revoke-rank' ];
377
378 // If we've selected a *specific* achievement type, show our post selector and populate it w/ the corresponding achievement posts
379 if ( '' !== rank_type && events.indexOf( trigger_type ) !== -1 ) {
380
381 // Add the loader
382 $('<span class="rank-type-spinner spinner is-active" style="float: none; margin: 0 2px 0 4px;"></span>').insertAfter( $this );
383
384 rank_selector.hide();
385
386 $.post(
387 ajaxurl,
388 {
389 action: 'gamipress_get_ranks_options_html',
390 nonce: gamipress_requirements_ui.nonce,
391 requirement_id: requirement_id,
392 post_type: rank_type
393 },
394 function( response ) {
395
396 // Remove the loader
397 $this.next('.rank-type-spinner').remove();
398
399 // Add the new options and show the input again
400 rank_selector.html( response );
401 rank_selector.show();
402 }
403 );
404 } else {
405 rank_selector.hide();
406 }
407 });
408
409 // Limit inputs
410 $('.requirements-list').on( 'change', '.limit-type', function() {
411 var $this = $(this);
412
413 if( $this.val() === 'unlimited' ) {
414 $this.siblings('.limit').hide();
415 } else {
416 $this.siblings('.limit').show();
417 }
418 });
419
420 // Listen for a change to optional select
421 $('.requirements-list').on( 'change', '.select-optional', function() {
422 var $this = $(this);
423
424 if( $this.val() === '1' ) {
425 $this.addClass('optional-selected');
426 $this.removeClass('required-selected');
427 } else {
428 $this.removeClass('optional-selected');
429 $this.addClass('required-selected');
430 }
431 });
432
433 // Trigger a change for our trigger type post selector to determine if it should show
434 $( '.select-trigger-type' ).trigger('change');
435
436 // Trigger a change for our sequential field
437 $( '#_gamipress_sequential' ).trigger('change');
438
439 // Trigger a change for our limit type to determine if limit should show
440 $( '.limit-type' ).trigger('change');
441
442 // Trigger a change for our optional select to update its class
443 $( '.select-optional' ).trigger('change');
444
445 // Trigger a change for our change status input
446 $( '.requirement-action-change-status input' ).trigger('change');
447
448 // Add a custom data with current fields values to check their changes
449 $('.requirements-list input, .requirements-list select, .requirements-list textarea').each( function() {
450 $(this).data('unsaved-value', $(this).val());
451 });
452
453 // Check if any field has changed their values
454 $('.requirements-list').on( 'change', 'input, select, textarea', function() {
455
456 var row = $(this).closest('.requirement-row');
457 var has_unsaved_changes = false;
458
459 // Check if any field has change his value
460 row.find('input, select, textarea').each( function() {
461 if( $(this).val() !== $(this).data('unsaved-value') ) {
462 has_unsaved_changes = true;
463 }
464 });
465
466 // If not has unsaved changes, remove warning and return
467 if( ! has_unsaved_changes ) {
468 row.find('.requirement-header-title .requirement-unsaved-changes').remove();
469 return;
470 }
471
472 // If has unsaved changes and not the waring, add it
473 if( has_unsaved_changes && ! row.find('.requirement-header-title .requirement-unsaved-changes').length ) {
474 row.find('.requirement-header-title').append('<span class="requirement-unsaved-changes dashicons dashicons-warning" title="' + gamipress_requirements_ui.unsaved_changes_text + '"></span>');
475 gamipress_requirements_unsaved_changes = true;
476 }
477
478 // Trigger change on sequential input to update the requirements order display
479 $("#_gamipress_sequential").trigger('change');
480
481 });
482
483 // Check on save post (block editor)
484 // Note: On block editor, the button is added through JS, so we need to wait some time to get it inside
485 setTimeout(function() {
486 $('button.editor-post-publish-button').on( 'click', function() {
487 if( gamipress_requirements_unsaved_changes ) {
488 $('.gamipress-save-requirements').trigger('click');
489 }
490 } );
491 }, 2000 );
492
493
494 // Check on save post
495 $('form#post').on( 'submit', function() {
496 if( gamipress_requirements_unsaved_changes ) {
497 $('.gamipress-save-requirements').trigger('click');
498 }
499 } );
500 })(jQuery);
501
502 /**
503 * Add a requirement
504 *
505 * @since 1.0.0
506 *
507 * @param element
508 * @param post_id
509 * @param requirement_type
510 */
511 function gamipress_add_requirement( element, post_id, requirement_type ) {
512
513 var $ = jQuery;
514
515 var requirements_list = $(element).siblings('.requirements-list');
516 $(element).siblings( '.requirements-spinner' ).addClass('is-active');
517
518 $.post(
519 ajaxurl,
520 {
521 action: 'gamipress_add_requirement',
522 nonce: gamipress_requirements_ui.nonce,
523 post_id: post_id,
524 requirement_type: requirement_type
525 },
526 function( response ) {
527 $( response ).appendTo( requirements_list );
528
529 // Hide the new requirement
530 requirements_list.find( 'li.requirement-row:last').attr('style', 'display: none;');
531
532 // Dynamically add the menu order for the new points award to be one higher than the last in line
533 var new_requirement_menu_order = Number( requirements_list.find( 'li.requirement-row' ).eq( -2 ).find( 'input[name="order"]' ).val() ) + 1;
534 requirements_list.find( 'li.requirement-row:last' ).find( 'input[name="order"]' ).val( new_requirement_menu_order );
535
536 // Trigger a change for the new trigger type and limit type elements
537 requirements_list.find( 'li.requirement-row:last' ).find( '.select-trigger-type' ).trigger('change');
538 requirements_list.find( 'li.requirement-row:last' ).find( '.limit-type' ).trigger('change');
539
540 // Hide the spinner
541 requirements_list.siblings( '.requirements-spinner' ).removeClass('is-active');
542
543 // Slide Down the new requirement
544 requirements_list.find( 'li.requirement-row:last').slideDown('fast');
545
546 // Add a custom data with current fields values to check their changes
547 requirements_list.find( 'li.requirement-row:last').find('input, select, textarea').each( function() {
548 $(this).data('unsaved-value', $(this).val());
549 });
550
551 // Trigger change event on sequential input to update the order again
552 $("#_gamipress_sequential").trigger('change');
553 }
554 );
555 }
556
557 /**
558 * Duplicate a requirement
559 *
560 * @since 1.4.6
561 *
562 * @param element
563 * @param requirement_id
564 */
565 function gamipress_duplicate_requirement( element, requirement_id ) {
566
567 var $ = jQuery;
568
569 var requirements_list = $(element).closest('.requirements-list');
570 requirements_list.siblings( '.requirements-spinner' ).addClass('is-active');
571
572 $.post(
573 ajaxurl,
574 {
575 action: 'gamipress_duplicate_requirement',
576 nonce: gamipress_requirements_ui.nonce,
577 post_id: $('input#post_ID').val(),
578 requirement_id: requirement_id
579 },
580 function( response ) {
581 $( response ).appendTo( requirements_list );
582
583 // Hide the new requirement
584 requirements_list.find( 'li.requirement-row:last').attr('style', 'display: none;');
585
586 // Dynamically add the menu order for the new points award to be one higher than the last in line
587 var new_requirement_menu_order = Number( requirements_list.find( 'li.requirement-row' ).eq( -2 ).find( 'input[name="order"]' ).val() ) + 1;
588 requirements_list.find( 'li.requirement-row:last' ).find( 'input[name="order"]' ).val( new_requirement_menu_order );
589
590 // Trigger a change for the new trigger type and limit type elements
591 requirements_list.find( 'li.requirement-row:last' ).find( '.select-trigger-type' ).trigger('change');
592 requirements_list.find( 'li.requirement-row:last' ).find( '.limit-type' ).trigger('change');
593
594 // Hide the spinner
595 requirements_list.siblings( '.requirements-spinner' ).removeClass('is-active');
596
597 // Slide Down the new requirement
598 requirements_list.find( 'li.requirement-row:last').slideDown('fast');
599
600 // Add a custom data with current fields values to check their changes
601 requirements_list.find( 'li.requirement-row:last').find('input, select, textarea').each( function() {
602 $(this).data('unsaved-value', $(this).val());
603 });
604
605 // Trigger change event on sequential input to update the order again
606 $("#_gamipress_sequential").trigger('change');
607
608 // If current element has a custom class for requirement actions, remove it
609 if( $(element).hasClass('requirement-action-active') )
610 $(element).removeClass('requirement-action-active');
611 }
612 );
613
614 }
615
616 /**
617 * Delete a requirement
618 *
619 * @since 1.0.0
620 *
621 * @param element
622 * @param requirement_id
623 */
624 function gamipress_delete_requirement( element, requirement_id ) {
625
626 var $ = jQuery;
627
628 var requirements_list = $(element).closest('.requirements-list');
629 requirements_list.find( '.requirement-' + requirement_id ).slideUp( 'fast' );
630
631 // Remove requirement published class to update requirements order
632 requirements_list.find( '.requirement-' + requirement_id).removeClass('requirement-published')
633
634 // Trigger change event on sequential input to update the order again
635 $("#_gamipress_sequential").trigger('change');
636
637 $.post(
638 ajaxurl,
639 {
640 action: 'gamipress_delete_requirement',
641 nonce: gamipress_requirements_ui.nonce,
642 requirement_id: requirement_id
643 },
644 function( response ) {
645 requirements_list.find( '.requirement-' + requirement_id ).remove();
646 }
647 );
648 }
649
650 /**
651 * Update all requirements
652 *
653 * @since 1.0.0
654 * @updated 1.4.7.2 Added loop parameter
655 *
656 * @param element
657 * @param loop
658 */
659 function gamipress_update_requirements( element, loop ) {
660
661 if( loop === undefined ) {
662 loop = 0;
663 }
664
665 var $ = jQuery;
666
667 var requirements_list = $(element).siblings('.requirements-list');
668 requirements_list.siblings( '.requirements-spinner' ).addClass('is-active');
669
670 // On large requirements list, we need to store them in groups
671 var requirements = requirements_list.find( '.requirement-row' );
672
673 // So let's to define an offset and limit
674 var requirements_limit = 20;
675 var current_offset = ( loop * requirements_limit );
676 var current_limit = ( ( loop + 1 ) * requirements_limit );
677
678 // Setup the data to be send
679 var requirement_data = {
680 action: 'gamipress_update_requirements',
681 nonce: gamipress_requirements_ui.nonce,
682 post_id: $('input#post_ID').val(),
683 loop: loop,
684 _gamipress_sequential: ( $('input#_gamipress_sequential').prop('checked') ? 'on' : '' ),
685 requirements: []
686 };
687
688 // To set smaller groups of requirements to being stored
689 var current_requirements = requirements.slice( current_offset, current_limit );
690
691 // Loop through current requirements and collect its data
692 current_requirements.each( function() {
693
694 // Cache our points award object
695 var requirement = $(this);
696 var trigger_type = requirement.find( '.select-trigger-type' ).val();
697
698 // Setup our points award object
699 var requirement_details = {
700 requirement_id : requirement.find( 'input[name="requirement_id"]').val(),
701 requirement_type : requirement.find( 'input[name="requirement_type"]').val(),
702 order : requirement.find( 'input[name="order"]' ).val(),
703 status : ( requirement.find( '.requirement-action-change-status input' ).prop('checked') ? 'publish' : 'pending' ),
704 points_condition : requirement.find( '.select-points-condition' ).val(),
705 points_required : requirement.find( '.points-required' ).val(),
706 points_type_required : requirement.find( '.select-points-type-required' ).val(),
707 rank_type_required : requirement.find( '.select-rank-type-required' ).val(),
708 rank_required : requirement.find( '.select-rank-required' ).val(),
709 post_type_required : requirement.find( '.select-post-type-required' ).val(),
710 user_role_required : requirement.find( '.select-user-role-required' ).val(),
711 count : requirement.find( '.count' ).val(),
712 limit : requirement.find( '.limit' ).val(),
713 limit_type : requirement.find( '.limit-type' ).val(),
714 trigger_type : trigger_type,
715 achievement_type : requirement.find( '.select-achievement-type' ).val(),
716 achievement_post : ( gamipress_requirements_ui.specific_activity_triggers[trigger_type] !== undefined ? requirement.find( '.select-post' ).val() : requirement.find( 'select.select-achievement-post' ).val() ),
717 achievement_post_site_id : ( gamipress_requirements_ui.specific_activity_triggers[trigger_type] !== undefined ? requirement.find( '.select-post-site-id' ).val() : '' ),
718 optional : requirement.find( '.requirement-optional select' ).val(),
719 title : requirement.find( '.requirement-title .title' ).val(),
720 url : requirement.find( '.requirement-url .url' ).val()
721 };
722
723 if( requirement_details.requirement_type === 'points-award' || requirement_details.requirement_type === 'points-deduct' ) {
724 requirement_details.points = requirement.find( '.points' ).val();
725 requirement_details.points_type = requirement.find( 'input[name="points_type"]' ).val();
726 requirement_details.maximum_earnings = requirement.find( '.maximum-earnings' ).val();
727 }
728
729 if( requirement_details.trigger_type === 'gamipress_update_user_meta_any_value'
730 || requirement_details.trigger_type === 'gamipress_update_post_meta_any_value' ) {
731
732 requirement_details.meta_key_required = requirement.find( '.meta-key-required' ).val();
733
734 }
735
736 if( requirement_details.trigger_type === 'gamipress_update_user_meta_specific_value'
737 || requirement_details.trigger_type === 'gamipress_update_post_meta_specific_value' ) {
738
739 requirement_details.meta_key_required = requirement.find( '.meta-key-required' ).val();
740 requirement_details.meta_value_required = requirement.find( '.meta-value-required' ).val();
741
742 }
743
744 /**
745 * Allow external functions to add their own data to the array
746 *
747 * @deprecated use gamipress_update_requirement_data event instead
748 *
749 * @since 1.0.0
750 *
751 * @selector .requirements-list .requirement
752 * @event update_requirement_data
753 */
754 requirement.trigger( 'update_requirement_data', [ requirement_details, requirement ] );
755
756 /**
757 * Allow external functions to add their own data to the array
758 *
759 * @since 1.5.9
760 *
761 * @selector .requirements-list .requirement
762 * @event gamipress_update_requirement_data
763 *
764 * @param Object requirement_details
765 * @param Node requirement
766 */
767 requirement.trigger( 'gamipress_update_requirement_data', [ requirement_details, requirement ] );
768
769 // Add our relevant data to the array
770 requirement_data.requirements.push( requirement_details );
771 });
772
773 $.post(
774 ajaxurl,
775 requirement_data,
776 function( response ) {
777 // Parse response
778 var titles = JSON.parse( response );
779
780 // Loop all given titles
781 $.each( titles, function( id, value ) {
782
783 var requirement = requirements_list.find('.requirement-' + id );
784
785 // Update the title
786 requirement.find('.requirement-header-title strong').html(value);
787 requirement.find('.requirement-title .title').val(value);
788
789 // Update unsaved values to meet that current ones has been saved
790 requirement.find('input, select, textarea').each( function() {
791 $(this).data('unsaved-value', $(this).val());
792 });
793
794 // Remove unsaved data warning
795 requirement.find('.requirement-unsaved-changes').remove();
796 });
797
798 if( current_limit < requirements.length ) {
799
800 // Continue looping each group of requirements to save them
801 loop++;
802
803 gamipress_update_requirements( element, loop );
804
805 } else {
806
807 // All requirements saved successfully Hide the spinner
808 $(element).siblings( '.requirements-spinner' ).removeClass('is-active');
809
810 }
811
812 gamipress_requirements_unsaved_changes = false;
813
814 }
815 );
816 }
817