PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 7.9.6
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v7.9.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 7.8.8 All 47 releases
gamipress / assets / js / gamipress-admin-functions.js

gamipress-admin-functions.js in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 7.9.6, at assets/js/gamipress-admin-functions.js

609 lines 15.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Helper function to initialize select2 on fields
3 *
4 * @since 1.6.6
5 *
6 * @param {Object} $this
7 */
8 function gamipress_selector( $this ) {
9
10 // Prevent load select2 on widgets lists
11 if( $this.closest('#available-widgets').length )
12 return;
13
14 var select2_args = {
15 theme: 'default gamipress-select2',
16 placeholder: ( $this.data('placeholder') ? $this.data('placeholder') : gamipress_admin_functions.selector_placeholder ),
17 allowClear: true,
18 multiple: ( $this[0].hasAttribute('multiple') )
19 };
20
21 $this.gamipress_select2( select2_args );
22
23 }
24
25 /**
26 * Helper function to initialize select2 post selector on fields
27 *
28 * @since 1.6.6
29 *
30 * @param {Object} $this
31 */
32 function gamipress_post_selector( $this ) {
33
34 // Prevent load select2 on widgets lists
35 if( $this.closest('#available-widgets').length )
36 return;
37
38 var select2_args = {
39 ajax: {
40 url: ajaxurl,
41 dataType: 'json',
42 delay: 250,
43 type: 'POST',
44 data: function( params ) {
45 return {
46 q: params.term,
47 page: params.page || 1,
48 action: ( $this.data('action') ? $this.data('action') : 'gamipress_get_posts' ),
49 nonce: gamipress_admin_functions.nonce,
50 post_type: $this.data('post-type').split(','),
51 };
52 },
53 processResults: gamipress_select2_posts_process_results
54 },
55 escapeMarkup: function ( markup ) { return markup; },
56 templateResult: gamipress_select2_posts_template_result,
57 theme: 'default gamipress-select2',
58 placeholder: ( $this.data('placeholder') ? $this.data('placeholder') : gamipress_admin_functions.post_selector_placeholder ),
59 allowClear: true,
60 multiple: ( $this[0].hasAttribute('multiple') )
61 };
62
63 $this.gamipress_select2( select2_args );
64
65 }
66
67 /**
68 * Helper function to initialize select2 user selector on fields
69 *
70 * @since 1.6.6
71 *
72 * @param {Object} $this
73 */
74 function gamipress_user_selector( $this ) {
75
76 // Prevent load select2 on widgets lists
77 if( $this.closest('#available-widgets').length )
78 return;
79
80 var select2_args = {
81 ajax: {
82 url: ajaxurl,
83 dataType: 'json',
84 delay: 250,
85 type: 'POST',
86 data: function( params ) {
87 return {
88 q: params.term,
89 page: params.page || 1,
90 action: 'gamipress_get_users',
91 nonce: gamipress_admin_functions.nonce,
92 };
93 },
94 processResults: gamipress_select2_users_process_results
95 },
96 escapeMarkup: function ( markup ) { return markup; },
97 templateResult: gamipress_select2_users_template_result,
98 theme: 'default gamipress-select2',
99 placeholder: ( $this.data('placeholder') ? $this.data('placeholder') : gamipress_admin_functions.user_selector_placeholder ),
100 allowClear: true,
101 multiple: ( $this[0].hasAttribute('multiple') )
102 };
103
104 $this.gamipress_select2( select2_args );
105
106 }
107
108 /**
109 * Helper function to destroy a select2 element when the method destroy does not works
110 *
111 * @since 1.6.6
112 *
113 * @param {Object} $this
114 */
115 function gamipress_select2_destroy( $this, clear_options = false ) {
116 $this.removeAttr('data-select2-id');
117 $this.removeData('data-hash');
118 $this.next('.select2').remove();
119
120 if( clear_options ) {
121 $this.find('option').remove();
122 }
123 }
124
125 /**
126 * Custom formatting for posts on select2
127 *
128 * @since 1.4.1
129 *
130 * @param {Object} item
131 *
132 * @return {string}
133 */
134 function gamipress_select2_posts_template_result( item ) {
135
136 if( item.post_parent_title !== undefined ) {
137 return gamipress_select2_post_parent_template_result( item );
138 }
139
140 if( item.post_type !== undefined ) {
141
142 var post_type_label = item.post_type;
143
144 if( gamipress_post_type_exists( item.post_type ) ) {
145 post_type_label = gamipress_get_post_type_label( item.post_type );
146 }
147
148 return '<strong>' + item.post_title + '</strong>'
149 + '<span class="result-description">'
150 + 'ID: ' + item.ID + '<span class="align-right">' + post_type_label + '</span>'
151 + ( item.site_name !== undefined ? ' (' + item.site_name + ')' : '' )
152 + '</span>';
153 }
154
155 return item.text;
156
157 }
158
159 /**
160 * Custom formatting for post with parent information on select2
161 *
162 * @since 1.4.1
163 *
164 * @param {Object} item
165 *
166 * @return {string}
167 */
168 function gamipress_select2_post_parent_template_result( item ) {
169
170 if( item.post_parent_type !== undefined ) {
171
172 var post_type_label = item.post_parent_type;
173
174 if( item.post_parent_type === 'points-type' ) {
175 post_type_label = '';
176 } else if( gamipress_post_type_exists( item.post_parent_type ) ) {
177 post_type_label = gamipress_get_post_type_label( item.post_parent_type );
178
179 post_type_label += ':';
180 }
181
182
183
184 return '<strong>' + item.post_title + '</strong>'
185 + '<span class="result-description">'
186 + 'ID: ' + item.ID + '<span class="align-right">' + post_type_label + ' ' + item.post_parent_title + '</span>'
187 + ( item.site_name !== undefined ? ' (' + item.site_name + ')' : '' )
188 + '</span>';
189 }
190
191 return item.text;
192
193 }
194
195 /**
196 * Custom results processing for posts on select2
197 *
198 * @since 1.4.1
199 *
200 * @param {Object} response
201 * @param {Object} params
202 *
203 * @return {string}
204 */
205 function gamipress_select2_posts_process_results( response, params ) {
206
207 if( response === null ) {
208 return { results: [] };
209 }
210
211 var formatted_results = [];
212
213 // Paginated responses will come with results and more_results keys
214 var results = ( response.data.results !== undefined ? response.data.results : response.data );
215
216 results.forEach( function( item ) {
217
218 // Extend select2 keys (id and text) with given keys (ID, post_title and optionally post_type, site_id and site_name)
219 formatted_results.push( jQuery.extend({
220 id: item.ID,
221 text: item.post_title + ' (#' + item.ID + ')',
222 }, item ) );
223
224 } );
225
226 return {
227 results: formatted_results,
228 pagination: {
229 more: ( response.data.more_results !== undefined ? response.data.more_results : false )
230 }
231 };
232
233 }
234
235 /**
236 * Custom formatting for users on select2
237 *
238 * @since 1.4.1
239 *
240 * @param {Object} item
241 *
242 * @return {string}
243 */
244 function gamipress_select2_users_template_result( item ) {
245
246 if( item.display_name !== undefined ) {
247
248 return '<strong>' + item.display_name + '</strong>'
249 + '<span class="result-description">'
250 + 'ID: ' + item.ID + ' - ' + item.user_email + ' (' + item.user_login + ')'
251 + '</span>';
252 }
253
254 return item.text;
255
256 }
257
258 /**
259 * Custom results processing for users on select2
260 *
261 * @since 1.4.1
262 *
263 * @param {Object} response
264 * @param {Object} params
265 *
266 * @return {string}
267 */
268 function gamipress_select2_users_process_results( response, params ) {
269
270 if( response === null ) {
271 return { results: [] };
272 }
273
274 var formatted_results = [];
275
276 // Paginated responses will come with results and more_results keys
277 var results = ( response.data.results !== undefined ? response.data.results : response.data );
278
279 results.forEach( function( item ) {
280
281 // Extend select2 keys (id and text) with given keys (ID, post_title and optionally post_type)
282 formatted_results.push( jQuery.extend({
283 id: item.ID,
284 text: item.user_login + ' (#' + item.ID + ')',
285 }, item ) );
286
287 } );
288
289 return {
290 results: formatted_results,
291 pagination: {
292 more: ( response.data.more_results !== undefined ? response.data.more_results : false )
293 }
294 };
295
296 }
297
298 /**
299 * Custom search matcher for selects with groups on select2
300 *
301 * @since 1.6.3
302 *
303 * @param {Object} params
304 * @param {Object} data
305 *
306 * @return {mixed}
307 */
308 function gamipress_select2_optgroup_matcher( params, data ) {
309
310 // Initialize required vars
311 data.parentText = data.parentText || '';
312
313 // Always return the object if there is nothing to compare
314 if ( params.term === undefined ) {
315 return data;
316 }
317
318 if ( params.term.trim() === '' ) {
319 return data;
320 }
321
322 // Do a recursive check for options with children
323 if ( data.children && data.children.length > 0 ) {
324
325 // Clone the data object if there are children
326 // This is required as we modify the object to remove any non-matches
327 var match = jQuery.extend( true, {}, data );
328
329 // Check each child of the option
330 for ( var c = data.children.length - 1; c >= 0; c-- ) {
331
332 var child = data.children[c];
333 child.parentText += data.parentText + " " + data.text;
334
335 var matches = gamipress_select2_optgroup_matcher( params, child );
336
337 // If there wasn't a match, remove the object in the array
338 if (matches == null) {
339 match.children.splice( c, 1 );
340 }
341
342 }
343
344 // If any children matched, return the new object
345 if ( match.children.length > 0 ) {
346 return match;
347 }
348
349 // If there were no matching children, check just the plain object
350 return gamipress_select2_optgroup_matcher( params, match );
351
352 }
353
354 // If the typed-in term matches the text of this term, or the text from any
355 // parent term, then it's a match.
356 var original = ( data.parentText + ' ' + data.text ).toUpperCase();
357 var term = params.term.toUpperCase();
358
359
360 // Check if the text contains the term
361 if ( original.indexOf( term ) > -1 ) {
362 return data;
363 }
364
365 // If it doesn't contain the term, don't return anything
366 return null;
367 }
368
369 /**
370 * Check if post type has been registered
371 *
372 * @since 1.6.5
373 *
374 * @param {string} post_type
375 *
376 * @return {boolean}
377 */
378 function gamipress_post_type_exists( post_type ) {
379 return ( gamipress_admin_functions.post_type_labels[post_type] !== undefined )
380 }
381
382 /**
383 * Get the post type label (singular name)
384 *
385 * @since 1.6.5
386 *
387 * @param {string} post_type
388 *
389 * @return {string}
390 */
391 function gamipress_get_post_type_label( post_type ) {
392
393 var label = '';
394
395 if( gamipress_post_type_exists( post_type ) ) {
396 label = gamipress_admin_functions.post_type_labels[post_type];
397 }
398
399 return label;
400 }
401
402 /**
403 * Check if given term is on reserved terms
404 *
405 * @since 1.7.4
406 *
407 * @param {string} term
408 *
409 * @return {boolean}
410 */
411 function gamipress_is_reserved_term( term ) {
412 return ( gamipress_admin_functions.reserved_terms.indexOf( term ) !== -1 )
413 }
414
415 /**
416 * Check if given slug has any error (like invalid chars, exceeds lenght, etc)
417 *
418 * @since 1.7.4
419 *
420 * @param {string} slug
421 * @param {string} current_slug
422 *
423 * @return {string}
424 */
425 function gamipress_get_slug_error( slug, current_slug ) {
426
427 // Only allow alphanumeric characters, "-" adn "_"
428 if( /[^a-zA-Z0-9\-_]/.test( slug ) )
429 return gamipress_admin_functions.slug_error_special_char;
430
431 // Check if slug is greater than 20 characters (maximum allowed for a post type)
432 if ( slug.length > 20 )
433 return gamipress_admin_functions.slug_error_max_length;
434
435 // Check if slug has been already registered
436 if( gamipress_post_type_exists( slug ) && slug !== current_slug )
437 return gamipress_admin_functions.slug_error_post_type.replace( '%s', gamipress_get_post_type_label( slug ) );
438
439 // Check if slug matches a reserved term
440 if ( gamipress_is_reserved_term( slug ) )
441 return gamipress_admin_functions.slug_error_reserved_term;
442
443 // No errors
444 return '';
445 }
446
447 /**
448 * Function to turn an object or a JSON object to a CSV file and force the download (Used on import/export tools)
449 *
450 * @since 1.6.4
451 *
452 * @param {Object} data
453 * @param {string} filename
454 */
455 function gamipress_download_csv( data, filename ) {
456
457 // Convert JSON to CSV
458 var csv = gamipress_object_to_csv( data );
459
460 gamipress_download_file( csv, filename, 'csv' );
461
462 }
463
464 /**
465 * Function to force the download of the given content (Used on import/export tools)
466 *
467 * @since 1.7.0
468 *
469 * @param {string} content
470 * @param {string} filename
471 * @param {string} extension
472 * @param {string} mime_type
473 * @param {string} charset
474 */
475 function gamipress_download_file( content, filename, extension, mime_type = '', charset = '' ) {
476
477 if( mime_type === undefined || mime_type === '' )
478 mime_type = 'text/' + extension;
479
480 if( charset === undefined || charset === '' )
481 charset = 'utf-8';
482
483 // Setup the file name
484 var file = ( filename.length ? filename + '.' + extension : 'file.' + extension );
485
486 var blob = new Blob( [content], { type: mime_type + ';charset=' + charset + ';' } );
487
488 if (navigator.msSaveBlob) {
489
490 // IE 10+
491 navigator.msSaveBlob( blob, file );
492
493 } else {
494
495 var link = document.createElement("a");
496
497 // Hide the link element
498 link.style.visibility = 'hidden';
499
500 // Check if browser supports HTML5 download attribute
501 if ( link.download !== undefined ) {
502
503 // Build the URL object
504 var url = URL.createObjectURL( blob );
505
506 // Update link attributes
507 link.setAttribute( "href", url );
508 link.setAttribute( "download", file );
509
510 // Append the link element and trigger the click event
511 document.body.appendChild( link );
512
513 link.click(); // NOTE: Is not a jQuery element, so is safe to use click()
514
515 // Finally remove the link element
516 document.body.removeChild( link );
517
518 }
519 }
520
521 }
522
523 /**
524 * Format an object into a CSV line
525 *
526 * @since 1.6.4
527 *
528 * @param {Object} obj
529 *
530 * @return {string}
531 */
532 function gamipress_object_to_csv( obj ) {
533
534 // Convert JSON to Object
535 var array = typeof obj !== 'object' ? JSON.parse( obj ) : obj;
536 var str = '';
537
538 for ( var i = 0; i < array.length; i++ ) {
539
540 var line = '';
541
542 for ( var index in array[i] ) {
543
544 // Separator
545 if ( line !== '' ) {
546 line += ',';
547 }
548
549 // Build a new line
550 line += '"' + array[i][index] + '"';
551 }
552
553 // Append the line break
554 str += line + '\r\n';
555
556 }
557
558 return str;
559
560 }
561
562 /**
563 * Helper function to get a parameter from an URL
564 *
565 * @since 1.0.0
566 *
567 * @param {String} url
568 * @param {String} param
569 * @param default_value
570 *
571 * @return {String}
572 */
573 function gamipress_get_url_param( url, param, default_value = false ) {
574
575 var results = new RegExp('[\?&]' + param + '=([^&#]*)').exec( url );
576
577 return results[1] || default_value;
578
579 }
580
581 /**
582 * Helper function to check if given URL is a valid one
583 *
584 * @since 1.0.0
585 *
586 * @param {String} url
587 *
588 * @return {boolean}
589 */
590 function gamipress_is_valid_url( url ) {
591 var result = url.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
592 return ( result !== null )
593 }
594
595 /**
596 * Helper function to remove script tags in a string
597 * @param String s
598 * @returns {string}
599 */
600 function gamipress_strip_scripts(s) {
601 var div = document.createElement('div');
602 div.innerHTML = s;
603 var scripts = div.getElementsByTagName('script');
604 var i = scripts.length;
605 while (i--) {
606 scripts[i].parentNode.removeChild(scripts[i]);
607 }
608 return div.innerHTML;
609 }