PluginProbe ʕ •ᴥ•ʔ
Strong Testimonials / 3.3.2
Strong Testimonials v3.3.2
3.3.2 3.3.1 trunk 1.0.1 2.30.9 2.31.10 2.32 2.32.1 2.32.2 2.32.3 2.32.4 2.33 2.34 2.35 2.36 2.37 2.38 2.38.1 2.39 2.39.1 2.39.2 2.39.3 2.40.0 2.40.1 2.40.2 2.40.3 2.40.4 2.40.5 2.40.6 2.40.7 2.41.0 2.41.1 2.50.0 2.50.1 2.50.2 2.50.3 2.50.4 2.51.0 2.51.1 2.51.2 2.51.3 2.51.4 2.51.5 2.51.6 2.51.7 2.51.8 2.51.9 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.20 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.17 3.2.18 3.2.19 3.2.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0
strong-testimonials / admin / js / admin-fields.js
strong-testimonials / admin / js Last commit date
lib 1 year ago admin-fields.js 1 year ago admin-form.js 1 year ago admin-global.js 1 year ago admin-order.js 1 year ago custom-spinner.js 1 year ago help.js 1 year ago rating-edit.js 1 year ago selectize.js 1 year ago st-uninstall.js 1 year ago strong-testimonials-elementor-editor.js 1 year ago view-category-filter.js 1 year ago views.js 1 month ago
admin-fields.js
606 lines
1 /**
2 * Strong Testimonials Custom Fields Editor
3 *
4 * @namespace wpmtstAdmin
5 * @namespace wpmtstAdmin.newField
6 */
7
8 // Function to get the Max value in Array
9 Array.max = function (array) {
10 return Math.max.apply(Math, array);
11 };
12
13 // Convert "A String" to "a_string"
14 function sanitizeName(label) {
15 return label.trim().replace(/\W/g, " ").replace(/\s+/g, "_").toLowerCase();
16 }
17
18 (function ($) {
19
20 /**
21 * If open, scroll field into view.
22 * If closed, scroll all the way up.
23 *
24 * @returns {jQuery}
25 */
26 $.fn.scrollUp = function () {
27 var containerOffset;
28 this.each(function () {
29 containerOffset = 0;
30 if ($(this).hasClass("open")) {
31 containerOffset = parseInt($(this).offset().top) - 72;
32 }
33 $("html, body").animate({scrollTop: containerOffset}, 800);
34 });
35
36 return this;
37 };
38
39 /**
40 * Replace the field type selector with its value. Better than readonly.
41 *
42 * @returns {jQuery}
43 */
44 $.fn.replaceSelect = function () {
45 this.each(function () {
46 if ($(this).hasClass("open")) {
47 $(this).find("select.field-type").each(function (index, el) {
48 $(el).replaceWith(el.value);
49 });
50 }
51 });
52
53 return this;
54 }
55
56 /**
57 * Initialize
58 */
59 var catCount = 0;
60 getCatCount();
61
62 var $theForm = $("#wpmtst-custom-fields-form");
63 var $fieldList = $("#custom-field-list");
64
65 formPreview();
66 toggleCategoryFields();
67
68 /**
69 * Sortable
70 */
71 $fieldList.sortable({
72 placeholder: "sortable-placeholder",
73 forcePlaceholderSize: true,
74 handle: ".handle",
75 cursor: "move",
76 update: function (event, ui) {
77 dismissNotice();
78 formPreview();
79 }
80 });
81
82 /**
83 * ------------------------------------------------------------
84 * Events
85 * ------------------------------------------------------------
86 */
87
88 /**
89 * Any changes.
90 */
91 $theForm.on("change", "input", function () {
92 dismissNotice();
93 formPreview();
94 });
95
96 /**
97 * Disable buttons on submit.
98 * Thanks https://stackoverflow.com/a/25651260/51600
99 */
100 $theForm.on('submit', function(){
101 $('#field-group-actions').find('.button').each(function (index) {
102 // Create a disabled clone of the submit button
103 $(this).clone(false).removeAttr('id').prop('disabled', true).insertBefore($(this));
104 // Hide the actual submit button and move it to the beginning of the form
105 $(this).hide();
106 });
107 });
108
109 /**
110 * Save Changes
111 */
112 $('#submit-form').on('click',function(e){
113
114 // Validate field type
115 $("select.field-type").each(function (index) {
116 if ('none' === this.value) {
117 $(this).closest('tr').addClass('form-error');
118 $(this).parent().find('.form-error-text').show();
119 var $parent = $(this).closest("li");
120 if (!$parent.hasClass("open")) {
121 $parent.find("a.field").trigger('click');
122 }
123 $(this).trigger('focus');
124 e.preventDefault();
125 } else {
126 $(this).closest('tr').removeClass('form-error');
127 $(this).parent().find('.form-error-text').hide();
128 }
129 });
130
131 // Validate field name
132 $("input.field-name").each(function (index) {
133 if ('name' === $(this).val() || 'date' === $(this).val()) {
134 $(this).closest('tr').addClass('form-error');
135 $(this).parent().find('.field-name-help.important').addClass('form-error-text');
136 var $parent = $(this).closest("li");
137 if (!$parent.hasClass("open")) {
138 $parent.find("a.field").trigger('click');
139 }
140 $(this).trigger('focus');
141 e.preventDefault();
142 } else {
143 $(this).closest('tr').removeClass('form-error');
144 $(this).parent().find('.field-name-help.important').removeClass('form-error-text');
145 }
146 });
147
148 });
149
150 /**
151 * Cancel Changes
152 */
153 $('#reset').on('click',function(e){
154 $theForm.trigger('submit');
155 });
156
157 /**
158 * Restore Defaults
159 */
160 $('#restore-defaults').on('click',function(e){
161 if (confirm("Restore the default fields?")) {
162 $theForm.trigger('submit');
163 } else {
164 $(this).trigger("blur");
165 return false;
166 }
167 });
168
169 /**
170 * Prevent single click on handle from opening accordion
171 */
172 $fieldList.on("click", "span.handle", function (e) {
173 e.stopImmediatePropagation();
174 e.preventDefault();
175 });
176
177 /**
178 * Open/close
179 */
180 $fieldList.on("click", "span.link", function () {
181 toggleField($(this).closest("li"));
182 return false;
183 });
184
185 /**
186 * Validate field label
187 */
188 $fieldList.on("change blur", "input.field-label", function () {
189 var newLabel = $(this).val().trim();
190 // fill in blank label
191 if ('' === newLabel) {
192 newLabel = wpmtstAdmin.newField;
193 }
194 $(this).val(newLabel);
195
196 var $parent = $(this).closest("li");
197 var fieldIndex = $parent.index();
198
199 // update parent list item
200 $parent.find("a.field").html(newLabel);
201
202 // fill in blank field name
203 var $fieldName = $parent.find("input.field-name");
204 if ('new_field' === $fieldName.val()) {
205 $fieldName.val(getUniqueName(newLabel, fieldIndex)).trigger( 'change' );
206 }
207 });
208
209 /**
210 * Validate field name
211 */
212 $fieldList.on("change", "input.field-name", function () {
213 var fieldName = $(this).val();
214 var $parent = $(this).closest("li");
215 var fieldIndex = $parent.index();
216
217 if (fieldName) {
218 $(this).val(getUniqueName(fieldName, fieldIndex));
219 } else {
220 var fieldLabel = $(this).closest(".field-table").find(".field-label").val();
221 $(this).val(getUniqueName(fieldLabel, fieldIndex));
222 }
223
224 // Check new name, not initial value
225 if ('name' === $(this).val() || 'date' === $(this).val()) {
226 $(this).closest('tr').addClass('form-error');
227 $(this).parent().find('.field-name-help.important').addClass('form-error-text');
228 $(this).trigger('focus')
229 return false;
230 } else {
231 $(this).closest('tr').removeClass('form-error');
232 $(this).parent().find('.field-name-help.important').removeClass('form-error-text');
233 }
234 });
235
236 /**
237 * Delete field
238 */
239 $fieldList.on("click", ".delete-field", function () {
240 $(this).trigger("blur");
241 dismissNotice();
242 var thisField = $(this).closest("li");
243 var thisLabel = thisField.find(".field").text();
244 if (confirm('Delete "' + thisLabel + '"?')) {
245 thisField.fadeOut(function () {
246 $.when(thisField.remove()).then(function () {
247 formPreview();
248 toggleCategoryFields();
249 $("#add-field, #submit").prop("disabled", false);
250 })
251 });
252 }
253 });
254
255 /**
256 * Close field
257 */
258 $fieldList.on("click", "span.close-field a", function () {
259 toggleField($(this).closest("li"));
260 return false;
261 });
262
263 /**
264 * Add new field
265 */
266 $("#add-field").on('click', function () {
267 dismissNotice();
268 var keys = $fieldList.find("li").map(function () {
269 var key_id = $(this).attr("id");
270 return key_id.substr(key_id.lastIndexOf("-") + 1);
271 }).get();
272 var nextKey = Array.max(keys) + 1;
273
274 var data = {
275 'action': 'wpmtst_add_field',
276 'nextKey': nextKey,
277 'fieldClass': null,
278 'fieldType': null,
279 'security': wpmtstAdmin.ajax_nonce
280 };
281 $.get(ajaxurl, data, function (response) {
282 $("#add-field, #submit").attr("disabled", "disabled");
283
284 // create list item
285 var $li = $('<li id="field-' + nextKey + '" data-status="new">').append(response);
286
287 // hide elements until Type is selected
288 $li.find('.field-label-row').hide();
289 $li.find('.field-name-row').hide();
290 $li.find("span.close-field").hide();
291
292 // append to list
293 $.when($fieldList.append($li)).then(function () {
294 formPreview();
295 togglePostFields();
296 toggleCategoryFields();
297
298 // click it to open
299 $li.find("span.link").trigger('click');
300 });
301 });
302 });
303
304 /**
305 * Field type change
306 */
307 $fieldList.on("change", ".field-type", function (e) {
308 var fieldType = $(this).val();
309 var $table = $(this).closest("table");
310 var $parent = $(this).closest('li');
311
312 if ($parent.data('status') !== 'new') {
313 $table.find(".field-secondary, .field-admin-table").remove();
314 }
315
316 if ('none' === fieldType) {
317 $parent.find('.field-label-row').hide();
318 $parent.find('.field-name-row').hide();
319
320 // Hide "Close" link
321 $parent.find("span.close-field").hide();
322 $("#add-field, #submit").attr("disabled", "disabled");
323 return;
324 }
325 $parent.find('tr').removeClass('form-error');
326 $parent.find('.form-error-text').hide();
327
328 var key_id = $parent.attr("id");
329 var key = key_id.substr(key_id.lastIndexOf("-") + 1);
330
331 var $fieldLabel = $parent.find('input.field-label');
332 var $fieldName = $parent.find('input.field-name');
333 var fieldIndex = $parent.index();
334
335 // get type of field from its optgroup
336 var fieldOption = $(this).find("option[value='" + fieldType + "']");
337 var fieldClass = fieldOption.closest("optgroup").attr("class");
338
339 switch (fieldClass) {
340
341 case 'post':
342 $parent.find('.field-label-row').show();
343 $parent.find('.field-name-row').show();
344
345 // Force values if selecting a Post field.
346 if (fieldType === 'post_title') {
347 $fieldLabel.val('Testimonial Title');
348 $fieldName.val('post_title').attr('disabled', 'disabled');
349 }
350 else if (fieldType === 'featured_image') {
351 $fieldLabel.val('Photo');
352 $fieldName.val('featured_image').attr('disabled', 'disabled');
353 }
354 else if (fieldType === 'post_content') {
355 $fieldLabel.val('Testimonial');
356 $fieldName.val('post_content').attr('disabled', 'disabled');
357 }
358 // move value to hidden input
359 $fieldName.after('<input type="hidden" name="' + $fieldName.attr("name") + '" value="' + $fieldName.val() + '" />');
360 // hide help message
361 $parent.find(".field-name-help").hide();
362 break;
363
364 case 'optional':
365 $parent.find('.field-label-row').show();
366 $parent.find('.field-name-row').show();
367
368 if ('category' === fieldType.split('-')[0]) {
369 $fieldName.val('category').attr('disabled', 'disabled');
370 // move value to hidden input
371 $fieldName.after('<input type="hidden" name="' + $fieldName.attr("name") + '" value="' + $fieldName.val() + '" />');
372 // hide help message
373 $parent.find(".field-name-help").hide();
374 }
375 var forceName = fieldOption.data('force-name');
376 if (forceName) {
377 $fieldName.val(forceName).attr('disabled', 'disabled');
378 // move value to hidden input
379 $fieldName.after('<input type="hidden" name="' + $fieldName.attr("name") + '" value="' + $fieldName.val() + '" />');
380 // hide help message
381 $parent.find(".field-name-help").hide();
382 }
383 $fieldLabel.val(wpmtstAdmin.newField).trigger('focus').trigger('select');
384 break;
385
386 default:
387 $parent.find('.field-label-row').show();
388 $parent.find('.field-name-row').show();
389
390 // TODO DRY
391 $fieldLabel.val(wpmtstAdmin.newField).trigger('focus').trigger('select');
392 $fieldName.val(getUniqueName($fieldLabel.val(), fieldIndex));
393 $fieldName.prop('disabled', false);
394 $parent.find(".field-name-help").show();
395 }
396
397 // secondary form fields
398 var data1 = {
399 'action': 'wpmtst_add_field_2',
400 'nextKey': key,
401 'fieldClass': fieldClass,
402 'fieldType': fieldType,
403 'security': wpmtstAdmin.ajax_nonce
404 };
405
406 var ajax1 = $.get(ajaxurl, data1, function (response) {
407 $table.append(response);
408 $( document ).trigger( "st-done-loading-secondary-fields", [ $table ] );
409 });
410
411
412 // admin-table field
413 var data2 = {
414 'action': 'wpmtst_add_field_4',
415 'nextKey': key,
416 'fieldClass': fieldClass,
417 'fieldType': fieldType,
418 'security': wpmtstAdmin.ajax_nonce
419 };
420
421 var ajax2 = ajax1.then(function () {
422 return $.get(ajaxurl, data2, function (response) {
423 $table.append(response);
424 });
425 });
426
427
428 // hidden inputs
429 var data3 = {
430 'action': 'wpmtst_add_field_3',
431 'nextKey': key,
432 'fieldClass': fieldClass,
433 'fieldType': fieldType,
434 'security': wpmtstAdmin.ajax_nonce
435 };
436
437 var ajax3 = ajax2.then(function () {
438 return $.get(ajaxurl, data3, function (response) {
439 $table.parent().append(response);
440 });
441 });
442
443 ajax3.done(function () {
444
445 formPreview();
446 $("#add-field, #submit").prop("disabled", false);
447
448 // Successfully added so show "Close" link
449 $("span.close-field").show();
450
451 $parent
452 // Reset temporary status
453 .removeData("status").removeAttr("data-status")
454 // update parent list item
455 .find(".custom-field-header a.field").html($fieldLabel.val()).end()
456 // update hidden [record_type] input
457 .find('input[name$="[record_type]"]').val(fieldClass);
458
459 });
460
461 });
462
463 /**
464 * ------------------------------------------------------------
465 * Functions
466 * ------------------------------------------------------------
467 */
468
469 function getCatCount() {
470 $.get(ajaxurl, {
471 'action': 'wpmtst_get_cat_count',
472 'security': wpmtstAdmin.ajax_nonce
473 },
474 function (response) {
475 catCount = parseInt(response);
476 });
477 }
478
479 // Preview
480 function formPreview() {
481 var formFields = $theForm.find("[name^='fields']");
482 if (!formFields.length) return;
483
484 var data = {
485 'action': 'wpmtst_get_form_preview',
486 'fields': formFields.serialize(),
487 'security': wpmtstAdmin.ajax_nonce
488 };
489
490 $.post(ajaxurl, data, function (response) {
491 var newDiv = $("<div></div>").hide().html(response)
492 $("#fields-editor-preview")
493 .children().first()
494 .after(newDiv)
495 .fadeOut(0, function () {
496 newDiv.show();
497 $(this).remove();
498 });
499 });
500 }
501
502 /*
503 * Disable any Post fields already in use.
504 *
505 * Doing this client-side so a Post field can be added
506 * but not saved before adding more fields;
507 * i.e. add multiple fields of either type without risk
508 * of duplicating single Post fields before clicking "Save".
509 */
510 function togglePostFields() {
511 $fieldList.find('input[name$="[record_type]"]').each(function () {
512 var $parent = $(this).closest("li");
513 var value = $(this).val();
514 if ("post" === value) {
515 var name = $parent.find(".field-name").val();
516 $fieldList.find("select.field-type.new").find('option[value="' + name + '"]').attr("disabled", "disabled");
517 }
518 });
519 }
520
521 // Only allow one category field
522 function toggleCategoryFields() {
523 var categoryInUse = false;
524
525 $fieldList.find('input[name$="[record_type]"]').each(function () {
526 var $parent = $(this).closest("li");
527 var value = $(this).val();
528 if ('optional' === value) {
529 var fieldType = $parent.find('input[name$="[input_type]"]').val();
530 if (!categoryInUse) {
531 categoryInUse = ( 'category' === fieldType.split('-')[0] );
532 }
533 }
534 });
535
536 var $options = $fieldList.find('option[value^="category"]');
537 if (categoryInUse) {
538 $options.each(function () {
539 var text = $(this).text();
540 $(this)
541 .attr("disabled", "disabled")
542 .text(text + ' ' + wpmtstAdmin.inUse)
543 .data('origText', text);
544 });
545 }
546 else if (0 === catCount) {
547 $options.each(function () {
548 var text = $(this).text();
549 $(this)
550 .attr("disabled", "disabled")
551 .text(text + ' ' + wpmtstAdmin.noneFound)
552 .data('origText', text);
553 });
554 } else {
555 $options.each(function () {
556 $(this)
557 .prop("disabled", false)
558 .text($(this).data('origText'));
559 });
560 }
561 }
562
563 // Actions on opening/closing the field
564 function toggleField($field) {
565 $field.replaceSelect()
566 .toggleClass("open")
567 .scrollUp()
568 .find("span.link")
569 .toggleClass("open")
570 .end()
571 .find(".custom-field")
572 .toggleClass("open")
573 .slideToggle()
574 .find(".first-field")
575 .trigger('focus');
576 }
577
578 // Build a unique name
579 function getUniqueName(fieldName, fieldIndex) {
580 fieldName = sanitizeName(fieldName);
581
582 // Get names of *other* fields
583 var names = $theForm.find("input.field-name").not(":eq(" + fieldIndex + ")").map(function () {
584 return this.value;
585 }).get();
586
587 names = names.filter(function (x) {
588 return (x !== (undefined || ''));
589 });
590
591 var uniqueName = fieldName;
592 var i = 2;
593
594 while ($.inArray(uniqueName, names) >= 1) {
595 uniqueName = fieldName + '_' + i++;
596 }
597 return uniqueName;
598 }
599
600 // Dismiss the "Fields saved" notice.
601 function dismissNotice() {
602 $('.wpmtst.notice').find(".notice-dismiss").trigger('click');
603 }
604
605 })(jQuery);
606