PluginProbe
Social Media Auto Poster – Schedule & Publish to Buffer / 6.2.5
Social Media Auto Poster – Schedule & Publish to Buffer v6.2.5
6.2.5 6.2.4 6.2.3 6.2.2 6.2.1 6.2.0 6.1.2 6.1.1 6.1.0 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 6.0.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 All 126 releases
wp-to-buffer / lib / social / assets / js / statuses.js

statuses.js in Social Media Auto Poster – Schedule & Publish to Buffer 6.2.5, at lib/social/assets/js/statuses.js

2,221 lines 55.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Handles the status settings screens at Plugin and Post level,
3 * for the UI and saving changes.
4 *
5 * @since 3.9.6
6 *
7 * @package
8 * @author WP Zinc
9 */
10
11 /**
12 * Reinitializes autosize instances
13 *
14 * @since 3.9.6
15 */
16 function wpZincSocialReinitAutosize() {
17 (function ($) {
18 // Bail if no autosize instances exist.
19 if (
20 $('.wpzinc-autosize-js', $(wpzinc_social.status_form)).length === 0
21 ) {
22 return;
23 }
24
25 autosize.destroy($('.wpzinc-autosize-js'));
26 autosize($('.wpzinc-autosize-js'));
27 })(jQuery);
28 }
29
30 /**
31 * Reinitializes autocomplete instances
32 *
33 * @since 3.9.6
34 */
35 function wpZincSocialReinitAutocomplete() {
36 wp_zinc_autocomplete_destroy();
37 wp_zinc_autocomplete_setup();
38 wp_zinc_autocomplete_initialize();
39 }
40
41 /**
42 * Reinitializes status tag instances
43 *
44 * @since 3.9.6
45 */
46 function wpZincSocialInitTags() {
47 (function ($) {
48 // Bail if no tag instances exist.
49 if ($('select.tags', $(wpzinc_social.status_form)).length === 0) {
50 return;
51 }
52
53 $('select.tags', $(wpzinc_social.status_form)).each(function () {
54 $(this).on('change.wpzinc-social', function () {
55 // Insert tag into required textarea.
56 let tag = $(this).val();
57 const textarea = $(this).attr('data-textarea');
58 const option = $('option:selected', $(this));
59 const status = $(this).closest('.wpzinc-social-status-form');
60 const sel = $(textarea, $(status));
61 const val = $(sel).val();
62
63 // If the selected option contains data attributes, we need to show a prompt to fetch an input
64 // before inserting the tag.
65 if (typeof $(option).data('question') !== 'undefined') {
66 // Prompt question.
67 let tag_replacement = prompt(
68 $(option).data('question'),
69 $(option).data('default-value')
70 );
71
72 // If no answer was given, use the default.
73 if (tag_replacement.length === 0) {
74 tag_replacement = $(option).data('default-value');
75 }
76
77 // Replace the replacement string with the input.
78 tag = tag.replace(
79 $(option).data('replace'),
80 tag_replacement
81 );
82 }
83
84 // Get position of cursor.
85 const pos = $(sel)[0].selectionStart;
86
87 // Pad tag if cursor not at start and the character immediately preceding and/or following
88 // the cursor isn't a space.
89 if (pos > 0) {
90 if (val.substring(pos - 1, pos) !== ' ') {
91 tag = ' ' + tag;
92 }
93 if (val.substring(pos, pos + 1) !== ' ') {
94 tag = tag + ' ';
95 }
96 }
97
98 // Insert tag if it has a value.
99 if (tag.trim().length > 0) {
100 $(sel)
101 .val(val.substring(0, pos) + tag + val.substring(pos))
102 .trigger('change');
103 }
104
105 // Reset tag selector (if we don't, selecting the same option twice results in the tag not being inserted
106 // the second time).
107 $(this).val('');
108 });
109 });
110 })(jQuery);
111 }
112
113 /**
114 * Initializes selectize instances
115 *
116 * @since 4.4.0
117 *
118 * @param {string} selector Initialize .wpzinc-selectize instances within the given DOM selector.
119 * @param {number} profile_id Profile ID.
120 * @param {string} action Action (publish,update,repost,bulk_publish).
121 * @param {number} status_index Zero based index of this status relative to all statuses for the Profile ID and Action.
122 */
123 function wpZincSocialInitSelectize(selector, profile_id, action, status_index) {
124 (function ($) {
125 $('.wpzinc-selectize', $(selector)).each(function () {
126 const field_id = $(this).attr('id');
127 let statuses_container = false,
128 row = false,
129 options = {},
130 selectize_options = [];
131
132 // If we're initializing selectize on a status, fetch the status which contains JSON to prepopulate existing values
133 // for this selectize instance.
134 if (profile_id && action) {
135 statuses_container = $(
136 'div.statuses[data-profile-id="' +
137 profile_id +
138 '"][data-action="' +
139 action +
140 '"]'
141 );
142 row = $(
143 'tr[data-status-index="' + status_index + '"]',
144 $(statuses_container)
145 );
146 options = JSON.parse($(row).attr('data-labels'));
147 selectize_options =
148 typeof options[field_id] !== typeof undefined
149 ? options[field_id]
150 : [];
151 }
152
153 // Init selectize.
154 $(this).selectize({
155 valueField: 'id',
156 labelField: 'text',
157 searchField: 'text',
158 plugins: ['drag_drop', 'remove_button'],
159 options: selectize_options,
160 delimiter: ',',
161 persist: false,
162 create: false,
163 load(query, callback) {
164 // Bail if the number of characters typed isn't enough.
165 if (!query.length || query.length < 3) {
166 return callback();
167 }
168
169 // Perform AJAX request.
170 $.ajax({
171 url: ajaxurl,
172 data: {
173 action: this.$input.data('action'),
174 taxonomy: this.$input.data('taxonomy'),
175 nonce: wpzinc_social[this.$input.data('nonce-key')],
176 q: query,
177 page: 10,
178 },
179 error() {
180 callback();
181 },
182 success(result) {
183 callback(result.data);
184 },
185 });
186 },
187 onChange() {
188 // If we're editing a status, assign a JSON string of this selectize instance's
189 // IDs and values back to the status row.
190 if (row) {
191 // Build array of labels that can be used if we reinit this selectize instance on
192 // this field again.
193 const labels = [],
194 length = this.items.length;
195 for (i = 0; i < length; i++) {
196 labels.push({
197 id: this.options[this.items[i]].id,
198 text: this.options[this.items[i]].text,
199 });
200 }
201
202 // Add to options object and inject back into the data-labels status row.
203 options = JSON.parse($(row).attr('data-labels'));
204 options[field_id] = labels;
205 $(row)
206 .data('labels', JSON.stringify(options))
207 .attr('data-labels', JSON.stringify(options));
208 }
209 },
210 });
211 });
212 })(jQuery);
213 }
214
215 /**
216 * Destroys selectize instances
217 *
218 * @since 4.4.0
219 *
220 * @param {string} selector Destroy .wpzinc-selectize instances within the given DOM selector.
221 */
222 function wpZincSocialDestroySelectize(selector) {
223 (function ($) {
224 $('.wpzinc-selectize', $(selector)).each(function () {
225 if (this.selectize) {
226 this.selectize.destroy();
227 }
228 });
229 })(jQuery);
230 }
231
232 /**
233 * Reindexes statuses
234 *
235 * @since 3.9.6
236 *
237 * @param {string} statuses_container Profile and Action Statuses Container, containing the statuses to reindex.
238 */
239 function wpZincSocialReindexStatuses(statuses_container) {
240 (function ($) {
241 // Find all sortable options in the status container (these are individual statuses)
242 // and reindex them from 1.
243 $('tr.sortable', $(statuses_container)).each(function (i) {
244 // Update data-status-index, zero based.
245 $(this).data('status-index', i).attr('data-status-index', i);
246
247 // Display the index number, zero + 1 based.
248 $('td.count ', $(this)).html('#' + (i + 1));
249
250 // Set 'first' class.
251 if (i === 0) {
252 $(this).addClass('first');
253 } else {
254 $(this).removeClass('first');
255 }
256 });
257 })(jQuery);
258 }
259
260 /**
261 * Show/hide schedule options based on the chosen schedule
262 *
263 * @since 3.9.6
264 *
265 * @param {string} action Action (publish,update,repost,bulk_publish)
266 */
267 function wpZincSocialUpdateScheduleOptions(action) {
268 (function ($) {
269 // Bail if no schedule dropdowns exist.
270 if ($('select.schedule', $(wpzinc_social.status_form)).length === 0) {
271 return;
272 }
273
274 // Show / hide schedule options.
275 switch ($('select.schedule', $(wpzinc_social.status_form)).val()) {
276 case 'custom':
277 $('div.schedule', $(wpzinc_social.status_form)).show();
278 $('span.schedule', $(wpzinc_social.status_form)).show();
279 $('span.hours_mins_secs', $(wpzinc_social.status_form)).show();
280 $('span.relative', $(wpzinc_social.status_form)).hide();
281 $('span.custom', $(wpzinc_social.status_form))
282 .text('after ' + action)
283 .show();
284 $('span.custom_field', $(wpzinc_social.status_form)).hide();
285 $(
286 'span.the_events_calendar',
287 $(wpzinc_social.status_form)
288 ).hide();
289 $('span.events_manager', $(wpzinc_social.status_form)).hide();
290 $(
291 'span.modern_events_calendar',
292 $(wpzinc_social.status_form)
293 ).hide();
294 $('span.specific', $(wpzinc_social.status_form)).hide();
295 break;
296
297 case 'custom_relative':
298 $('div.schedule', $(wpzinc_social.status_form)).show();
299 $('span.schedule', $(wpzinc_social.status_form)).show();
300 $('span.hours_mins_secs', $(wpzinc_social.status_form)).hide();
301 $('span.relative', $(wpzinc_social.status_form)).show();
302 $('span.custom', $(wpzinc_social.status_form))
303 .text('after ' + action)
304 .show();
305 $('span.custom_field', $(wpzinc_social.status_form)).hide();
306 $(
307 'span.the_events_calendar',
308 $(wpzinc_social.status_form)
309 ).hide();
310 $('span.events_manager', $(wpzinc_social.status_form)).hide();
311 $(
312 'span.modern_events_calendar',
313 $(wpzinc_social.status_form)
314 ).hide();
315 $('span.specific', $(wpzinc_social.status_form)).hide();
316 break;
317
318 case 'custom_field':
319 $('div.schedule', $(wpzinc_social.status_form)).show();
320 $('span.schedule', $(wpzinc_social.status_form)).show();
321 $('span.hours_mins_secs', $(wpzinc_social.status_form)).show();
322 $('span.relative', $(wpzinc_social.status_form)).hide();
323 $('span.custom', $(wpzinc_social.status_form)).text('').hide();
324 $('span.custom_field', $(wpzinc_social.status_form)).show();
325 $(
326 'span.the_events_calendar',
327 $(wpzinc_social.status_form)
328 ).hide();
329 $('span.events_manager', $(wpzinc_social.status_form)).hide();
330 $(
331 'span.modern_events_calendar',
332 $(wpzinc_social.status_form)
333 ).hide();
334 $('span.specific', $(wpzinc_social.status_form)).hide();
335 break;
336
337 case '_EventStartDate':
338 case '_EventEndDate':
339 $('div.schedule', $(wpzinc_social.status_form)).show();
340 $('span.schedule', $(wpzinc_social.status_form)).show();
341 $('span.hours_mins_secs', $(wpzinc_social.status_form)).show();
342 $('span.relative', $(wpzinc_social.status_form)).hide();
343 $('span.custom', $(wpzinc_social.status_form)).text('').hide();
344 $('span.custom_field', $(wpzinc_social.status_form)).hide();
345 $(
346 'span.the_events_calendar',
347 $(wpzinc_social.status_form)
348 ).show();
349 $('span.events_manager', $(wpzinc_social.status_form)).hide();
350 $(
351 'span.modern_events_calendar',
352 $(wpzinc_social.status_form)
353 ).hide();
354 $('span.specific', $(wpzinc_social.status_form)).hide();
355 break;
356
357 case '_event_start_date':
358 case '_event_end_date':
359 $('div.schedule', $(wpzinc_social.status_form)).show();
360 $('span.schedule', $(wpzinc_social.status_form)).show();
361 $('span.hours_mins_secs', $(wpzinc_social.status_form)).show();
362 $('span.relative', $(wpzinc_social.status_form)).hide();
363 $('span.custom', $(wpzinc_social.status_form)).text('').hide();
364 $('span.custom_field', $(wpzinc_social.status_form)).hide();
365 $(
366 'span.the_events_calendar',
367 $(wpzinc_social.status_form)
368 ).hide();
369 $('span.events_manager', $(wpzinc_social.status_form)).show();
370 $(
371 'span.modern_events_calendar',
372 $(wpzinc_social.status_form)
373 ).hide();
374 $('span.specific', $(wpzinc_social.status_form)).hide();
375 break;
376
377 case 'mec_start_datetime':
378 case 'mec_end_datetime':
379 $('div.schedule', $(wpzinc_social.status_form)).show();
380 $('span.schedule', $(wpzinc_social.status_form)).show();
381 $('span.hours_mins_secs', $(wpzinc_social.status_form)).show();
382 $('span.relative', $(wpzinc_social.status_form)).hide();
383 $('span.custom', $(wpzinc_social.status_form)).text('').hide();
384 $('span.custom_field', $(wpzinc_social.status_form)).hide();
385 $(
386 'span.the_events_calendar',
387 $(wpzinc_social.status_form)
388 ).hide();
389 $('span.events_manager', $(wpzinc_social.status_form)).hide();
390 $(
391 'span.modern_events_calendar',
392 $(wpzinc_social.status_form)
393 ).show();
394 $('span.specific', $(wpzinc_social.status_form)).hide();
395 break;
396
397 case 'specific':
398 $('div.schedule', $(wpzinc_social.status_form)).show();
399 $('span.schedule', $(wpzinc_social.status_form)).show();
400 $('span.hours_mins_secs', $(wpzinc_social.status_form)).hide();
401 $('span.relative', $(wpzinc_social.status_form)).hide();
402 $('span.custom', $(wpzinc_social.status_form)).text('').hide();
403 $('span.custom_field', $(wpzinc_social.status_form)).hide();
404 $(
405 'span.the_events_calendar',
406 $(wpzinc_social.status_form)
407 ).hide();
408 $('span.events_manager', $(wpzinc_social.status_form)).hide();
409 $(
410 'span.modern_events_calendar',
411 $(wpzinc_social.status_form)
412 ).hide();
413 $('span.specific', $(wpzinc_social.status_form)).show();
414 break;
415
416 default:
417 // Hide additonal schedule options.
418 $('div.schedule', $(wpzinc_social.status_form)).hide();
419 $('span.schedule', $(wpzinc_social.status_form)).hide();
420 $('span.hours_mins_secs', $(wpzinc_social.status_form)).hide();
421 $('span.relative', $(wpzinc_social.status_form)).hide();
422 $('span.custom', $(wpzinc_social.status_form)).text('').hide();
423 $('span.custom_field', $(wpzinc_social.status_form)).hide();
424 $(
425 'span.the_events_calendar',
426 $(wpzinc_social.status_form)
427 ).hide();
428 $('span.events_manager', $(wpzinc_social.status_form)).hide();
429 $(
430 'span.modern_events_calendar',
431 $(wpzinc_social.status_form)
432 ).hide();
433 $('span.specific', $(wpzinc_social.status_form)).hide();
434 break;
435 }
436 })(jQuery);
437 }
438
439 /**
440 * Show/hide text to image options based on the chosen image option
441 *
442 * @since 4.2.0
443 */
444 function wpZincSocialUpdateImageOptions() {
445 (function ($) {
446 // Bail if no image dropdowns exist.
447 if ($('select.image', $(wpzinc_social.status_form)).length === 0) {
448 return;
449 }
450
451 // Get selected image option.
452 const selected_image_option = $(
453 'select.image',
454 $(wpzinc_social.status_form)
455 ).val();
456
457 // Hide additional and text to image options.
458 $(
459 'tr.additional-images, tr.text-to-image',
460 $(wpzinc_social.status_form)
461 ).hide();
462
463 // Show additional and text to image options, based on the selected image option.
464 $(
465 'tr.additional-images, tr.text-to-image',
466 $(wpzinc_social.status_form)
467 ).each(function () {
468 const conditionalValues = $(this)
469 .data('conditional-value')
470 .toString()
471 .split(','); // .toString() prevents errors when splitting a single integer e.g. 2.
472 if (conditionalValues.indexOf(selected_image_option) !== -1) {
473 $(this).show();
474 }
475 });
476 })(jQuery);
477 }
478
479 /**
480 * Show/hide Google Business options based on the chosen Google Business Post Type option
481 *
482 * @since 4.9.0
483 */
484 function wpZincSocialUpdateGoogleBusinessOptions() {
485 (function ($) {
486 // Bail if no Google Business Post Type dropdown exists.
487 if (
488 $('select#googlebusiness_post_type', $(wpzinc_social.status_form))
489 .length === 0
490 ) {
491 return;
492 }
493
494 // Hide all table rows.
495 $('tr.whats_new', $(wpzinc_social.status_form)).hide();
496 $('tr.event', $(wpzinc_social.status_form)).hide();
497 $('tr.offer', $(wpzinc_social.status_form)).hide();
498
499 // Show table rows matching the post type.
500 $(
501 'tr.' +
502 $(
503 'select#googlebusiness_post_type',
504 $(wpzinc_social.status_form)
505 ).val(),
506 $(wpzinc_social.status_form)
507 ).show();
508 })(jQuery);
509 }
510
511 /**
512 * Update post type options based on the profile provider.
513 *
514 * @since 6.0.0
515 *
516 * @param {Object} profile Profile.
517 */
518 function wpZincSocialUpdatePostTypeOptions(profile) {
519 (function ($) {
520 // Disable all options.
521 $('option', $('select.post_type', $(wpzinc_social.status_form))).attr(
522 'disabled',
523 true
524 );
525
526 // Enable options based on the profile service.
527 switch (profile.service) {
528 case 'instagram':
529 $(
530 'option[value="image"]',
531 $('select.post_type', $(wpzinc_social.status_form))
532 ).attr('disabled', false);
533 $(
534 'option[value="story"]',
535 $('select.post_type', $(wpzinc_social.status_form))
536 ).attr('disabled', false);
537 break;
538
539 case 'pinterest':
540 $(
541 'option[value="pin"]',
542 $('select.post_type', $(wpzinc_social.status_form))
543 ).attr('disabled', false);
544 break;
545
546 case 'googlebusiness':
547 $(
548 'option[value="googlebusiness"]',
549 $('select.post_type', $(wpzinc_social.status_form))
550 ).attr('disabled', false);
551 break;
552
553 default:
554 $(
555 'option[value="text"]',
556 $('select.post_type', $(wpzinc_social.status_form))
557 ).attr('disabled', false);
558 $(
559 'option[value="link"]',
560 $('select.post_type', $(wpzinc_social.status_form))
561 ).attr('disabled', false);
562 $(
563 'option[value="image"]',
564 $('select.post_type', $(wpzinc_social.status_form))
565 ).attr('disabled', false);
566 break;
567 }
568
569 // If the current selected value is now disabled, set it to the first enabled value.
570 if (
571 $('select.post_type', $(wpzinc_social.status_form)).val() ===
572 'disabled'
573 ) {
574 $('select.post_type', $(wpzinc_social.status_form)).val(
575 $(
576 'option:enabled',
577 $('select.post_type', $(wpzinc_social.status_form))
578 )
579 .first()
580 .val()
581 );
582 }
583 })(jQuery);
584 }
585
586 /**
587 * Show/hide status options based on the chosen post type
588 *
589 * @since 6.0.0
590 */
591 function wpZincSocialUpdateStatusSections() {
592 (function ($) {
593 // Hide all sections.
594 $('.wpzinc-option.link', $(wpzinc_social.status_form)).hide();
595 $('.wpzinc-option.images', $(wpzinc_social.status_form)).hide();
596 $('.wpzinc-option.pinterest', $(wpzinc_social.status_form)).hide();
597 $('.wpzinc-option.googlebusiness', $(wpzinc_social.status_form)).hide();
598
599 // Show sections based on the chosen status post type.
600 switch ($('select.post_type', $(wpzinc_social.status_form)).val()) {
601 case 'link':
602 $('.wpzinc-option.link', $(wpzinc_social.status_form)).show();
603 $('.wpzinc-option.images', $(wpzinc_social.status_form)).hide();
604 break;
605
606 case 'image':
607 case 'story':
608 $('.wpzinc-option.link', $(wpzinc_social.status_form)).hide();
609 $('.wpzinc-option.images', $(wpzinc_social.status_form)).show();
610 break;
611
612 case 'pin':
613 $('.wpzinc-option.link', $(wpzinc_social.status_form)).show();
614 $('.wpzinc-option.images', $(wpzinc_social.status_form)).show();
615 $(
616 '.wpzinc-option.pinterest',
617 $(wpzinc_social.status_form)
618 ).show();
619 break;
620
621 case 'googlebusiness':
622 $('.wpzinc-option.link', $(wpzinc_social.status_form)).show();
623 $('.wpzinc-option.images', $(wpzinc_social.status_form)).show();
624 $(
625 '.wpzinc-option.googlebusiness',
626 $(wpzinc_social.status_form)
627 ).show();
628 break;
629 }
630 })(jQuery);
631 }
632
633 /**
634 * Adds a status for the given profile ID and action, by duplicating
635 * the last status.
636 *
637 * @since 4.4.0
638 *
639 * @param {string} profile_id Profile ID.
640 * @param {string} action Action (publish,update,repost,bulk_publish).
641 */
642 function wpZincSocialAddStatus(profile_id, action) {
643 (function ($) {
644 // Get last status row.
645 // Get last status and container.
646 const statuses_container = $(
647 'div.statuses[data-profile-id="' +
648 profile_id +
649 '"][data-action="' +
650 action +
651 '"]'
652 ),
653 statuses_table_body = $('tbody', $(statuses_container)),
654 last_status = $('tr.status', $(statuses_table_body)).last();
655
656 // Clone status to new row in table.
657 $(statuses_table_body).first().after($(last_status).clone());
658
659 // Reindex statuses.
660 wpZincSocialReindexStatuses(statuses_container);
661
662 // Populate hidden field with all statuses' data.
663 wpZincSocialUpdateStatuses();
664 })(jQuery);
665 }
666
667 /**
668 * Displays an inline form for editing a given status, populating
669 * the form's values.
670 *
671 * @since 4.4.0
672 *
673 * @param {string} profile_id Profile ID.
674 * @param {Object} profile Profile (from API).
675 * @param {string} action Action (publish,update,repost,bulk_publish).
676 * @param {number} status_index Zero based index of this status relative to all statuses for the Profile ID and Action.
677 * @param {Object} status Status.
678 */
679 function wpZincSocialEditStatus(
680 profile_id,
681 profile,
682 action,
683 status_index,
684 status
685 ) {
686 // Destroy selectize.
687 wpZincSocialDestroySelectize(wpzinc_social.status_form);
688
689 // Populate form values.
690 wpZincSocialPopulateStatusForm(
691 profile_id,
692 profile,
693 action,
694 status_index,
695 status
696 );
697
698 // Update post type options.
699 wpZincSocialUpdatePostTypeOptions(profile);
700
701 // Update schedule options.
702 wpZincSocialUpdateScheduleOptions(action);
703
704 // Update image options.
705 wpZincSocialUpdateImageOptions();
706
707 // Update status sections to display, depending on the status' post type.
708 wpZincSocialUpdateStatusSections();
709
710 // Update Google Business options.
711 wpZincSocialUpdateGoogleBusinessOptions();
712
713 // Display form.
714 wpZincSocialDisplayStatusForm(profile_id, action, status_index);
715
716 // Reinit autosize.
717 wpZincSocialReinitAutosize();
718
719 // Reinit autocomplete.
720 wpZincSocialReinitAutocomplete();
721
722 // Init selectize.
723 wpZincSocialInitSelectize(
724 wpzinc_social.status_form,
725 profile_id,
726 action,
727 status_index
728 );
729 }
730
731 /**
732 * Deletes a status for the given profile ID, action and index.
733 *
734 * @since 4.4.0
735 *
736 * @param {string} profile_id Profile ID.
737 * @param {string} action Action (publish,update,repost,bulk_publish).
738 * @param {number} status_index Zero based index of this status relative to all statuses for the Profile ID and Action.
739 */
740 function wpZincSocialDeleteStatus(profile_id, action, status_index) {
741 (function ($) {
742 // Confirm deletion.
743 const result = confirm(wpzinc_social.delete_status_message);
744 if (!result) {
745 return;
746 }
747
748 // Get status and container.
749 const statuses_container = $(
750 'div.statuses[data-profile-id="' +
751 profile_id +
752 '"][data-action="' +
753 action +
754 '"]'
755 ),
756 row = $(
757 'tr[data-status-index="' + status_index + '"]',
758 $(statuses_container)
759 );
760
761 // Delete status.
762 $(row).remove();
763
764 // Reindex statuses.
765 wpZincSocialReindexStatuses(statuses_container);
766
767 // Populate hidden field with all statuses' data.
768 wpZincSocialUpdateStatuses();
769 })(jQuery);
770 }
771
772 /**
773 * Saves the status form values back to the status as a JSON data object.
774 *
775 * @since 4.4.0
776 *
777 * @param {string} profile_id Profile ID.
778 * @param {string} action Action (publish,update,repost,bulk_publish).
779 * @param {number} status_index Zero based index of this status relative to all statuses for the Profile ID and Action.
780 */
781 function wpZincSocialUpdateStatus(profile_id, action, status_index) {
782 (function ($) {
783 // Get row.
784 const row = $(
785 'div.statuses[data-profile-id="' +
786 profile_id +
787 '"][data-action="' +
788 action +
789 '"] tr[data-status-index="' +
790 status_index +
791 '"]'
792 );
793 let status_custom_fields_index = -1;
794 let status_authors_custom_fields_index = -1;
795 const status = JSON.parse($(row).attr('data-status'));
796
797 // Reset some status elements.
798 status.conditions = {};
799 status.custom_fields = {};
800 status.authors_custom_fields = {};
801 status.terms = {};
802
803 // Iterate through the status form, building the status object.
804 $.each(
805 $(wpzinc_social.status_form)
806 .find('input, select, textarea')
807 .serializeArray(),
808 function (index, field) {
809 // Remove prepended Plugin Name from Field Name.
810 field.name = field.name.replace(
811 wpzinc_social.plugin_name + '_',
812 ''
813 );
814
815 switch (field.name) {
816 case 'pinterest[board]':
817 // Check both <select> and <input> for a value.
818 if (
819 $(
820 'input[name="' +
821 wpzinc_social.plugin_name +
822 '_' +
823 field.name +
824 '"]',
825 $(wpzinc_social.status_form)
826 ).val() !== ''
827 ) {
828 status.pinterest.board = $(
829 'input[name="' +
830 wpzinc_social.plugin_name +
831 '_' +
832 field.name +
833 '"]',
834 $(wpzinc_social.status_form)
835 ).val();
836 } else if (
837 $(
838 'select[name="' +
839 wpzinc_social.plugin_name +
840 '_' +
841 field.name +
842 '"]',
843 $(wpzinc_social.status_form)
844 ).val()
845 ) {
846 status.pinterest.board = $(
847 'select[name="' +
848 wpzinc_social.plugin_name +
849 '_' +
850 field.name +
851 '"]',
852 $(wpzinc_social.status_form)
853 ).val();
854 }
855 break;
856
857 /**
858 * Conditions: Custom Fields
859 */
860 case 'custom_fields[key][]':
861 status_custom_fields_index++;
862
863 // Ignore if no key specified.
864 if (field.value === '') {
865 break;
866 }
867
868 status.custom_fields[status_custom_fields_index] = {};
869 status.custom_fields[status_custom_fields_index].key =
870 field.value;
871 break;
872 case 'custom_fields[compare][]':
873 // Ignore if no key specified for this Custom Field Condition.
874 if (
875 typeof status.custom_fields[
876 status_custom_fields_index
877 ] === typeof undefined
878 ) {
879 break;
880 }
881
882 status.custom_fields[
883 status_custom_fields_index
884 ].compare = field.value;
885 break;
886 case 'custom_fields[value][]':
887 // Ignore if no key specified for this Custom Field Condition.
888 if (
889 typeof status.custom_fields[
890 status_custom_fields_index
891 ] === typeof undefined
892 ) {
893 break;
894 }
895
896 status.custom_fields[status_custom_fields_index].value =
897 field.value;
898 break;
899
900 /**
901 * Authors
902 */
903 case 'authors':
904 if (field.value === 'false') {
905 break;
906 }
907
908 status[field.name] = field.value.split(',');
909 break;
910
911 /**
912 * Authors Roles
913 */
914 case 'authors_roles':
915 if (field.value === 'false') {
916 break;
917 }
918
919 status[field.name] = field.value.split(',');
920 break;
921
922 /**
923 * Conditions: Authors Custom Fields
924 */
925 case 'authors_custom_fields[key][]':
926 status_authors_custom_fields_index++;
927
928 // Ignore if no key specified.
929 if (field.value === '') {
930 break;
931 }
932
933 status.authors_custom_fields[
934 status_authors_custom_fields_index
935 ] = {};
936 status.authors_custom_fields[
937 status_authors_custom_fields_index
938 ].key = field.value;
939 break;
940 case 'authors_custom_fields[compare][]':
941 // Ignore if no key specified for this Custom Field Condition.
942 if (
943 typeof status.authors_custom_fields[
944 status_authors_custom_fields_index
945 ] === typeof undefined
946 ) {
947 break;
948 }
949
950 status.authors_custom_fields[
951 status_authors_custom_fields_index
952 ].compare = field.value;
953 break;
954 case 'authors_custom_fields[value][]':
955 // Ignore if no key specified for this Custom Field Condition.
956 if (
957 typeof status.authors_custom_fields[
958 status_authors_custom_fields_index
959 ] === typeof undefined
960 ) {
961 break;
962 }
963
964 status.authors_custom_fields[
965 status_authors_custom_fields_index
966 ].value = field.value;
967 break;
968
969 /**
970 * Other Fields
971 */
972 default:
973 /**
974 * Conditions: Taxonomy Conditions
975 */
976 const taxonomy = field.name.match(
977 /conditions\[([^)]+)\]/
978 );
979 if (taxonomy) {
980 status.conditions[taxonomy[1]] = field.value;
981 break;
982 }
983
984 /**
985 * Conditions: Terms
986 */
987 const term = field.name.match(/terms\[([^)]+)\]/);
988 if (term) {
989 status.terms[term[1]] = field.value.split(',');
990 break;
991 }
992
993 // Cast booleans.
994 if (field.value === 'true') {
995 field.value = true;
996 }
997 if (field.value === 'false') {
998 field.value = false;
999 }
1000
1001 /**
1002 * Handle array fields.
1003 */
1004 const matches = field.name.match(/(.*?)\[(.*?)\]/);
1005 if (matches !== null) {
1006 status[matches[1]][matches[2]] = field.value;
1007 } else {
1008 status[field.name] = field.value;
1009 }
1010 break;
1011 }
1012 }
1013 );
1014
1015 // Assign JSON string to data-status of the row.
1016 $(row)
1017 .data('status', JSON.stringify(status))
1018 .attr('data-status', JSON.stringify(status));
1019
1020 // Populate hidden field with all statuses' data.
1021 wpZincSocialUpdateStatuses();
1022
1023 // Fetch row cells data via AJAX.
1024 $.ajax({
1025 url: ajaxurl,
1026 type: 'POST',
1027 async: true,
1028 data: {
1029 action: wpzinc_social.get_status_row_action,
1030 nonce: wpzinc_social.get_status_row_nonce,
1031 post_type: wpzinc_social.post_type,
1032 post_action: action,
1033 status: JSON.stringify(status),
1034 },
1035 error(xhr) {
1036 alert(
1037 'wpZincSocialUpdateStatus(): error: ' +
1038 xhr.status +
1039 ' ' +
1040 xhr.statusText
1041 );
1042 },
1043 success(result) {
1044 // Bail if an error occured.
1045 if (!result.success) {
1046 alert(result.data);
1047 }
1048
1049 // Post Type.
1050 $('td.post_type', $(row)).text(result.data.post_type);
1051
1052 // Message.
1053 $('td.message', $(row)).text(result.data.message);
1054
1055 // Schedule.
1056 $('td.schedule', $(row)).text(result.data.schedule);
1057 },
1058 });
1059 })(jQuery);
1060 }
1061
1062 /**
1063 * Populates values in the status form for the given status
1064 *
1065 * @since 4.4.0
1066 *
1067 * @param {string} profile_id Profile ID.
1068 * @param {Object} profile Profile (from API).
1069 * @param {string} action Action (publish,update,repost,bulk_publish).
1070 * @param {number} status_index Zero based index of this status relative to all statuses for the Profile ID and Action.
1071 * @param {Object} status Status.
1072 */
1073 function wpZincSocialPopulateStatusForm(
1074 profile_id,
1075 profile,
1076 action,
1077 status_index,
1078 status
1079 ) {
1080 (function ($) {
1081 // Iterate through form fields.
1082 $('input, select, textarea', $(wpzinc_social.status_form)).each(
1083 function () {
1084 let field = $(this).attr('name');
1085
1086 // Skip if the field doesn't have a name, as it doesn't need to be populated.
1087 if (typeof field === 'undefined') {
1088 return;
1089 }
1090
1091 // Remove prepended Plugin Name from Field Name.
1092 field = field.replace(wpzinc_social.plugin_name + '_', '');
1093
1094 // Depending on the attribute, populate the field.
1095 switch (field) {
1096 /**
1097 * Pinterest: the user will need to specify the board to use
1098 * Buffer: The API gives us a list of subprofiles, comprising of boards
1099 * Hootsuite: The API gives us nothing, so we ask for a board URL, which we'll convert to a board ID later
1100 */
1101 case 'pinterest[board]':
1102 // Hide field if the Profile can be a seperate subprofile.
1103 if (profile.can_be_subprofile) {
1104 $(this).addClass('hidden');
1105 break;
1106 }
1107
1108 // Populate and show either the <select> or <input> pinterest[board] field.
1109 if (typeof profile.subprofiles !== typeof undefined) {
1110 // The API provides the Boards we can post to.
1111 // Show a <select> allowing the user to choose one.
1112
1113 // If there are no submprofiles, the Pinterest account has no boards attached to it yet.
1114 // Show a message.
1115 if (!Object.keys(profile.subprofiles).length) {
1116 $(
1117 'div.notice-inline.pinterest',
1118 $(wpzinc_social.status_form)
1119 ).removeClass('hidden');
1120 $(
1121 'select[name="' +
1122 wpzinc_social.plugin_name +
1123 '_' +
1124 field +
1125 '"]',
1126 $(wpzinc_social.status_form)
1127 ).addClass('hidden');
1128 $(
1129 'input[name="' +
1130 wpzinc_social.plugin_name +
1131 '_' +
1132 field +
1133 '"]',
1134 $(wpzinc_social.status_form)
1135 ).addClass('hidden');
1136 } else {
1137 // Populate <select> dropdown of subprofiles.
1138 $(
1139 'option',
1140 $(
1141 'select[name="' +
1142 wpzinc_social.plugin_name +
1143 '_' +
1144 field +
1145 '"]',
1146 $(wpzinc_social.status_form)
1147 )
1148 ).remove();
1149 for (const key in profile.subprofiles) {
1150 $(
1151 'select[name="' +
1152 wpzinc_social.plugin_name +
1153 '_' +
1154 field +
1155 '"]',
1156 $(wpzinc_social.status_form)
1157 ).append(
1158 $('<option></option>')
1159 .attr(
1160 'value',
1161 profile.subprofiles[key].id
1162 )
1163 .text(profile.subprofiles[key].name)
1164 );
1165 }
1166
1167 // Show <select> to allow Pinterest Board selection.
1168 $(
1169 'select[name="' +
1170 wpzinc_social.plugin_name +
1171 '_' +
1172 field +
1173 '"]',
1174 $(wpzinc_social.status_form)
1175 ).removeClass('hidden');
1176 $(
1177 'input[name="' +
1178 wpzinc_social.plugin_name +
1179 '_' +
1180 field +
1181 '"]',
1182 $(wpzinc_social.status_form)
1183 ).addClass('hidden');
1184 $(
1185 'select[name="' +
1186 wpzinc_social.plugin_name +
1187 '_' +
1188 field +
1189 '"]',
1190 $(wpzinc_social.status_form)
1191 ).val(status.pinterest.board);
1192 }
1193 } else {
1194 // The API doesn't provide the Boards we can post to.
1195 // Show <input> to allow Pinterest Board URL instead.
1196 $(
1197 'select[name="' +
1198 wpzinc_social.plugin_name +
1199 '_' +
1200 field +
1201 '"]',
1202 $(wpzinc_social.status_form)
1203 ).addClass('hidden');
1204 $(
1205 'input[name="' +
1206 wpzinc_social.plugin_name +
1207 '_' +
1208 field +
1209 '"]',
1210 $(wpzinc_social.status_form)
1211 ).removeClass('hidden');
1212 $(
1213 'input[name="' +
1214 wpzinc_social.plugin_name +
1215 '_' +
1216 field +
1217 '"]',
1218 $(wpzinc_social.status_form)
1219 ).val(status.pinterest.board);
1220 }
1221 break;
1222
1223 /**
1224 * Text to Image
1225 * If a Background Image is selected in text_to_image_background_image, populate the <img src=""> attribute.
1226 */
1227 case 'text_to_image_background_image':
1228 if (typeof status[field] !== 'undefined') {
1229 $(this).val(status[field]);
1230 } else {
1231 $(this).val('');
1232 }
1233 break;
1234 case 'text_to_image_background_image_url':
1235 if (
1236 typeof status.text_to_image_background_image_url !==
1237 'undefined'
1238 ) {
1239 $(this).val(status[field]);
1240 $(
1241 '.wpzinc-media-library-insert img',
1242 $(wpzinc_social.status_form)
1243 ).attr(
1244 'src',
1245 status.text_to_image_background_image_url
1246 );
1247 } else {
1248 $(this).val('');
1249 $(
1250 '.wpzinc-media-library-insert img',
1251 $(wpzinc_social.status_form)
1252 ).attr('src', '');
1253 }
1254 break;
1255
1256 /**
1257 * Conditions: Custom Fields
1258 */
1259 case 'custom_fields[key][]':
1260 // Display Custom Field Rows.
1261 for (const custom_field_index in status.custom_fields) {
1262 $(
1263 'input[name="' +
1264 wpzinc_social.plugin_name +
1265 '_custom_fields[key][]"]',
1266 $(wpzinc_social.status_form)
1267 )
1268 .last()
1269 .val(
1270 status.custom_fields[custom_field_index].key
1271 );
1272 $(
1273 'select[name="' +
1274 wpzinc_social.plugin_name +
1275 '_custom_fields[compare][]"]',
1276 $(wpzinc_social.status_form)
1277 )
1278 .last()
1279 .val(
1280 status.custom_fields[custom_field_index]
1281 .compare
1282 );
1283 $(
1284 'input[name="' +
1285 wpzinc_social.plugin_name +
1286 '_custom_fields[value][]"]',
1287 $(wpzinc_social.status_form)
1288 )
1289 .last()
1290 .val(
1291 status.custom_fields[custom_field_index]
1292 .value
1293 );
1294
1295 // Add New Table Row for the next Custom Field Condition, if there are additional
1296 // Custom Field Conditions to display.
1297 wpzinc_table_row_add(
1298 'custom-field',
1299 $(this).closest('table')
1300 );
1301 }
1302 break;
1303 case 'custom_fields[compare][]':
1304 case 'custom_fields[value][]':
1305 // Ignore, as we've already populated the Custom Field Conditions above.
1306 break;
1307
1308 /**
1309 * Authors
1310 */
1311 case 'authors':
1312 if (!status[field]) {
1313 break;
1314 }
1315
1316 $('input[name="' + $(this).attr('name') + '"]').val(
1317 status[field].join(',')
1318 );
1319 break;
1320 case 'authors_compare':
1321 if (!status[field]) {
1322 break;
1323 }
1324
1325 $('select[name="' + $(this).attr('name') + '"]').val(
1326 status[field]
1327 );
1328 break;
1329
1330 /**
1331 * Authors Roles
1332 */
1333 case 'authors_roles':
1334 if (!status[field]) {
1335 break;
1336 }
1337
1338 $('input[name="' + $(this).attr('name') + '"]').val(
1339 status[field].join(',')
1340 );
1341 break;
1342 case 'authors_roles_compare':
1343 if (!status[field]) {
1344 break;
1345 }
1346
1347 $('select[name="' + $(this).attr('name') + '"]').val(
1348 status[field]
1349 );
1350 break;
1351
1352 /**
1353 * Conditions: Custom Fields
1354 */
1355 case 'authors_custom_fields[key][]':
1356 // Display Custom Field Rows.
1357 for (const authors_custom_field_index in status.authors_custom_fields) {
1358 $(
1359 'input[name="' +
1360 wpzinc_social.plugin_name +
1361 '_authors_custom_fields[key][]"]',
1362 $(wpzinc_social.status_form)
1363 )
1364 .last()
1365 .val(
1366 status.authors_custom_fields[
1367 authors_custom_field_index
1368 ].key
1369 );
1370 $(
1371 'select[name="' +
1372 wpzinc_social.plugin_name +
1373 '_authors_custom_fields[compare][]"]',
1374 $(wpzinc_social.status_form)
1375 )
1376 .last()
1377 .val(
1378 status.authors_custom_fields[
1379 authors_custom_field_index
1380 ].compare
1381 );
1382 $(
1383 'input[name="' +
1384 wpzinc_social.plugin_name +
1385 '_authors_custom_fields[value][]"]',
1386 $(wpzinc_social.status_form)
1387 )
1388 .last()
1389 .val(
1390 status.authors_custom_fields[
1391 authors_custom_field_index
1392 ].value
1393 );
1394
1395 // Add New Table Row for the next Custom Field Condition, if there are additional
1396 // Custom Field Conditions to display.
1397 wpzinc_table_row_add(
1398 'authors-custom-field',
1399 $(this).closest('table')
1400 );
1401 }
1402 break;
1403 case 'authors_custom_fields[compare][]':
1404 case 'authors_custom_fields[value][]':
1405 // Ignore, as we've already populated the Custom Field Conditions above.
1406 break;
1407
1408 default:
1409 /**
1410 * Conditions: Taxonomy Conditions
1411 */
1412 const taxonomy = field.match(/conditions\[([^)]+)\]/);
1413 if (taxonomy) {
1414 if (
1415 typeof status.conditions[taxonomy[1]] !==
1416 typeof undefined
1417 ) {
1418 $(this).val(status.conditions[taxonomy[1]]);
1419 }
1420 break;
1421 }
1422
1423 /**
1424 * Conditions: Terms
1425 */
1426 const term = field.match(/terms\[([^)]+)\]/);
1427 if (term) {
1428 if (
1429 typeof status.terms[term[1]] !==
1430 typeof undefined
1431 ) {
1432 $(this).val(status.terms[term[1]].join(','));
1433 }
1434 break;
1435 }
1436
1437 /**
1438 * Array fields.
1439 */
1440 const matches = field.match(/(.*?)\[(.*?)\]/);
1441 if (matches !== null) {
1442 $(this).val(status[matches[1]][matches[2]]);
1443 break;
1444 }
1445
1446 /**
1447 * Standard fields.
1448 */
1449 $(this).val(status[field]);
1450 break;
1451 }
1452 }
1453 );
1454
1455 // Add the profile id, action and status index to the form.
1456 $(wpzinc_social.status_form)
1457 .data('profile-id', profile_id)
1458 .attr('data-profile-id', profile_id);
1459 $(wpzinc_social.status_form)
1460 .data('action', action)
1461 .attr('data-action', action);
1462 $(wpzinc_social.status_form)
1463 .data('status-index', status_index)
1464 .attr('data-status-index', status_index);
1465
1466 // Re-initialize any conditionals for e.g. Media Library image selection.
1467 $('input, select', $(wpzinc_social.status_form)).conditional();
1468 })(jQuery);
1469 }
1470
1471 /**
1472 * Displays the status form
1473 *
1474 * @since 4.4.0
1475 *
1476 * @param {string} profile_id Profile ID.
1477 * @param {string} action Action (publish,update,repost,bulk_publish).
1478 * @param {number} status_index Zero based index of this status relative to all statuses for the Profile ID and Action.
1479 */
1480 function wpZincSocialDisplayStatusForm(profile_id, action, status_index) {
1481 (function ($) {
1482 // Get row.
1483 const row = $(
1484 'div.statuses[data-profile-id="' +
1485 profile_id +
1486 '"][data-action="' +
1487 action +
1488 '"] tr[data-status-index="' +
1489 status_index +
1490 '"]'
1491 ),
1492 status_form_container_row = $(
1493 'div.statuses[data-profile-id="' +
1494 profile_id +
1495 '"][data-action="' +
1496 action +
1497 '"] tr.status-form-container'
1498 );
1499
1500 // Move status form inside edit form row.
1501 $('td', status_form_container_row).append(
1502 $(wpzinc_social.status_form).removeClass('hidden')
1503 );
1504
1505 // Move edit form row to immediately below the status row we're editing.
1506 $(row).after($(status_form_container_row).removeClass('hidden'));
1507 })(jQuery);
1508 }
1509
1510 /**
1511 * Saves the contents of the status form, and then hides the status form
1512 *
1513 * @since 4.4.0
1514 */
1515 function wpZincSocialSaveAndHideStatusForm() {
1516 (function ($) {
1517 // If the status form is visible, save its values now.
1518 if ($('div.statuses div.wpzinc-social-status-form').length > 0) {
1519 wpZincSocialUpdateStatus(
1520 $(
1521 'div.statuses tr.status-form-container div.wpzinc-social-status-form'
1522 ).data('profile-id'),
1523 $(
1524 'div.statuses tr.status-form-container div.wpzinc-social-status-form'
1525 ).data('action'),
1526 $(
1527 'div.statuses tr.status-form-container div.wpzinc-social-status-form'
1528 ).data('status-index')
1529 );
1530 }
1531
1532 // Reset Profile ID, Action and Status on Form.
1533 $(wpzinc_social.status_form)
1534 .data('profile-id', '')
1535 .attr('data-profile-id', '');
1536 $(wpzinc_social.status_form).data('action', '').attr('data-action', '');
1537 $(wpzinc_social.status_form)
1538 .data('status-index', '')
1539 .attr('data-status-index', '');
1540
1541 // Move form into container.
1542 $(wpzinc_social.status_form_container).append(
1543 $(wpzinc_social.status_form)
1544 );
1545 })(jQuery);
1546 }
1547
1548 /**
1549 * Clears all values from the status form
1550 *
1551 * @since 4.4.0
1552 */
1553 function wpZincSocialClearStatusForm() {
1554 (function ($) {
1555 // Clear all values.
1556 $('input, select, textarea', $(wpzinc_social.status_form)).each(
1557 function () {
1558 $(this).val('');
1559 }
1560 );
1561
1562 // Remove Custom Field Condition Rows.
1563 $(
1564 'tr.custom-field:not(.hide-delete-button)',
1565 $(wpzinc_social.status_form)
1566 ).each(function () {
1567 $(this).remove();
1568 });
1569
1570 // Remove Author Custom Field Condition Rows.
1571 $(
1572 'tr.authors-custom-field:not(.hide-delete-button)',
1573 $(wpzinc_social.status_form)
1574 ).each(function () {
1575 $(this).remove();
1576 });
1577 })(jQuery);
1578 }
1579
1580 /**
1581 * Returns a statuses object that can be saved against a Post Type
1582 * based on the current UI.
1583 *
1584 * @since 4.4.0
1585 */
1586 function wpZincSocialGetStatuses() {
1587 const statuses = {};
1588
1589 (function ($) {
1590 // Iterate through each Profile.
1591 $('li.wpzinc-nav-tab a').each(function () {
1592 const profile = $(this).attr('href').split('#profile-').pop();
1593
1594 if (profile === 'default') {
1595 statuses[profile] = {};
1596 } else {
1597 statuses[profile] = {
1598 enabled: $(
1599 'input[name="' +
1600 wpzinc_social.plugin_name +
1601 '[' +
1602 profile +
1603 '][enabled]"]'
1604 ).is(':checked'),
1605 };
1606
1607 // Determine override value, which can be in a checkbox (if the user can choose) or a hidden field (if we require override
1608 // for e.g. Pinterest).
1609 if (
1610 $(
1611 'input[type="checkbox"][name="' +
1612 wpzinc_social.plugin_name +
1613 '[' +
1614 profile +
1615 '][override]"]'
1616 ).length > 0
1617 ) {
1618 statuses[profile].override = $(
1619 'input[type="checkbox"][name="' +
1620 wpzinc_social.plugin_name +
1621 '[' +
1622 profile +
1623 '][override]"]'
1624 ).is(':checked');
1625 } else {
1626 statuses[profile].override =
1627 $(
1628 'input[type="hidden"][name="' +
1629 wpzinc_social.plugin_name +
1630 '[' +
1631 profile +
1632 '][override]"]'
1633 ).val() === '1' ||
1634 $(
1635 'input[type="hidden"][name="' +
1636 wpzinc_social.plugin_name +
1637 '[' +
1638 profile +
1639 '][override]"]'
1640 ).val() === 1
1641 ? true
1642 : false;
1643 }
1644 }
1645
1646 // Iterate through each Profile Action.
1647 $('li.wpzinc-nav-tab-horizontal a', '#profile-' + profile).each(
1648 function () {
1649 const action = $(this)
1650 .attr('href')
1651 .split('#profile-' + profile + '-')
1652 .pop();
1653
1654 statuses[profile][action] = {
1655 enabled: $(
1656 'input[name="' +
1657 wpzinc_social.plugin_name +
1658 '[' +
1659 profile +
1660 '][' +
1661 action +
1662 '][enabled]"]'
1663 ).is(':checked'),
1664 status: [],
1665 };
1666
1667 // Fetch statuses for the Profile and Action.
1668 $('tr.status', '#profile-' + profile + '-' + action).each(
1669 function () {
1670 statuses[profile][action].status.push(
1671 JSON.parse($(this).attr('data-status'))
1672 );
1673 }
1674 );
1675 }
1676 );
1677 });
1678 })(jQuery);
1679
1680 // Return.
1681 return statuses;
1682 }
1683
1684 /**
1685 * Populates a hidden field with a JSON string of all statuses and their settings
1686 * for the Post Type
1687 *
1688 * @since 4.4.0
1689 */
1690 function wpZincSocialUpdateStatuses() {
1691 let statuses;
1692
1693 (function ($) {
1694 // Get statuses.
1695 statuses = wpZincSocialGetStatuses();
1696
1697 // Update hidden field.
1698 $(
1699 'input[name="' +
1700 wpzinc_social.plugin_name +
1701 '[statuses]"][type="hidden"]'
1702 ).val(JSON.stringify(statuses));
1703 })(jQuery);
1704
1705 // Return statuses.
1706 return statuses;
1707 }
1708
1709 /**
1710 * Saves all statuses and their settings for the Post Type
1711 *
1712 * @since 4.4.0
1713 *
1714 * @param {string} post_type Post Type
1715 * @param {string} tab Tab (auth, profiles-error, profiles-missing, post-type-error, post-type-missing, post-type-enabled, post-type-disabled).
1716 */
1717 function wpZincSocialSaveStatuses(post_type, tab) {
1718 let statuses;
1719
1720 (function ($) {
1721 // Get statuses.
1722 statuses = wpZincSocialGetStatuses();
1723
1724 // Show modal and overlay.
1725 wpzinc_modal_open(wpzinc_social.save_statuses_modal.title, '');
1726
1727 // Send via AJAX.
1728 $.ajax({
1729 url: ajaxurl,
1730 type: 'POST',
1731 async: true,
1732 data: {
1733 action: wpzinc_social.save_statuses_action,
1734 nonce: wpzinc_social.save_statuses_nonce,
1735 post_type,
1736 statuses: JSON.stringify(statuses),
1737 },
1738 error(xhr) {
1739 wpzinc_modal_show_error_message_and_exit(
1740 'wpZincSocialSaveStatuses(): error: ' +
1741 xhr.status +
1742 ' ' +
1743 xhr.statusText
1744 );
1745 },
1746 success(result) {
1747 if (!result.success) {
1748 wpzinc_modal_show_error_message_and_exit(result.data);
1749 }
1750
1751 // Depending on whether settings are enabled for this Post Type, show/hide notices and ticks.
1752 if (tab.length) {
1753 if (result.data.post_type_enabled) {
1754 $(tab).addClass('enabled');
1755 $('.notice-warning').hide();
1756 } else {
1757 $(tab).removeClass('enabled');
1758 $('.notice-warning').show();
1759 }
1760 }
1761
1762 // Show success message and close.
1763 wpzinc_modal_show_success_and_exit(
1764 wpzinc_social.save_statuses_modal.title_success
1765 );
1766 },
1767 });
1768 })(jQuery);
1769 }
1770
1771 /**
1772 * Saves all statuses and their settings for the Post
1773 *
1774 * @since 4.4.0
1775 *
1776 * @param {number} post_id Post ID.
1777 * @param {number} override Override Setting.
1778 * @param {number} featured_image Featured Image.
1779 * @param {Array} additional_images Additonal Images.
1780 */
1781 function wpZincSocialSavePostStatuses(
1782 post_id,
1783 override,
1784 featured_image,
1785 additional_images
1786 ) {
1787 let statuses;
1788
1789 (function ($) {
1790 // Get statuses.
1791 statuses = wpZincSocialGetStatuses();
1792
1793 // Show modal and overlay.
1794 wpzinc_modal_open(wpzinc_social.save_statuses_modal.title, '');
1795
1796 // Send via AJAX.
1797 $.ajax({
1798 url: ajaxurl,
1799 type: 'POST',
1800 async: true,
1801 data: {
1802 action: wpzinc_social.save_statuses_action,
1803 nonce: wpzinc_social.save_statuses_nonce,
1804 post_id,
1805 override,
1806 featured_image,
1807 additional_images,
1808 statuses: JSON.stringify(statuses),
1809 },
1810 error() {
1811 // Close modal and overlay.
1812 wpzinc_modal_close();
1813 },
1814 success(result) {
1815 if (!result.success) {
1816 wpzinc_modal_show_error_message_and_exit(result.data);
1817 }
1818
1819 // Show success message and close.
1820 wpzinc_modal_show_success_and_exit(
1821 wpzinc_social.save_statuses_modal.title_success
1822 );
1823 },
1824 });
1825 })(jQuery);
1826 }
1827
1828 let wpZincSocialCharacterCounting = false;
1829
1830 /**
1831 * Character Count
1832 *
1833 * @since 3.9.6
1834 *
1835 * @param {string} textarea Textarea to count characters in.
1836 */
1837 function wpZincSocialCharacterCount(textarea) {
1838 (function ($) {
1839 // If we're currently running an AJAX request, don't run another one.
1840 if (wpZincSocialCharacterCounting) {
1841 return;
1842 }
1843
1844 // Set a flag so we know we're performing an AJAX request.
1845 wpZincSocialCharacterCounting = true;
1846
1847 // Send an AJAX request to fetch the parsed statuses and character counts for each status.
1848 $.post(
1849 wpzinc_social.ajax,
1850 {
1851 action: wpzinc_social.character_count_action,
1852 post_id: wpzinc_social.post_id,
1853 status: $(textarea).val(),
1854 nonce: wpzinc_social.character_count_nonce,
1855 },
1856 function (response) {
1857 $('span.character-count', $(textarea).parent()).text(
1858 response.data.character_count
1859 );
1860
1861 // Reset the flag after a few seconds, so we don't flood the server with requests.
1862 setTimeout(function () {
1863 wpZincSocialCharacterCounting = false;
1864 }, 3000);
1865 }
1866 );
1867 })(jQuery);
1868 }
1869
1870 /**
1871 * Enables the dialog to confirm the user wants to navigate away from the current screen,
1872 * as settings haven't been saved
1873 *
1874 * @since 4.5.5
1875 */
1876 function wpZincSocialEnableNotSavedPrompt() {
1877 // Don't do anything if we're not on the Settings screen.
1878 // This prevents the prompt wrongly displaying on the Post Edit screen.
1879 if (!wpzinc_social.prompt_unsaved_changes) {
1880 return;
1881 }
1882
1883 window.onbeforeunload = function () {
1884 return true;
1885 };
1886 }
1887
1888 /**
1889 * Disables the dialog to confirm the user wants to navigate away from the current screen,
1890 * as settings haven't been saved.
1891 *
1892 * @since 4.5.5
1893 */
1894 function wpZincSocialDisableNotSavedPrompt() {
1895 window.onbeforeunload = null;
1896 }
1897
1898 /**
1899 * Bind DOM Event Listeners to perform status tasks
1900 */
1901 jQuery(document).ready(function ($) {
1902 // Tags dropdown.
1903 wpZincSocialInitTags();
1904
1905 // Status sections.
1906 $(wpzinc_social.status_form).on(
1907 'change.' + wpzinc_social.status_form,
1908 'select.post_type',
1909 function () {
1910 wpZincSocialUpdateStatusSections();
1911 }
1912 );
1913
1914 // Schedule dropdown.
1915 $(wpzinc_social.status_form).on(
1916 'change.' + wpzinc_social.status_form,
1917 'select.schedule',
1918 function () {
1919 wpZincSocialUpdateScheduleOptions(
1920 $(this).closest('div.statuses').data('action')
1921 );
1922 }
1923 );
1924
1925 // Image dropdown.
1926 $(wpzinc_social.status_form).on(
1927 'change.' + wpzinc_social.status_form,
1928 'select.image',
1929 function () {
1930 wpZincSocialUpdateImageOptions();
1931 }
1932 );
1933
1934 // Google Business Profile Post Type.
1935 $(wpzinc_social.status_form).on(
1936 'change.' + wpzinc_social.status_form,
1937 'select#googlebusiness_post_type',
1938 function () {
1939 wpZincSocialUpdateGoogleBusinessOptions();
1940 }
1941 );
1942
1943 /**
1944 * Enable/Disable Profile or Action
1945 */
1946 $('input.enable', $('#profiles-container')).on('change', function () {
1947 // Get Tab related to this checkbox and the checkbox's Enabled state.
1948 const tab_href = $(this).data('tab'),
1949 enabled = $(this).prop('checked');
1950
1951 if (enabled) {
1952 $('a[href="#' + tab_href + '"]').addClass('enabled');
1953 } else {
1954 $('a[href="#' + tab_href + '"]').removeClass('enabled');
1955 }
1956
1957 wpZincSocialSaveAndHideStatusForm();
1958
1959 wpZincSocialClearStatusForm();
1960
1961 wpZincSocialUpdateStatuses();
1962
1963 wpZincSocialEnableNotSavedPrompt();
1964 });
1965
1966 /**
1967 * Enable/Disable Override Defaults
1968 */
1969 $('input.override', $('#profiles-container')).on('change', function () {
1970 wpZincSocialSaveAndHideStatusForm();
1971
1972 wpZincSocialClearStatusForm();
1973
1974 wpZincSocialUpdateStatuses();
1975
1976 wpZincSocialEnableNotSavedPrompt();
1977 });
1978
1979 /**
1980 * Tab click
1981 */
1982 $('.wpzinc-js-tabs').on('click', function () {
1983 wpZincSocialSaveAndHideStatusForm();
1984
1985 wpZincSocialClearStatusForm();
1986 });
1987
1988 /**
1989 * Add Status Update
1990 */
1991 $('#profiles-container').on('click', 'a.button.add-status', function (e) {
1992 e.preventDefault();
1993
1994 wpZincSocialSaveAndHideStatusForm();
1995
1996 wpZincSocialClearStatusForm();
1997
1998 wpZincSocialAddStatus(
1999 $(this).closest('div.statuses').data('profile-id'),
2000 $(this).closest('div.statuses').data('action')
2001 );
2002
2003 wpZincSocialEnableNotSavedPrompt();
2004 });
2005
2006 /**
2007 * Edit Status Update
2008 */
2009 $('#profiles-container').on('click', 'a.edit-status', function (e) {
2010 e.preventDefault();
2011
2012 wpZincSocialSaveAndHideStatusForm();
2013
2014 wpZincSocialClearStatusForm();
2015
2016 wpZincSocialEditStatus(
2017 $(this).closest('div.statuses').data('profile-id'),
2018 $(this).closest('div.statuses').data('profile'),
2019 $(this).closest('div.statuses').data('action'),
2020 $(this).closest('tr').data('status-index'),
2021 JSON.parse($(this).closest('tr').attr('data-status'))
2022 );
2023
2024 wpZincSocialEnableNotSavedPrompt();
2025 });
2026
2027 /**
2028 * Editing Status Update
2029 */
2030 $(wpzinc_social.status_form).on(
2031 'change',
2032 'input, select, textarea',
2033 function () {
2034 wpZincSocialUpdateStatus(
2035 $(wpzinc_social.status_form).data('profile-id'),
2036 $(wpzinc_social.status_form).data('action'),
2037 $(wpzinc_social.status_form).data('status-index')
2038 );
2039
2040 wpZincSocialEnableNotSavedPrompt();
2041 }
2042 );
2043
2044 $('body').on('wpzinc-media-library-attachment-added', function () {
2045 // Ignore Media Library events outside of the status form.
2046 if (
2047 typeof $(wpzinc_social.status_form).data('profile-id') ===
2048 'undefined'
2049 ) {
2050 return;
2051 }
2052
2053 wpZincSocialUpdateStatus(
2054 $(wpzinc_social.status_form).data('profile-id'),
2055 $(wpzinc_social.status_form).data('action'),
2056 $(wpzinc_social.status_form).data('status-index')
2057 );
2058
2059 wpZincSocialEnableNotSavedPrompt();
2060 });
2061
2062 $('body').on('wpzinc-table-row-delete', function () {
2063 wpZincSocialUpdateStatus(
2064 $(wpzinc_social.status_form).data('profile-id'),
2065 $(wpzinc_social.status_form).data('action'),
2066 $(wpzinc_social.status_form).data('status-index')
2067 );
2068
2069 wpZincSocialEnableNotSavedPrompt();
2070 });
2071
2072 /**
2073 * Delete Status Update
2074 */
2075 $('#profiles-container').on('click', 'a.delete-status', function (e) {
2076 e.preventDefault();
2077
2078 wpZincSocialSaveAndHideStatusForm();
2079
2080 wpZincSocialClearStatusForm();
2081
2082 wpZincSocialDeleteStatus(
2083 $(this).closest('div.statuses').data('profile-id'),
2084 $(this).closest('div.statuses').data('action'),
2085 $(this).closest('tr').data('status-index')
2086 );
2087
2088 wpZincSocialEnableNotSavedPrompt();
2089 });
2090
2091 /**
2092 * Reorder Status Updates
2093 */
2094 if ($('#profiles-container div.statuses').length > 0) {
2095 $('#profiles-container div.statuses').sortable({
2096 containment: 'parent',
2097 items: '.sortable',
2098 stop(e, ui) {
2099 // Get status and container.
2100 const status = $(ui.item),
2101 statuses_container = $(status).closest('div.statuses');
2102
2103 // Reindex statuses.
2104 wpZincSocialReindexStatuses($(statuses_container));
2105
2106 // Populate hidden field with all statuses' data.
2107 wpZincSocialUpdateStatuses();
2108
2109 wpZincSocialEnableNotSavedPrompt();
2110 },
2111 });
2112 }
2113
2114 /**
2115 * Force focus on inputs, so they can be accessed on mobile.
2116 * For some reason using jQuery UI sortable prevents us accessing textareas on mobile
2117 * See http://bugs.jqueryui.com/ticket/4429
2118 */
2119 $('#profiles-container div.statuses').bind(
2120 'click.sortable mousedown.sortable',
2121 function (e) {
2122 e.target.focus();
2123 }
2124 );
2125
2126 /**
2127 * Character Count Events
2128 *
2129 * @since 3.0.0
2130 */
2131 if (wpzinc_social.post_id > 0) {
2132 $('textarea.message', $(wpzinc_social.status_form)).on(
2133 'keyup change',
2134 function () {
2135 wpZincSocialCharacterCount(this);
2136 }
2137 );
2138 }
2139
2140 /**
2141 * Plugin Settings: Save Post Type Statuses via AJAX
2142 */
2143 $('form.wpzinc-social').on('submit', function (e) {
2144 // Don't submit form.
2145 e.preventDefault();
2146
2147 // Disable the not saved prompt, as we're about to save.
2148 wpZincSocialDisableNotSavedPrompt();
2149
2150 // Populate hidden field with all statuses' data.
2151 wpZincSocialUpdateStatuses();
2152
2153 // Save Post Type statuses.
2154 wpZincSocialSaveStatuses(
2155 wpzinc_social.post_type,
2156 $(
2157 'h2.nav-tab-wrapper a[data-post-type="' +
2158 wpzinc_social.post_type +
2159 '"]'
2160 )
2161 );
2162 });
2163
2164 /**
2165 * Post Settings: Save Post Statuses via AJAX
2166 */
2167 $('button.' + wpzinc_social.plugin_name + '-save-post-statuses').on(
2168 'click',
2169 function (e) {
2170 // Don't submit form.
2171 e.preventDefault();
2172
2173 // Disable the not saved prompt, as we're about to save.
2174 wpZincSocialDisableNotSavedPrompt();
2175
2176 // Populate hidden field with all statuses' data.
2177 wpZincSocialUpdateStatuses();
2178
2179 // Get Additional Images.
2180 const additional_images = [];
2181 for (i = 0; i <= 10; i++) {
2182 if (
2183 !$(
2184 'input[name="' +
2185 wpzinc_social.plugin_name +
2186 '[additional_images][' +
2187 i +
2188 ']"]'
2189 ).length
2190 ) {
2191 continue;
2192 }
2193
2194 additional_images.push(
2195 $(
2196 'input[name="' +
2197 wpzinc_social.plugin_name +
2198 '[additional_images][' +
2199 i +
2200 ']"]'
2201 ).val()
2202 );
2203 }
2204
2205 // Save Post statuses.
2206 wpZincSocialSavePostStatuses(
2207 wpzinc_social.post_id,
2208 $(
2209 'select[name="' + wpzinc_social.plugin_name + '[override]"]'
2210 ).val(),
2211 $(
2212 'input[name="' +
2213 wpzinc_social.plugin_name +
2214 '[featured_image]"]'
2215 ).val(),
2216 additional_images
2217 );
2218 }
2219 );
2220 });
2221